tractatus/public/js/utils/currency.js
TheFlow 2298d36bed fix(submissions): restructure Economist package and fix article display
- Create Economist SubmissionTracking package correctly:
  * mainArticle = full blog post content
  * coverLetter = 216-word SIR— letter
  * Links to blog post via blogPostId
- Archive 'Letter to The Economist' from blog posts (it's the cover letter)
- Fix date display on article cards (use published_at)
- Target publication already displaying via blue badge

Database changes:
- Make blogPostId optional in SubmissionTracking model
- Economist package ID: 68fa85ae49d4900e7f2ecd83
- Le Monde package ID: 68fa2abd2e6acd5691932150

Next: Enhanced modal with tabs, validation, export

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 08:47:42 +13:00

131 lines
3.6 KiB
JavaScript

/**
* Currency Utilities (Client-Side)
* Multi-currency support for Koha donation form
*/
// Base prices in NZD (in cents)
const BASE_PRICES_NZD = {
tier_5: 500, // $5 NZD
tier_15: 1500, // $15 NZD
tier_50: 5000 // $50 NZD
};
// Exchange rates: 1 NZD = X currency
const EXCHANGE_RATES = {
NZD: 1.0,
USD: 0.60,
EUR: 0.55,
GBP: 0.47,
AUD: 0.93,
CAD: 0.82,
JPY: 94.0,
CHF: 0.53,
SGD: 0.81,
HKD: 4.68
};
// Currency metadata
const CURRENCY_CONFIG = {
NZD: { symbol: '$', code: 'NZD', name: 'NZ Dollar', decimals: 2, flag: '🇳🇿' },
USD: { symbol: '$', code: 'USD', name: 'US Dollar', decimals: 2, flag: '🇺🇸' },
EUR: { symbol: '€', code: 'EUR', name: 'Euro', decimals: 2, flag: '🇪🇺' },
GBP: { symbol: '£', code: 'GBP', name: 'British Pound', decimals: 2, flag: '🇬🇧' },
AUD: { symbol: '$', code: 'AUD', name: 'Australian Dollar', decimals: 2, flag: '🇦🇺' },
CAD: { symbol: '$', code: 'CAD', name: 'Canadian Dollar', decimals: 2, flag: '🇨🇦' },
JPY: { symbol: '¥', code: 'JPY', name: 'Japanese Yen', decimals: 0, flag: '🇯🇵' },
CHF: { symbol: 'CHF', code: 'CHF', name: 'Swiss Franc', decimals: 2, flag: '🇨🇭' },
SGD: { symbol: '$', code: 'SGD', name: 'Singapore Dollar', decimals: 2, flag: '🇸🇬' },
HKD: { symbol: '$', code: 'HKD', name: 'Hong Kong Dollar', decimals: 2, flag: '🇭🇰' }
};
// Supported currencies
const SUPPORTED_CURRENCIES = ['NZD', 'USD', 'EUR', 'GBP', 'AUD', 'CAD', 'JPY', 'CHF', 'SGD', 'HKD'];
/**
* Convert NZD amount to target currency
*/
function convertFromNZD(amountNZD, targetCurrency) {
const rate = EXCHANGE_RATES[targetCurrency];
return Math.round(amountNZD * rate);
}
/**
* Get tier prices for a currency
*/
function getTierPrices(currency) {
return {
tier_5: convertFromNZD(BASE_PRICES_NZD.tier_5, currency),
tier_15: convertFromNZD(BASE_PRICES_NZD.tier_15, currency),
tier_50: convertFromNZD(BASE_PRICES_NZD.tier_50, currency)
};
}
/**
* Format currency amount for display
*/
function formatCurrency(amountCents, currency) {
const config = CURRENCY_CONFIG[currency];
const amount = amountCents / 100;
// For currencies with symbols that should come after (none in our list currently)
// we could customize here, but Intl.NumberFormat handles it well
try {
return new Intl.NumberFormat('en-NZ', {
style: 'currency',
currency: currency,
minimumFractionDigits: config.decimals,
maximumFractionDigits: config.decimals
}).format(amount);
} catch (e) {
// Fallback if Intl fails
return `${config.symbol}${amount.toFixed(config.decimals)}`;
}
}
/**
* Get currency display name with flag
*/
function getCurrencyDisplayName(currency) {
const config = CURRENCY_CONFIG[currency];
return `${config.flag} ${config.code} - ${config.name}`;
}
/**
* Detect user's currency from browser/location
*/
function detectUserCurrency() {
// Try localStorage first
const saved = localStorage.getItem('tractatus_currency');
if (saved && SUPPORTED_CURRENCIES.includes(saved)) {
return saved;
}
// Try to detect from browser language
const lang = navigator.language || navigator.userLanguage || 'en-NZ';
const langMap = {
'en-US': 'USD',
'en-GB': 'GBP',
'en-AU': 'AUD',
'en-CA': 'CAD',
'en-NZ': 'NZD',
'ja': 'JPY',
'ja-JP': 'JPY',
'de': 'EUR',
'de-DE': 'EUR',
'fr': 'EUR',
'fr-FR': 'EUR',
'de-CH': 'CHF',
'en-SG': 'SGD',
'zh-HK': 'HKD'
};
return langMap[lang] || langMap[lang.substring(0, 2)] || 'NZD';
}
/**
* Save user's currency preference
*/
function saveCurrencyPreference(currency) {
localStorage.setItem('tractatus_currency', currency);
}