← 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
};