export function formatDate(value: string | Date | null | undefined): string { if (!value) return '—'; const d = typeof value === 'string' ? new Date(value) : value; return d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' }); } export function formatHours(minutes: number): string { const h = minutes / 60; return h >= 10 ? `${h.toFixed(0)}h` : `${h.toFixed(1)}h`; } export function formatMoney(amount: string | number | null | undefined): string { if (amount == null || amount === '') return '—'; const n = typeof amount === 'string' ? Number(amount) : amount; if (!Number.isFinite(n)) return '—'; return new Intl.NumberFormat(undefined, { style: 'currency', currency: 'USD' }).format(n); } export function formatBytes(bytes: number): string { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; } export function planLimitMessage(code: string | undefined, fallback = 'Action not allowed.'): string { switch (code) { case 'plan_limit_clients': return "You've hit your plan's client limit. Upgrade to add more."; case 'plan_limit_activeCases': return "You've hit your plan's active-case limit. Close a case or upgrade."; case 'plan_limit_invoicesPerMonth': return "You've hit your monthly invoice limit. Upgrade for unlimited invoicing."; case 'plan_limit_storageBytes': return "You've hit your storage limit. Delete files or upgrade."; default: return fallback; } }