@accounter/client
Version:
Accounter client application
98 lines (92 loc) • 2.49 kB
text/typescript
import { Currency } from '../gql/graphql.js';
import { formatStringifyAmount } from './index.js';
export const FIAT_CURRENCIES: Currency[] = [
Currency.Ils,
Currency.Eur,
Currency.Usd,
Currency.Gbp,
Currency.Cad,
Currency.Jpy,
Currency.Aud,
Currency.Sek,
] as const;
export type CurrencyFormatter = Pick<Intl.NumberFormat, 'format'>;
export function getCurrencyFormatter(
currency: Currency,
options?: Omit<Intl.NumberFormatOptions, 'currency'>,
): CurrencyFormatter {
// Crypto currencies (e.g. USDC, ETH, GRT) are not valid ISO 4217 codes, so
// `Intl.NumberFormat` with `style: 'currency'` throws a RangeError. Fall back
// to decimal formatting and prepend the currency symbol for those.
if (!FIAT_CURRENCIES.includes(currency)) {
const decimalFormatter = new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
...options,
style: 'decimal',
});
return {
format: (value: number): string => {
// Place the minus sign before the symbol (e.g. `-USDC 1,234.50`) to
// match the standard financial notation used for fiat currencies.
const symbol = currencyCodeToSymbol(currency);
const formatted = decimalFormatter.format(Math.abs(value));
return value < 0 ? `-${symbol} ${formatted}` : `${symbol} ${formatted}`;
},
};
}
return new Intl.NumberFormat('en-US', {
style: 'currency',
...options,
currency,
});
}
export function currencyCodeToSymbol(currency_code: Currency): string {
let currencySymbol = '₪';
switch (currency_code) {
case 'USD': {
currencySymbol = '$';
break;
}
case 'EUR': {
currencySymbol = '€';
break;
}
case 'GBP': {
currencySymbol = '£';
break;
}
case 'CAD': {
currencySymbol = 'C$';
break;
}
case 'JPY': {
currencySymbol = '¥';
break;
}
case 'AUD': {
currencySymbol = 'A$';
break;
}
case 'SEK': {
currencySymbol = 'kr';
break;
}
case 'GRT': {
currencySymbol = 'GRT';
break;
}
case 'USDC': {
currencySymbol = 'USDC';
break;
}
case 'ETH': {
currencySymbol = 'ETH';
break;
}
}
return currencySymbol;
}
export function formatAmountWithCurrency(amount: number, currency: Currency, digits = 2): string {
return `${currencyCodeToSymbol(currency)} ${formatStringifyAmount(amount, digits)}`;
}