// The one place PYG amounts are formatted for admin screens (cards, tables, // charts, modal previews). PYG has no decimals. Separators follow the UI // language: English 2,470,000 PYG, Spanish 2.470.000 PYG. Grouping is done by // hand so it does not depend on the browser's locale data. Components use the // useMoney() hook (lib/useMoney.ts) to bind these to the active language. export type MoneyLocale = 'en' | 'es'; const SEP: Record = { en: { group: ',', decimal: '.' }, es: { group: '.', decimal: ',' }, }; const sepFor = (locale: string) => SEP[locale === 'en' ? 'en' : 'es']; export function formatNumber(n: number, locale: string = 'es'): string { const sign = n < 0 ? '-' : ''; return sign + Math.abs(Math.round(n)).toString().replace(/\B(?=(\d{3})+(?!\d))/g, sepFor(locale).group); } export function formatPyg(n: number, locale: string = 'es'): string { return `${formatNumber(n, locale)} PYG`; } /** Axis labels: 2.470.000 -> 2,5M (es) / 2.5M (en); 850.000 -> 850k. */ export function formatPygShort(n: number, locale: string = 'es'): string { const abs = Math.abs(n); const sign = n < 0 ? '-' : ''; if (abs >= 1_000_000) { return `${sign}${(abs / 1_000_000).toFixed(abs >= 10_000_000 ? 0 : 1).replace('.', sepFor(locale).decimal)}M`; } if (abs >= 1_000) return `${sign}${Math.round(abs / 1_000)}k`; return `${sign}${abs}`; } /** Basis points as a percent string: 290 -> "2.9%" (en) / "2,9%" (es). */ export function formatPercent(bp: number, locale: string = 'es'): string { const v = Math.round(bp) / 100; return `${String(v).replace('.', sepFor(locale).decimal)}%`; }