/** * CurrencyDisplay * * Deterministic currency formatting for display. * Avoids Intl and toLocaleString to prevent SSR/hydration mismatches. */ export class CurrencyFormatter { /** * Formats an amount as currency (e.g., "$10.00" or "€1.000,00"). * Default currency is USD. */ static format(amount: number, currency: string = 'USD'): string { const symbol = currency === 'USD' ? '$' : currency === 'EUR' ? '€' : currency + ' '; const formattedAmount = amount.toFixed(2); // Add thousands separators const parts = formattedAmount.split('.'); // Use dot as thousands separator for EUR, comma for USD if (currency === 'EUR') { parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, '.'); return `${symbol}${parts[0]},${parts[1]}`; } else { parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); return `${symbol}${parts.join('.')}`; } } /** * Formats an amount as a compact currency (e.g., "$10" or "€1.000"). */ static formatCompact(amount: number, currency: string = 'USD'): string { const symbol = currency === 'USD' ? '$' : currency === 'EUR' ? '€' : currency + ' '; const roundedAmount = Math.round(amount); // Add thousands separators const formattedAmount = roundedAmount.toString(); // Use dot as thousands separator for EUR, comma for USD if (currency === 'EUR') { return `${symbol}${formattedAmount.replace(/\B(?=(\d{3})+(?!\d))/g, '.')}`; } else { return `${symbol}${formattedAmount.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}`; } } }