(636) 898-0888   Toll Free: (877) 456-2900

import { useState, useEffect, useCallback } from "react"; const formatCurrency = (val) => new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", maximumFractionDigits: 0 }).format(val); const formatNumber = (val) => new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 }).format(val); const CREDIT_RATES = { "760+": 6.5, "720-759": 6.875, "680-719": 7.125, "640-679": 7.5, "580-639": 8.0, }; const COUNTY_TAXES = { "Los Angeles, CA": 1.19, "Cook County, IL": 2.1, "Harris County, TX": 2.0, "Maricopa, AZ": 0.63, "King County, WA": 0.93, "Miami-Dade, FL": 0.97, "Denver, CO": 0.54, "New York, NY": 1.72, "Travis County, TX": 1.8, "Fulton County, GA": 1.02, }; const INSURANCE_RATE = 0.005; const PMI_RATE = 0.008; function calculate({ income, debts, downPayment, creditScore, county, extraSavings = 0 }) { const rate = CREDIT_RATES[creditScore] / 100 / 12; const taxRate = (COUNTY_TAXES[county] || 1.1) / 100; const dp = downPayment + extraSavings; const maxFrontEnd = income * 0.28; const maxBackEnd = income * 0.43 - debts; const maxMonthly = Math.min(maxFrontEnd, maxBackEnd); if (maxMonthly <= 0) return null; const estimatePriceFromMonthly = (monthly) => { let lo = 50000, hi = 2000000; for (let i = 0; i < 60; i++) { const mid = (lo + hi) / 2; const loanAmt = mid - dp; if (loanAmt <= 0) { hi = mid; continue; } const n = 360; const pmt = loanAmt * (rate * Math.pow(1 + rate, n)) / (Math.pow(1 + rate, n) - 1); const tax = (mid * taxRate) / 12; const ins = (mid * INSURANCE_RATE) / 12; const pmi = loanAmt / mid > 0.8 ? (loanAmt * PMI_RATE) / 12 : 0; const total = pmt + tax + ins + pmi; if (total < monthly) lo = mid; else hi = mid; } return Math.round((lo + hi) / 2); }; const price = estimatePriceFromMonthly(maxMonthly); const loanAmt = Math.max(0, price - dp); const n = 360; const pmt = loanAmt > 0 ? loanAmt * (rate * Math.pow(1 + rate, n)) / (Math.pow(1 + rate, n) - 1) : 0; const tax = (price * taxRate) / 12; const ins = (price * INSURANCE_RATE) / 12; const pmi = loanAmt / price > 0.8 ? (loanAmt * PMI_RATE) / 12 : 0; const totalPITI = pmt + tax + ins + pmi; const dti = ((debts + totalPITI) / income) * 100; const ltv = (loanAmt / price) * 100; return { price, loanAmt, pmt, tax, ins, pmi, totalPITI, dti, ltv, dp }; } function Slider({ label, min, max, step, value, onChange, prefix = "", suffix = "" }) { const pct = ((value - min) / (max - min)) * 100; return (

{label} {prefix}{formatNumber(value)}{suffix}
 
onChange(Number(e.target.value))} style={{ position: "absolute", top: "-8px", left: 0, width: "100%", height: "22px", opacity: 0, cursor: "pointer", margin: 0 }} />
 
