6ecd195073
- 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>
58 lines
1.4 KiB
TypeScript
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>
|
|
);
|
|
}
|