← back to Watches

config/currencies.js

181 lines

/**
 * Currency Configuration
 * Defines supported currencies for multi-currency price display
 */

export const CURRENCIES = {
  USD: {
    code: 'USD',
    symbol: '$',
    name: 'US Dollar',
    locale: 'en-US',
    decimals: 2,
    symbolPosition: 'before', // $100
    thousandSeparator: ',',
    decimalSeparator: '.',
    flag: '🇺🇸'
  },
  EUR: {
    code: 'EUR',
    symbol: '€',
    name: 'Euro',
    locale: 'de-DE',
    decimals: 2,
    symbolPosition: 'after', // 100€
    thousandSeparator: '.',
    decimalSeparator: ',',
    flag: '🇪🇺'
  },
  GBP: {
    code: 'GBP',
    symbol: '£',
    name: 'British Pound',
    locale: 'en-GB',
    decimals: 2,
    symbolPosition: 'before', // £100
    thousandSeparator: ',',
    decimalSeparator: '.',
    flag: '🇬🇧'
  },
  JPY: {
    code: 'JPY',
    symbol: '¥',
    name: 'Japanese Yen',
    locale: 'ja-JP',
    decimals: 0, // No decimal places for Yen
    symbolPosition: 'before', // ¥10000
    thousandSeparator: ',',
    decimalSeparator: '.',
    flag: '🇯🇵'
  },
  CHF: {
    code: 'CHF',
    symbol: 'CHF',
    name: 'Swiss Franc',
    locale: 'de-CH',
    decimals: 2,
    symbolPosition: 'after', // 100 CHF
    thousandSeparator: "'",
    decimalSeparator: '.',
    flag: '🇨🇭'
  },
  AUD: {
    code: 'AUD',
    symbol: 'A$',
    name: 'Australian Dollar',
    locale: 'en-AU',
    decimals: 2,
    symbolPosition: 'before', // A$100
    thousandSeparator: ',',
    decimalSeparator: '.',
    flag: '🇦🇺'
  },
  CAD: {
    code: 'CAD',
    symbol: 'C$',
    name: 'Canadian Dollar',
    locale: 'en-CA',
    decimals: 2,
    symbolPosition: 'before', // C$100
    thousandSeparator: ',',
    decimalSeparator: '.',
    flag: '🇨🇦'
  }
};

// Default currency
export const DEFAULT_CURRENCY = 'USD';

// Supported currency codes array
export const SUPPORTED_CURRENCIES = Object.keys(CURRENCIES);

/**
 * Format a price in the specified currency
 * @param {number} amount - The amount to format
 * @param {string} currencyCode - Currency code (USD, EUR, etc.)
 * @param {object} options - Additional formatting options
 * @returns {string} Formatted price string
 */
export function formatPrice(amount, currencyCode = DEFAULT_CURRENCY, options = {}) {
  const currency = CURRENCIES[currencyCode] || CURRENCIES[DEFAULT_CURRENCY];
  const { showSymbol = true, showCode = false } = options;

  // Use Intl.NumberFormat for locale-aware formatting
  const formatter = new Intl.NumberFormat(currency.locale, {
    style: showSymbol ? 'currency' : 'decimal',
    currency: currency.code,
    minimumFractionDigits: currency.decimals,
    maximumFractionDigits: currency.decimals
  });

  let formatted = formatter.format(amount);

  // Add currency code if requested
  if (showCode && !showSymbol) {
    formatted = `${formatted} ${currency.code}`;
  }

  return formatted;
}

/**
 * Parse a formatted price string back to a number
 * @param {string} priceString - Formatted price string
 * @param {string} currencyCode - Currency code
 * @returns {number} Numeric value
 */
export function parsePrice(priceString, currencyCode = DEFAULT_CURRENCY) {
  const currency = CURRENCIES[currencyCode] || CURRENCIES[DEFAULT_CURRENCY];

  // Remove currency symbols and formatting
  let cleaned = priceString
    .replace(currency.symbol, '')
    .replace(currency.code, '')
    .replace(new RegExp(`\\${currency.thousandSeparator}`, 'g'), '')
    .replace(currency.decimalSeparator, '.')
    .trim();

  return parseFloat(cleaned) || 0;
}

/**
 * Get currency by code
 * @param {string} code - Currency code
 * @returns {object|null} Currency object or null
 */
export function getCurrency(code) {
  return CURRENCIES[code?.toUpperCase()] || null;
}

/**
 * Validate currency code
 * @param {string} code - Currency code to validate
 * @returns {boolean} True if valid
 */
export function isValidCurrency(code) {
  return SUPPORTED_CURRENCIES.includes(code?.toUpperCase());
}

/**
 * Get all currencies as array for dropdowns
 * @returns {array} Array of currency objects with code as key
 */
export function getCurrencyList() {
  return Object.entries(CURRENCIES).map(([code, data]) => ({
    value: code,
    label: `${data.flag} ${code} - ${data.name}`,
    ...data
  }));
}

export default {
  CURRENCIES,
  DEFAULT_CURRENCY,
  SUPPORTED_CURRENCIES,
  formatPrice,
  parsePrice,
  getCurrency,
  isValidCurrency,
  getCurrencyList
};