export function roiCalculator(form: FormTs) {
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'ROI Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addRow(row => {
row.addTextPanel('subheader', {
computedValue: () => 'Calculate the return on your investment',
customStyles: { 'font-size': '1rem', 'color': '#64748b' }
});
});
form.addSpacer({ height: 20 });
// Investment Details Section
const investmentSection = form.addSubform('investmentDetails', { title: '๐ต Investment Details' });
investmentSection.addRow(row => {
row.addDecimal('initialInvestment', {
label: 'Initial Investment Amount ($)',
min: 0,
max: 100000000,
defaultValue: 10000,
decimalPlaces: 2,
isRequired: true
}, '1fr');
row.addDecimal('additionalCosts', {
label: 'Additional Costs ($)',
min: 0,
max: 10000000,
defaultValue: 0,
decimalPlaces: 2,
tooltip: 'Include ongoing costs, maintenance, etc.'
}, '1fr');
});
// Returns Section
const returnsSection = form.addSubform('returnsDetails', { title: '๐ Expected Returns' });
returnsSection.addRow(row => {
row.addRadioButton('returnType', {
label: 'How will you measure returns?',
options: [
{ id: 'total', name: 'Total Return Amount' },
{ id: 'revenue', name: 'Revenue Generated' },
{ id: 'savings', name: 'Cost Savings' }
],
defaultValue: 'total',
orientation: 'horizontal',
isRequired: true
});
});
returnsSection.addRow(row => {
row.addDecimal('expectedReturn', {
label: () => {
const type = returnsSection.radioButton('returnType')?.value() || 'total';
const labels: Record<string, string> = {
'total': 'Total Return Amount ($)',
'revenue': 'Expected Revenue ($)',
'savings': 'Expected Savings ($)'
};
return labels[type] || 'Expected Return ($)';
},
min: 0,
max: 100000000,
defaultValue: 15000,
decimalPlaces: 2,
isRequired: true
}, '1fr');
row.addInteger('timeframe', {
label: 'Timeframe (months)',
min: 1,
max: 120,
defaultValue: 12,
isRequired: true
}, '1fr');
});
// Advanced Options Section
const advancedSection = form.addSubform('advancedOptions', { title: 'โ๏ธ Advanced Options', isCollapsible: true });
advancedSection.addRow(row => {
row.addCheckbox('includeOpportunityCost', {
label: 'Include Opportunity Cost',
defaultValue: false
}, '1fr');
row.addDecimal('alternativeReturn', {
label: 'Alternative Investment Return (%)',
min: 0,
max: 50,
defaultValue: 5,
decimalPlaces: 1,
isVisible: () => advancedSection.checkbox('includeOpportunityCost')?.value() === true,
tooltip: 'What return could you get elsewhere? (e.g., 5% for savings account)'
}, '1fr');
});
advancedSection.addRow(row => {
row.addCheckbox('adjustForInflation', {
label: 'Adjust for Inflation',
defaultValue: false
}, '1fr');
row.addDecimal('inflationRate', {
label: 'Annual Inflation Rate (%)',
min: 0,
max: 20,
defaultValue: 3,
decimalPlaces: 1,
isVisible: () => advancedSection.checkbox('adjustForInflation')?.value() === true
}, '1fr');
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Results Section
const resultsSection = form.addSubform('results', { title: '๐ฐ ROI Analysis', isCollapsible: false });
resultsSection.addRow(row => {
row.addPriceDisplay('totalInvestment', {
label: 'Total Investment',
computedValue: () => {
const initial = investmentSection.decimal('initialInvestment')?.value() || 0;
const additional = investmentSection.decimal('additionalCosts')?.value() || 0;
return initial + additional;
},
variant: 'default'
}, '1fr');
row.addPriceDisplay('netProfit', {
label: 'Net Profit',
computedValue: () => {
const initial = investmentSection.decimal('initialInvestment')?.value() || 0;
const additional = investmentSection.decimal('additionalCosts')?.value() || 0;
const returns = returnsSection.decimal('expectedReturn')?.value() || 0;
const totalCost = initial + additional;
let netProfit = returns - totalCost;
// Adjust for opportunity cost
if (advancedSection.checkbox('includeOpportunityCost')?.value()) {
const altReturn = advancedSection.decimal('alternativeReturn')?.value() || 5;
const months = returnsSection.integer('timeframe')?.value() || 12;
const opportunityCost = totalCost * (altReturn / 100) * (months / 12);
netProfit -= opportunityCost;
}
// Adjust for inflation
if (advancedSection.checkbox('adjustForInflation')?.value()) {
const inflation = advancedSection.decimal('inflationRate')?.value() || 3;
const months = returnsSection.integer('timeframe')?.value() || 12;
const inflationFactor = Math.pow(1 + inflation / 100, months / 12);
netProfit = netProfit / inflationFactor;
}
return Math.round(netProfit * 100) / 100;
},
variant: () => {
const initial = investmentSection.decimal('initialInvestment')?.value() || 0;
const additional = investmentSection.decimal('additionalCosts')?.value() || 0;
const returns = returnsSection.decimal('expectedReturn')?.value() || 0;
return returns > (initial + additional) ? 'success' : 'error';
}
}, '1fr');
});
resultsSection.addRow(row => {
row.addTextPanel('annualizedRoi', {
computedValue: () => {
const initial = investmentSection.decimal('initialInvestment')?.value() || 0;
const additional = investmentSection.decimal('additionalCosts')?.value() || 0;
const returns = returnsSection.decimal('expectedReturn')?.value() || 0;
const months = returnsSection.integer('timeframe')?.value() || 12;
const totalCost = initial + additional;
if (totalCost === 0 || months === 0) return '';
const netProfit = returns - totalCost;
const roi = (netProfit / totalCost) * 100;
const annualizedRoi = roi * (12 / months);
return `Annualized ROI: ${(Number(annualizedRoi) || 0).toFixed(1)}% per year`;
},
customStyles: {
'font-size': '1.1rem',
'text-align': 'center',
'color': '#475569'
}
});
});
resultsSection.addRow(row => {
row.addTextPanel('paybackPeriod', {
computedValue: () => {
const initial = investmentSection.decimal('initialInvestment')?.value() || 0;
const additional = investmentSection.decimal('additionalCosts')?.value() || 0;
const returns = returnsSection.decimal('expectedReturn')?.value() || 0;
const months = returnsSection.integer('timeframe')?.value() || 12;
const totalCost = initial + additional;
if (totalCost === 0 || returns === 0) return '';
const monthlyReturn = returns / months;
const paybackMonths = totalCost / monthlyReturn;
if (paybackMonths > months) {
return `Payback Period: ${(Number(paybackMonths) || 0).toFixed(1)} months (exceeds timeframe)`;
}
return `Payback Period: ${(Number(paybackMonths) || 0).toFixed(1)} months`;
},
customStyles: {
'font-size': '1rem',
'text-align': 'center',
'color': '#64748b'
}
});
});
const finalSection = form.addSubform('final', {
title: '๐งพ Summary',
isCollapsible: false,
sticky: 'bottom'
});
finalSection.addRow(row => {
row.addTextPanel('roiResult', {
computedValue: () => {
const initial = investmentSection.decimal('initialInvestment')?.value() || 0;
const additional = investmentSection.decimal('additionalCosts')?.value() || 0;
const returns = returnsSection.decimal('expectedReturn')?.value() || 0;
const totalCost = initial + additional;
if (totalCost === 0) return 'Enter investment details';
let netProfit = returns - totalCost;
// Adjust for opportunity cost
if (advancedSection.checkbox('includeOpportunityCost')?.value()) {
const altReturn = advancedSection.decimal('alternativeReturn')?.value() || 5;
const months = returnsSection.integer('timeframe')?.value() || 12;
const opportunityCost = totalCost * (altReturn / 100) * (months / 12);
netProfit -= opportunityCost;
}
// Adjust for inflation
if (advancedSection.checkbox('adjustForInflation')?.value()) {
const inflation = advancedSection.decimal('inflationRate')?.value() || 3;
const months = returnsSection.integer('timeframe')?.value() || 12;
const inflationFactor = Math.pow(1 + inflation / 100, months / 12);
netProfit = netProfit / inflationFactor;
}
const roi = (netProfit / totalCost) * 100;
return `ROI: ${(Number(roi) || 0).toFixed(1)}%`;
},
customStyles: {
'font-size': '2rem',
'font-weight': '700',
'text-align': 'center',
'color': '#1e293b'
}
});
});
finalSection.addRow(row => {
row.addTextPanel('disclaimer', {
computedValue: () => 'Estimates only. Consult a financial advisor for decisions.',
customStyles: { 'font-size': '0.85rem', 'color': '#94a3b8', 'font-style': 'italic', 'text-align': 'center' }
});
});
form.configureSubmitButton({
label: 'Save Analysis'
});
}