// Generic currency formatting composable with fallback chain. // Usage: // const { formatMoney, currentCurrency } = useCurrencyFormat({ // primary: clientCurrency, // e.g. 'EUR' // fallbacks: ['EUR'], // locale: 'sl-SI' // }) // formatMoney(123.45) -> '123,45 €' import { ref, computed } from 'vue' export function useCurrencyFormat(options = {}) { const { primary = 'EUR', fallbacks = ['EUR'], locale = 'sl-SI', minimumFractionDigits = 2, maximumFractionDigits = 2, } = options const primaryCurrency = ref(primary) const fallbackList = ref(Array.isArray(fallbacks) && fallbacks.length ? fallbacks : ['EUR']) const currencyChain = computed(() => [primaryCurrency.value, ...fallbackList.value].filter(Boolean)) const formatterByCode = new Map() function getFormatter(code) { if (!code) return null if (!formatterByCode.has(code)) { try { formatterByCode.set( code, new Intl.NumberFormat(locale, { style: 'currency', currency: code, minimumFractionDigits, maximumFractionDigits, }) ) } catch (e) { // invalid currency code – skip formatterByCode.set(code, null) } } return formatterByCode.get(code) } const activeCurrency = computed(() => { for (const c of currencyChain.value) { if (getFormatter(c)) return c } return 'EUR' }) function formatMoney(val, overrideCurrency) { if (val === null || val === undefined || val === '' || isNaN(val)) return '—' const code = overrideCurrency || activeCurrency.value const fmt = getFormatter(code) || getFormatter('EUR') return fmt ? fmt.format(Number(val)) : Number(val).toFixed(2) + ' ' + code } return { formatMoney, activeCurrency, primaryCurrency, setCurrency(code) { primaryCurrency.value = code }, } }