Interactive sliders with real-time calculations
onAmountChange(amount) → Recalculates all values, updates UI instantlyonTermChange(years) → Recalculates monthly payment and interestonQuickSelect(preset) → Jumps slider to preset value (£50K, £150K, etc.)onShowCalculation() → Opens modal with formula and breakdownonLockScenario() → Saves chosen scenario and proceeds to CM07Real-time calculation endpoint (optional - can be client-side)
/api/v1/loan-calculator/calculatePOST /api/v1/loan-calculator/calculate Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Content-Type: application/json { "principal": 150000, "term_months": 36, "annual_interest_rate": 0.045, "application_id": "app_20251222_143023_usr123" }
{
"request_id": "req_cm06_20251222_143715",
"status": "success",
"calculation": {
"monthly_payment": 4440,
"total_interest": 9840,
"total_repayment": 159840,
"apr": 0.045
},
"affordability": {
"disposable_income_monthly": 6240,
"payment_to_income_ratio": 0.711,
"cashflow_buffer": 1800,
"status": "comfortable", // "comfortable", "manageable", "tight"
"recommendation": "This leaves you a healthy operational cushion"
},
"amortization_schedule": [
{
"month": 1,
"payment": 4440,
"principal": 3877,
"interest": 563,
"balance": 146123
},
// ... 35 more months
],
"processing_time_ms": 12,
"timestamp": "2025-12-22T14:37:15Z"
}
/api/v1/applications/{application_id}/save-scenarioPOST /api/v1/applications/app_20251222_143023_usr123/save-scenario { "chosen_amount": 150000, "chosen_term_months": 36, "monthly_payment": 4440, "total_interest": 9840, "scenarios_explored": 7, // Number of slider adjustments "time_spent_seconds": 145 }
// £150,000 @ 4.5% APR over 36 months P = 150000 APR = 0.045 r = 0.045 / 12 = 0.00375 n = 36 M = 150000 × [0.00375(1.00375)^36] / [(1.00375)^36 - 1] M = 150000 × [0.00375 × 1.1448] / [1.1448 - 1] M = 150000 × 0.004293 / 0.1448 M = 150000 × 0.02964 M = £4,440/month
// Same loan example Total Repayment = 4440 × 36 = £159,840 Total Interest = 159840 - 150000 = £9,840 Interest as % = (9840 / 150000) × 100 = 6.56% // Note: This is total interest over life of loan, // not the same as APR (which is annualized)
// Olivia's café example Disposable Income = £6,240/month Monthly Payment = £4,440 Ratio = 4440 / 6240 = 0.711 = 71.1% Cashflow Buffer = 6240 - 4440 = £1,800/month Status: Comfortable ✓ // 71% is under 75% threshold with healthy £1.8K buffer
// Month 1 Interest = 150000 × 0.00375 = £563 Principal = 4440 - 563 = £3,877 Balance = 150000 - 3877 = £146,123 // Month 2 Interest = 146123 × 0.00375 = £548 Principal = 4440 - 548 = £3,892 Balance = 146123 - 3892 = £142,231 // Month 3 Interest = 142231 × 0.00375 = £533 Principal = 4440 - 533 = £3,907 Balance = 142231 - 3907 = £138,324
Real-time loan calculations and affordability assessment
// Calculate monthly payment using PMT formula function calculateMonthlyPayment(principal, annualRate, months) { // Convert annual rate to monthly const monthlyRate = annualRate / 12; // Handle edge case: 0% interest if (monthlyRate === 0) { return principal / months; } // PMT formula: P × [r(1+r)^n] / [(1+r)^n - 1] const x = Math.pow(1 + monthlyRate, months); const monthly = principal * (monthlyRate * x) / (x - 1); return Math.round(monthly); // Round to nearest pound } // Calculate total interest function calculateTotalInterest(monthlyPayment, months, principal) { const totalRepayment = monthlyPayment * months; return totalRepayment - principal; } // Assess affordability function assessAffordability(monthlyPayment, disposableIncome) { const ratio = monthlyPayment / disposableIncome; const buffer = disposableIncome - monthlyPayment; let status, message; if (ratio < 0.60 && buffer > 2000) { status = 'comfortable'; message = 'This leaves you a healthy operational cushion'; } else if (ratio < 0.75 && buffer > 500) { status = 'manageable'; message = 'This is manageable. Consider extending term if needed.'; } else { status = 'tight'; message = 'This would be challenging. We recommend reducing amount or extending term.'; } return { status, ratio, buffer, message }; } // Real-time update on slider change function updateCalculations() { const principal = parseInt(amountSlider.value); const years = parseInt(termSlider.value); const months = years * 12; const rate = 0.045; // From CM05 credit assessment const monthlyPayment = calculateMonthlyPayment(principal, rate, months); const totalInterest = calculateTotalInterest(monthlyPayment, months, principal); const affordability = assessAffordability(monthlyPayment, 6240); // Update UI instantly updateUI(monthlyPayment, totalInterest, affordability); }
function generateAmortizationSchedule(principal, annualRate, months) { const monthlyRate = annualRate / 12; const monthlyPayment = calculateMonthlyPayment(principal, annualRate, months); const schedule = []; let balance = principal; for (let month = 1; month <= months; month++) { const interest = Math.round(balance * monthlyRate); const principalPayment = monthlyPayment - interest; balance -= principalPayment; schedule.push({ month, payment: monthlyPayment, principal: principalPayment, interest, balance: Math.max(0, balance) // Avoid negative due to rounding }); } return schedule; }