export function money(v: number | string | null | undefined, opts?: { sign?: boolean }): string { const n = typeof v === "string" ? Number(v) : v ?? 0; if (n === null || Number.isNaN(n)) return "—"; const f = n.toLocaleString("en-US", { style: "currency", currency: "USD", minimumFractionDigits: 2, maximumFractionDigits: 2, }); if (opts?.sign && n > 0) return `+${f}`; return f; } export function pct(v: number | string | null | undefined, digits = 2): string { const n = typeof v === "string" ? Number(v) : v ?? 0; if (Number.isNaN(n)) return "—"; return `${(n * 100).toFixed(digits)}%`; } export function num(v: number | string | null | undefined, digits = 2): string { const n = typeof v === "string" ? Number(v) : v ?? 0; if (Number.isNaN(n)) return "—"; return n.toLocaleString("en-US", { minimumFractionDigits: digits, maximumFractionDigits: digits, }); } export function timeAgo(iso: string): string { const t = new Date(iso).getTime(); if (!t) return "—"; const sec = Math.round((Date.now() - t) / 1000); if (sec < 60) return `${sec}s ago`; const min = Math.round(sec / 60); if (min < 60) return `${min}m ago`; const hr = Math.round(min / 60); if (hr < 24) return `${hr}h ago`; const day = Math.round(hr / 24); return `${day}d ago`; }