{prefix}{formatNumber(min)}{suffix} {prefix}{formatNumber(max)}{suffix}

); } function DTIBar({ dti }) { const capped = Math.min(dti, 60); const color = dti < 28 ? "#4a9e6b" : dti < 36 ? "#c4922a" : dti < 43 ? "#e07b2a" : "#c0392b"; return (

Debt-to-Income Ratio {dti.toFixed(1)}%
); } function PaymentBreakdown({ result }) { const items = [ { label: "Principal & Interest", value: result.pmt, color: "#c4922a" }, { label: "Property Tax", value: result.tax, color: "#e6b04a" }, { label: "Homeowner's Insurance", value: result.ins, color: "#8b7355" }, ...(result.pmi > 0 ? [{ label: "PMI", value: result.pmi, color: "#c0392b" }] : []), ]; const total = result.totalPITI; return (
{items.map(item => { const pct = (item.value / total) * 100; return (
{item.label} {formatCurrency(item.value)}/mo
); })}
); } export default function HomeAffordabilityCalculator() { const [income, setIncome] = useState(8000); const [debts, setDebts] = useState(500); const [downPayment, setDownPayment] = useState(30000); const [creditScore, setCreditScore] = useState("720-759"); const [county, setCounty] = useState("Los Angeles, CA"); const [activeTab, setActiveTab] = useState("calculator"); const [savedScenarios, setSavedScenarios] = useState([]); const [showSaved, setShowSaved] = useState(false); const [justSaved, setJustSaved] = useState(false); const result = calculate({ income, debts, downPayment, creditScore, county }); const result5k = result ? calculate({ income, debts, downPayment, creditScore, county, extraSavings: 5000 }) : null; const result10k = result ? calculate({ income, debts, downPayment, creditScore, county, extraSavings: 10000 }) : null; const dtiOnly = result ? ((debts + result.totalPITI) / income) * 100 : 0; const saveScenario = () => { if (!result) return; const scenario = { id: Date.now(), date: new Date().toLocaleDateString(), income, debts, downPayment, creditScore, county, price: result.price, piti: result.totalPITI, }; setSavedScenarios(prev => [scenario, ...prev].slice(0, 5)); setJustSaved(true); setTimeout(() => setJustSaved(false), 2000); }; const getAffordabilityLabel = () => { if (!result) return { label: "Adjust your inputs", color: "#c0392b" }; const dti = ((debts + result.totalPITI) / income) * 100; if (dti < 28) return { label: "Excellent Position", color: "#4a9e6b" }; if (dti < 36) return { label: "Good Standing", color: "#c4922a" }; if (dti < 43) return { label: "Borderline", color: "#e07b2a" }; return { label: "High DTI", color: "#c0392b" }; }; const { label, color } = getAffordabilityLabel(); return (
{/* Header */}{/* Tabs */}
{[["calculator", "Calculator"], ["whatif", "What If I Saved More?"], ["saved", `Saved (${savedScenarios.length})`]].map(([id, lbl]) => ( ))}
{/* CALCULATOR TAB */} {activeTab === "calculator" && ( <> {/* Big result card */} {result && ()} {!result && (
⚠️
Your debts exceed the maximum allowable limit
Reduce monthly debts or increase income to qualify
)} {/* Inputs */}

Your Financial Picture

{/* DTI & Breakdown */} {result && ( <>
 

Payment Breakdown

{/* Plain English */}

What This Means

Based on your {formatCurrency(income * 12)}/year gross income and {formatCurrency(downPayment)} down payment, you could afford a home up to {formatCurrency(result.price)}.

Your total monthly payment of {formatCurrency(result.totalPITI)} includes your mortgage, property taxes, insurance{result.pmi > 0 ? ", and PMI" : ""}. Your debt-to-income ratio is {dtiOnly.toFixed(1)}% — {dtiOnly < 36 ? "you're in solid shape to qualify with most lenders." : dtiOnly < 43 ? "you're near the upper limit most lenders accept." : "this may be challenging; consider paying down debts first."}

{result.ltv > 80 && (

💡 Pro tip: Saving {formatCurrency(result.price * 0.2 - result.dp)} more would bring you to a 20% down payment, eliminating the {formatCurrency(result.pmi)}/mo PMI charge and saving you {formatCurrency(result.pmi * 360)} over 30 years.

)}
{/* Save button */} </> )} </> )} {/* WHAT IF TAB */} {activeTab === "whatif" && result && ( <>

The Power of Saving More

See how additional savings unlock more home

{[ { label: "Current", extra: 0, r: result, accent: "#8b7355" }, { label: "+ $5,000", extra: 5000, r: result5k, accent: "#c4922a" }, { label: "+ $10,000", extra: 10000, r: result10k, accent: "#4a9e6b" }, ].map(({ label, extra, r, accent }) => r && (
0 ? `${accent}08` : "#fafafa", position: "relative", overflow: "hidden", }}> {extra > 0 && (
+{formatCurrency(r.price - result.price)}
)}
{label}
Down Payment
{formatCurrency(r.dp)}
Max Price
{formatCurrency(r.price)}
Monthly PITI
{formatCurrency(r.totalPITI)}/mo
{r.pmi > 0 && (
PMI
{formatCurrency(r.pmi)}/mo
)}
))}

The Big Picture

{result5k && (

Saving an extra $5,000 could unlock an additional {formatCurrency(result5k.price - result.price)} in purchasing power.

)} {result10k && (

Saving an extra $10,000 could unlock an additional {formatCurrency(result10k.price - result.price)} in purchasing power — and may even eliminate PMI.

)}
</> )} {/* SAVED TAB */} {activeTab === "saved" && (
{savedScenarios.length === 0 ? (
📋

No Saved Scenarios Yet

Head to the Calculator tab and tap "Save This Scenario" to track your numbers over time.

) : ( <>

Your last {savedScenarios.length} saved scenario{savedScenarios.length > 1 ? "s" : ""}

{savedScenarios.map((s, i) => (
{ setIncome(s.income); setDebts(s.debts); setDownPayment(s.downPayment); setCreditScore(s.creditScore); setCounty(s.county); setActiveTab("calculator"); }}>
{s.date} · {s.county}
{formatCurrency(s.price)}
{formatCurrency(s.piti)}/mo · {formatCurrency(s.income)}/mo income
Load →
))} </> )}
)}
); }