Files
caddy-proxy-manager/app/(dashboard)/certificates/components/RelativeTime.tsx
T
fuomag9 6ecd195073 redesign certificates page: tabs, drawers, relative expiry, status bar
- Split ACME / Imported / CA-mTLS into tabs with count badges
- Add clickable status summary bar (expired / expiring soon / healthy)
- Per-tab search filter by name and domain
- Replace accordion cards with DataTable for imported certs
- Slide-in Drawers (480 px) for add/edit imported and CA certs
- File upload + show/hide toggle for private key in ImportCertDrawer
- CaCertDrawer: Generate / Import PEM tabs for add, simple form for edit
- CA tab: expandable rows showing issued client certs inline
- RelativeTime component: "in 45 days" / "EXPIRED 3 days ago" with date tooltip
- Remove CreateCaCertDialog and EditCaCertDialog (replaced by CaCertDrawer)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 22:36:46 +01:00

58 lines
1.4 KiB
TypeScript

"use client";
import { Tooltip, Typography } from "@mui/material";
import type { CertExpiryStatus } from "../page";
function formatRelative(validTo: string): string {
const diff = new Date(validTo).getTime() - Date.now();
const absDiff = Math.abs(diff);
const days = Math.floor(absDiff / 86400000);
const hours = Math.floor(absDiff / 3600000);
if (diff < 0) {
if (days >= 1) return `EXPIRED ${days} day${days !== 1 ? "s" : ""} ago`;
return `EXPIRED ${hours} hour${hours !== 1 ? "s" : ""} ago`;
}
if (days >= 1) return `in ${days} day${days !== 1 ? "s" : ""}`;
return `in ${hours} hour${hours !== 1 ? "s" : ""}`;
}
function formatFull(validTo: string): string {
return new Date(validTo).toLocaleDateString(undefined, {
year: "numeric",
month: "short",
day: "numeric",
});
}
export function RelativeTime({
validTo,
status,
}: {
validTo: string | null;
status: CertExpiryStatus | null;
}) {
if (validTo === null || status === null) {
return (
<Typography variant="body2" color="text.secondary">
</Typography>
);
}
const color =
status === "expired"
? "error.main"
: status === "expiring_soon"
? "warning.main"
: "success.main";
return (
<Tooltip title={formatFull(validTo)}>
<Typography variant="body2" sx={{ color, fontWeight: 500, cursor: "default" }}>
{formatRelative(validTo)}
</Typography>
</Tooltip>
);
}