Spaces:
Running
Running
| import type { Severity, SeverityCounts } from "@/shared/types"; | |
| export function formatStars(n: number): string { | |
| if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1).replace(/\.0$/, "")}M`; | |
| if (n >= 1_000) return `${(n / 1_000).toFixed(1).replace(/\.0$/, "")}k`; | |
| return String(n); | |
| } | |
| export function formatRelativeTime(iso: string | null | undefined): string { | |
| if (!iso) return "—"; | |
| const then = new Date(iso).getTime(); | |
| if (Number.isNaN(then)) return "—"; | |
| const diffSec = Math.round((then - Date.now()) / 1000); | |
| const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" }); | |
| const abs = Math.abs(diffSec); | |
| if (abs < 60) return rtf.format(diffSec, "second"); | |
| const diffMin = Math.round(diffSec / 60); | |
| if (Math.abs(diffMin) < 60) return rtf.format(diffMin, "minute"); | |
| const diffHr = Math.round(diffMin / 60); | |
| if (Math.abs(diffHr) < 48) return rtf.format(diffHr, "hour"); | |
| const diffDay = Math.round(diffHr / 24); | |
| if (Math.abs(diffDay) < 60) return rtf.format(diffDay, "day"); | |
| const diffMo = Math.round(diffDay / 30); | |
| return rtf.format(diffMo, "month"); | |
| } | |
| export function formatDate(iso: string | null | undefined): string { | |
| if (!iso) return "—"; | |
| return new Date(iso).toLocaleDateString("en-US", { | |
| year: "numeric", | |
| month: "short", | |
| day: "numeric", | |
| }); | |
| } | |
| export function shortSha(sha: string | null | undefined): string { | |
| if (!sha) return "—"; | |
| return sha.slice(0, 7); | |
| } | |
| export function totalFindings(c: SeverityCounts): number { | |
| return c.critical + c.high + c.medium + c.low; | |
| } | |
| export const SEV_ORDER: Severity[] = ["critical", "high", "medium", "low"]; | |
| export function severityLabel(s: Severity): string { | |
| return s.charAt(0).toUpperCase() + s.slice(1); | |
| } | |