/** * Format a date string or Date to a long readable date: "Jan 6, 2026" */ export function formatDate(value?: string | Date | null): string { if (!value) return "—" const date = value instanceof Date ? value : new Date(value) if (isNaN(date.getTime())) return "—" return date.toLocaleDateString(undefined, { year: "numeric", month: "short", day: "numeric" }) } /** * Format a date string or Date to date + time: "Jan 6, 2026, 2:30 PM" */ export function formatDateTime(value?: string | Date | null): string { if (!value) return "—" const date = value instanceof Date ? value : new Date(value) if (isNaN(date.getTime())) return "—" return date.toLocaleDateString(undefined, { year: "numeric", month: "short", day: "numeric", hour: "numeric", minute: "2-digit", }) } /** * Format a date string or Date to a short numeric date: "04/06/2026" */ export function formatDateShort(value?: string | Date | null): string { if (!value) return "—" const date = value instanceof Date ? value : new Date(value) if (isNaN(date.getTime())) return "—" return date.toLocaleDateString(undefined, { year: "numeric", month: "2-digit", day: "2-digit" }) } /** * Format a time string or Date to a readable time: "2:30 PM" */ export function formatTime(value?: string | Date | null): string { if (!value) return "—" const date = value instanceof Date ? value : new Date(value) if (isNaN(date.getTime())) return "—" return date.toLocaleTimeString(undefined, { hour: "numeric", minute: "2-digit" }) } /** * Format a snake_case or underscore-separated string to Title Case words. * e.g. "in_progress" → "In Progress" */ export function formatEnum(value?: string | null): string { if (!value) return "—" return value .split("_") .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) .join(" ") } /** * Format a number with locale-aware thousand separators. * e.g. 150000 → "150,000" */ export function formatNumber(value?: number | string | null): string { if (value == null || value === "") return "—" const num = typeof value === "string" ? Number(value) : value if (isNaN(num)) return "—" return num.toLocaleString() } /** * Format a numeric value as currency: "$1,500.00" */ export function formatCurrency( value?: number | string | null, currency = "USD", locale?: string, ): string { if (value == null || value === "") return "—" const num = typeof value === "string" ? Number(value) : value if (isNaN(num)) return "—" return new Intl.NumberFormat(locale, { style: "currency", currency }).format(num) }