export function currencyExchangeCalculator(form: FormTs) {
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Currency Exchange Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Amount Section
const amountSection = form.addSubform('amount', { title: '💵 Amount to Convert' });
amountSection.addRow(row => {
row.addDecimal('sourceAmount', {
label: 'Amount',
min: 0.01,
max: 100000000,
defaultValue: 1000,
isRequired: true
}, '2fr');
row.addDropdown('sourceCurrency', {
label: 'From Currency',
options: [
{ id: 'USD', name: 'USD - US Dollar' },
{ id: 'EUR', name: 'EUR - Euro' },
{ id: 'GBP', name: 'GBP - British Pound' },
{ id: 'JPY', name: 'JPY - Japanese Yen' },
{ id: 'CAD', name: 'CAD - Canadian Dollar' },
{ id: 'AUD', name: 'AUD - Australian Dollar' },
{ id: 'CHF', name: 'CHF - Swiss Franc' },
{ id: 'CNY', name: 'CNY - Chinese Yuan' },
{ id: 'INR', name: 'INR - Indian Rupee' },
{ id: 'MXN', name: 'MXN - Mexican Peso' },
{ id: 'BRL', name: 'BRL - Brazilian Real' },
{ id: 'KRW', name: 'KRW - South Korean Won' },
{ id: 'SGD', name: 'SGD - Singapore Dollar' },
{ id: 'HKD', name: 'HKD - Hong Kong Dollar' },
{ id: 'PLN', name: 'PLN - Polish Zloty' }
],
defaultValue: 'USD',
isRequired: true
}, '1fr');
});
// Target Currency Section
const targetSection = form.addSubform('target', { title: '🔄 Convert To' });
targetSection.addRow(row => {
row.addDropdown('targetCurrency', {
label: 'To Currency',
options: [
{ id: 'USD', name: 'USD - US Dollar' },
{ id: 'EUR', name: 'EUR - Euro' },
{ id: 'GBP', name: 'GBP - British Pound' },
{ id: 'JPY', name: 'JPY - Japanese Yen' },
{ id: 'CAD', name: 'CAD - Canadian Dollar' },
{ id: 'AUD', name: 'AUD - Australian Dollar' },
{ id: 'CHF', name: 'CHF - Swiss Franc' },
{ id: 'CNY', name: 'CNY - Chinese Yuan' },
{ id: 'INR', name: 'INR - Indian Rupee' },
{ id: 'MXN', name: 'MXN - Mexican Peso' },
{ id: 'BRL', name: 'BRL - Brazilian Real' },
{ id: 'KRW', name: 'KRW - South Korean Won' },
{ id: 'SGD', name: 'SGD - Singapore Dollar' },
{ id: 'HKD', name: 'HKD - Hong Kong Dollar' },
{ id: 'PLN', name: 'PLN - Polish Zloty' }
],
defaultValue: 'EUR',
isRequired: true
});
});
// Exchange Provider Section
const providerSection = form.addSubform('provider', { title: '🏦 Exchange Provider' });
providerSection.addRow(row => {
row.addRadioButton('providerType', {
label: 'Provider Type',
options: [
{ id: 'bank', name: 'Bank (1.5-3% markup)' },
{ id: 'exchange', name: 'Currency Exchange (2-5% markup)' },
{ id: 'online', name: 'Online Service (0.5-1.5% markup)' },
{ id: 'card', name: 'Credit Card (2-3% foreign fee)' },
{ id: 'custom', name: 'Custom Rate' }
],
defaultValue: 'online',
isRequired: true
});
});
providerSection.addRow(row => {
row.addDecimal('customMarkup', {
label: 'Custom Markup Percentage',
min: 0,
max: 20,
defaultValue: 1,
suffix: '%',
isVisible: () => providerSection.radioButton('providerType')?.value() === 'custom'
}, '1fr');
row.addDecimal('flatFee', {
label: 'Flat Transaction Fee',
min: 0,
max: 100,
defaultValue: 0,
prefix: '$',
tooltip: 'Fixed fee charged per transaction'
}, '1fr');
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Exchange Rates Reference
const ratesSection = form.addSubform('rates', { title: '📈 Exchange Rates (vs USD)', isCollapsible: true });
ratesSection.addRow(row => {
row.addTextPanel('ratesInfo', {
computedValue: () => {
return 'EUR: 0.92 | GBP: 0.79 | JPY: 149.50 | CAD: 1.36 | AUD: 1.53 | CHF: 0.88 | CNY: 7.24 | INR: 83.12 | MXN: 17.15 | BRL: 4.97 | KRW: 1,320 | SGD: 1.34 | HKD: 7.82 | PLN: 3.98';
},
customStyles: { 'font-size': '0.85rem', 'color': '#475569', 'text-align': 'center' }
});
});
ratesSection.addRow(row => {
row.addTextPanel('rateNote', {
computedValue: () => 'Note: Rates are approximate mid-market rates. Actual rates vary by provider.',
customStyles: { 'font-size': '0.75rem', 'color': '#94a3b8', 'text-align': 'center', 'font-style': 'italic' }
});
});
// Results Section
const resultsSection = form.addSubform('results', { title: '📊 Conversion Details', isCollapsible: false });
const getExchangeRate = (from: string, to: string): number => {
const usdRates: Record<string, number> = {
'USD': 1, 'EUR': 0.92, 'GBP': 0.79, 'JPY': 149.50, 'CAD': 1.36,
'AUD': 1.53, 'CHF': 0.88, 'CNY': 7.24, 'INR': 83.12, 'MXN': 17.15,
'BRL': 4.97, 'KRW': 1320, 'SGD': 1.34, 'HKD': 7.82, 'PLN': 3.98
};
if (from === to) return 1;
const fromToUsd = 1 / (usdRates[from] || 1);
const usdToTarget = usdRates[to] || 1;
return fromToUsd * usdToTarget;
};
resultsSection.addRow(row => {
row.addTextPanel('midMarketRate', {
label: 'Mid-Market Rate',
computedValue: () => {
const from = amountSection.dropdown('sourceCurrency')?.value() || 'USD';
const to = targetSection.dropdown('targetCurrency')?.value() || 'EUR';
const rate = getExchangeRate(from, to);
return `1 ${from} = ${(Number(rate) || 0).toFixed(4)} ${to}`;
},
customStyles: { 'font-size': '1rem', 'font-weight': '500', 'color': '#475569' }
}, '1fr');
row.addTextPanel('providerRate', {
label: 'Provider Rate (with markup)',
computedValue: () => {
const from = amountSection.dropdown('sourceCurrency')?.value() || 'USD';
const to = targetSection.dropdown('targetCurrency')?.value() || 'EUR';
const provider = providerSection.radioButton('providerType')?.value() || 'online';
const customMarkup = providerSection.decimal('customMarkup')?.value() || 1;
const markups: Record<string, number> = {
bank: 2.25, exchange: 3.5, online: 1, card: 2.5, custom: customMarkup
};
const rate = getExchangeRate(from, to);
const markup = markups[provider] || 1;
const adjustedRate = rate * (1 - markup / 100);
return `1 ${from} = ${(Number(adjustedRate) || 0).toFixed(4)} ${to}`;
},
customStyles: { 'font-size': '1rem', 'font-weight': '500', 'color': '#475569' }
}, '1fr');
});
resultsSection.addRow(row => {
row.addPriceDisplay('markupCost', {
label: 'Markup Cost',
computedValue: () => {
const amount = amountSection.decimal('sourceAmount')?.value() || 1000;
const from = amountSection.dropdown('sourceCurrency')?.value() || 'USD';
const to = targetSection.dropdown('targetCurrency')?.value() || 'EUR';
const provider = providerSection.radioButton('providerType')?.value() || 'online';
const customMarkup = providerSection.decimal('customMarkup')?.value() || 1;
const flatFee = providerSection.decimal('flatFee')?.value() || 0;
const markups: Record<string, number> = {
bank: 2.25, exchange: 3.5, online: 1, card: 2.5, custom: customMarkup
};
const rate = getExchangeRate(from, to);
const markup = markups[provider] || 1;
const midMarketResult = amount * rate;
const adjustedResult = amount * rate * (1 - markup / 100);
const toUsdRate = getExchangeRate(to, 'USD');
return ((midMarketResult - adjustedResult) * toUsdRate) + flatFee;
},
variant: 'default'
}, '1fr');
row.addTextPanel('markupPercent', {
label: 'Effective Fee',
computedValue: () => {
const provider = providerSection.radioButton('providerType')?.value() || 'online';
const customMarkup = providerSection.decimal('customMarkup')?.value() || 1;
const markups: Record<string, number> = {
bank: 2.25, exchange: 3.5, online: 1, card: 2.5, custom: customMarkup
};
return `${markups[provider]}%`;
},
customStyles: { 'font-size': '1.2rem', 'font-weight': '600', 'text-align': 'center', 'color': '#dc2626' }
}, '1fr');
});
// Summary Section
const summarySection = form.addSubform('summary', {
title: '💰 You Will Receive',
isCollapsible: false,
sticky: 'bottom'
});
summarySection.addRow(row => {
row.addTextPanel('convertedAmount', {
computedValue: () => {
const amount = amountSection.decimal('sourceAmount')?.value() || 1000;
const from = amountSection.dropdown('sourceCurrency')?.value() || 'USD';
const to = targetSection.dropdown('targetCurrency')?.value() || 'EUR';
const provider = providerSection.radioButton('providerType')?.value() || 'online';
const customMarkup = providerSection.decimal('customMarkup')?.value() || 1;
const markups: Record<string, number> = {
bank: 2.25, exchange: 3.5, online: 1, card: 2.5, custom: customMarkup
};
const rate = getExchangeRate(from, to);
const markup = markups[provider] || 1;
const result = amount * rate * (1 - markup / 100);
const currencySymbols: Record<string, string> = {
'USD': '$', 'EUR': '€', 'GBP': '£', 'JPY': '¥', 'CAD': 'C$',
'AUD': 'A$', 'CHF': 'CHF ', 'CNY': '¥', 'INR': '₹', 'MXN': 'MX$',
'BRL': 'R$', 'KRW': '₩', 'SGD': 'S$', 'HKD': 'HK$', 'PLN': 'zł'
};
const symbol = currencySymbols[to] || '';
return `${symbol}${result.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
},
customStyles: { 'font-size': '2rem', 'font-weight': '700', 'text-align': 'center', 'color': '#059669' }
});
});
summarySection.addRow(row => {
row.addTextPanel('conversionSummary', {
computedValue: () => {
const amount = amountSection.decimal('sourceAmount')?.value() || 1000;
const from = amountSection.dropdown('sourceCurrency')?.value() || 'USD';
const to = targetSection.dropdown('targetCurrency')?.value() || 'EUR';
return `Converting ${amount.toLocaleString()} ${from} to ${to}`;
},
customStyles: { 'font-size': '0.95rem', 'text-align': 'center', 'color': '#64748b' }
});
});
summarySection.addRow(row => {
row.addTextPanel('disclaimer', {
computedValue: () => 'Exchange rates are indicative only. Actual rates may vary. Always check with your provider before transacting.',
customStyles: { 'font-size': '0.8rem', 'color': '#94a3b8', 'text-align': 'center' }
});
});
form.configureSubmitButton({
label: 'Find Best Rates'
});
}