export function mortgageCalculator(form: FormTs) {
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Mortgage Payment Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Loan Details Section
const loanSection = form.addSubform('loan', { title: '๐ต Loan Details' });
loanSection.addRow(row => {
row.addMoney('homePrice', {
label: 'Home Price',
currency: '$',
min: 50000,
max: 10000000,
defaultValue: 350000,
isRequired: true
}, '1fr');
row.addMoney('downPayment', {
label: 'Down Payment',
currency: '$',
min: 0,
max: () => loanSection.money('homePrice')?.value() || 0,
defaultValue: 70000,
isRequired: true
}, '1fr');
});
loanSection.addRow(row => {
row.addPriceDisplay('downPaymentPercent', {
label: 'Down Payment Percentage',
computedValue: () => {
const homePrice = loanSection.money('homePrice')?.value() || 350000;
const downPayment = loanSection.money('downPayment')?.value() || 0;
return (downPayment / homePrice) * 100;
},
currency: '',
suffix: '%',
decimals: 1,
variant: 'default'
}, '1fr');
row.addPriceDisplay('loanAmount', {
label: 'Loan Amount',
computedValue: () => {
const homePrice = loanSection.money('homePrice')?.value() || 350000;
const downPayment = loanSection.money('downPayment')?.value() || 0;
return homePrice - downPayment;
},
variant: 'highlight'
}, '1fr');
});
// Interest & Term Section
const termsSection = form.addSubform('terms', { title: '๐ Interest & Loan Term' });
termsSection.addRow(row => {
row.addDecimal('interestRate', {
label: 'Interest Rate (Annual %)',
min: 0.1,
max: 20,
step: 0.125,
defaultValue: 6.5,
isRequired: true
}, '1fr');
row.addDropdown('loanTerm', {
label: 'Loan Term',
options: [
{ id: '10', name: '10 Years' },
{ id: '15', name: '15 Years' },
{ id: '20', name: '20 Years' },
{ id: '25', name: '25 Years' },
{ id: '30', name: '30 Years' }
],
defaultValue: '30',
isRequired: true
}, '1fr');
});
termsSection.addRow(row => {
row.addRadioButton('loanType', {
label: 'Loan Type',
options: [
{ id: 'fixed', name: 'Fixed Rate' },
{ id: 'arm', name: 'Adjustable Rate (ARM)' }
],
defaultValue: 'fixed',
orientation: 'horizontal'
});
});
// Additional Costs Section
const additionalSection = form.addSubform('additional', { title: '๐ Additional Monthly Costs' });
additionalSection.addRow(row => {
row.addMoney('propertyTax', {
label: 'Property Tax (Annual)',
currency: '$',
min: 0,
max: 100000,
defaultValue: 4200,
placeholder: 'Annual property tax'
}, '1fr');
row.addMoney('homeInsurance', {
label: 'Home Insurance (Annual)',
currency: '$',
min: 0,
max: 50000,
defaultValue: 1800,
placeholder: 'Annual insurance premium'
}, '1fr');
});
additionalSection.addRow(row => {
row.addMoney('pmi', {
label: 'PMI (Monthly)',
currency: '$',
min: 0,
max: 1000,
defaultValue: 0,
placeholder: 'Private Mortgage Insurance',
computedValue: () => {
const homePrice = loanSection.money('homePrice')?.value() || 350000;
const downPayment = loanSection.money('downPayment')?.value() || 0;
const downPaymentPercent = (downPayment / homePrice) * 100;
if (downPaymentPercent >= 20) return 0;
const loanAmount = homePrice - downPayment;
return Math.round(loanAmount * 0.007 / 12);
}
}, '1fr');
row.addMoney('hoaFees', {
label: 'HOA Fees (Monthly)',
currency: '$',
min: 0,
max: 2000,
defaultValue: 0,
placeholder: 'Homeowners association'
}, '1fr');
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Results Section
const resultsSection = form.addSubform('results', { title: '๐ณ Your Monthly Payment', isCollapsible: false });
// Helper function for mortgage calculation (PMT formula)
const calculateMonthlyPayment = () => {
const homePrice = loanSection.money('homePrice')?.value() || 350000;
const downPayment = loanSection.money('downPayment')?.value() || 0;
const principal = homePrice - downPayment;
const annualRate = (termsSection.decimal('interestRate')?.value() || 6.5) / 100;
const monthlyRate = annualRate / 12;
const termYears = parseInt(termsSection.dropdown('loanTerm')?.value() || '30');
const numPayments = termYears * 12;
if (monthlyRate === 0) return principal / numPayments;
const payment = principal *
(monthlyRate * Math.pow(1 + monthlyRate, numPayments)) /
(Math.pow(1 + monthlyRate, numPayments) - 1);
return payment;
};
resultsSection.addRow(row => {
row.addPriceDisplay('principalInterest', {
label: 'Principal & Interest',
computedValue: () => Math.round(calculateMonthlyPayment()),
variant: 'default'
}, '1fr');
row.addPriceDisplay('monthlyTax', {
label: 'Property Tax',
computedValue: () => {
const annualTax = additionalSection.money('propertyTax')?.value() || 0;
return Math.round(annualTax / 12);
},
variant: 'default',
suffix: '/mo'
}, '1fr');
});
resultsSection.addRow(row => {
row.addPriceDisplay('monthlyInsurance', {
label: 'Home Insurance',
computedValue: () => {
const annualInsurance = additionalSection.money('homeInsurance')?.value() || 0;
return Math.round(annualInsurance / 12);
},
variant: 'default',
suffix: '/mo'
}, '1fr');
row.addPriceDisplay('monthlyPmiHoa', {
label: 'PMI + HOA',
computedValue: () => {
const pmi = additionalSection.money('pmi')?.value() || 0;
const hoa = additionalSection.money('hoaFees')?.value() || 0;
return Math.round(pmi + hoa);
},
variant: 'default',
suffix: '/mo'
}, '1fr');
});
// Loan Summary Section
const summarySection = form.addSubform('summary', { title: '๐ Loan Summary', isCollapsible: false });
summarySection.addRow(row => {
row.addPriceDisplay('totalPrincipal', {
label: 'Total Principal',
computedValue: () => {
const homePrice = loanSection.money('homePrice')?.value() || 350000;
const downPayment = loanSection.money('downPayment')?.value() || 0;
return homePrice - downPayment;
},
variant: 'default'
}, '1fr');
row.addPriceDisplay('totalInterest', {
label: 'Total Interest Paid',
computedValue: () => {
const monthlyPayment = calculateMonthlyPayment();
const termYears = parseInt(termsSection.dropdown('loanTerm')?.value() || '30');
const totalPayments = monthlyPayment * termYears * 12;
const homePrice = loanSection.money('homePrice')?.value() || 350000;
const downPayment = loanSection.money('downPayment')?.value() || 0;
const principal = homePrice - downPayment;
return Math.round(totalPayments - principal);
},
variant: 'default'
}, '1fr');
});
summarySection.addRow(row => {
row.addPriceDisplay('totalCost', {
label: 'Total of All Payments',
computedValue: () => {
const monthlyPayment = calculateMonthlyPayment();
const termYears = parseInt(termsSection.dropdown('loanTerm')?.value() || '30');
return Math.round(monthlyPayment * termYears * 12);
},
variant: 'highlight'
}, '1fr');
row.addTextPanel('payoffDate', {
label: 'Payoff Date',
computedValue: () => {
const termYears = parseInt(termsSection.dropdown('loanTerm')?.value() || '30');
const payoffYear = new Date().getFullYear() + termYears;
const payoffMonth = new Date().toLocaleString('default', { month: 'long' });
return `${payoffMonth} ${payoffYear}`;
},
customStyles: { 'font-weight': '500', 'color': '#059669' }
}, '1fr');
});
// PMI Warning
summarySection.addRow(row => {
row.addTextPanel('pmiWarning', {
computedValue: () => {
const homePrice = loanSection.money('homePrice')?.value() || 350000;
const downPayment = loanSection.money('downPayment')?.value() || 0;
const downPaymentPercent = (downPayment / homePrice) * 100;
if (downPaymentPercent < 20) {
return `Tip: Increase your down payment to ${Math.ceil(homePrice * 0.2).toLocaleString('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 })} (20%) to avoid PMI.`;
}
return 'Great! With 20%+ down payment, you avoid PMI.';
},
customStyles: { 'font-size': '0.9rem', 'color': '#64748b', 'background': '#f8fafc', 'padding': '12px', 'border-radius': '6px' }
});
});
const finalSection = form.addSubform('final', {
title: '๐งพ Summary',
isCollapsible: false,
sticky: 'bottom'
});
finalSection.addRow(row => {
row.addPriceDisplay('totalMonthly', {
label: 'Total Monthly Payment',
computedValue: () => {
const pi = calculateMonthlyPayment();
const tax = (additionalSection.money('propertyTax')?.value() || 0) / 12;
const insurance = (additionalSection.money('homeInsurance')?.value() || 0) / 12;
const pmi = additionalSection.money('pmi')?.value() || 0;
const hoa = additionalSection.money('hoaFees')?.value() || 0;
return Math.round(pi + tax + insurance + pmi + hoa);
},
variant: 'large',
suffix: '/month'
});
});
finalSection.addRow(row => {
row.addTextPanel('payoffInfo', {
computedValue: () => {
const termYears = parseInt(termsSection.dropdown('loanTerm')?.value() || '30');
const payoffYear = new Date().getFullYear() + termYears;
return `Payoff: ${payoffYear}`;
},
customStyles: { 'font-size': '0.85rem', 'color': '#64748b', 'font-style': 'italic' }
});
});
form.configureSubmitButton({
label: 'Get Pre-Approved',
isVisible: false
});
}