Mortgage Calculator
Inputs
Monthly payment breakdown
$2,171/mo
Principal & Interest: $1,825.19/mo
Property Tax: $280/mo
Homeowner’s Insurance: $66/mo
Amortization for mortgage loan
Loan Amount: $320,000
Total Interest Paid (est.): $369,201
Total Cost of Loan: $689,201
Payoff date: Dec 2054
[wpcode id=”54″]
import React, { useState } from 'react';
import {
Box,
Container,
Grid,
TextField,
InputAdornment,
MenuItem,
Typography,
Button,
Tabs,
Tab,
Paper
} from '@mui/material';
import { PieChart, Pie, Cell, Tooltip, Legend } from 'recharts';
import {
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
ResponsiveContainer
} from 'recharts';
// For a real app, you might fetch average tax, insurance, or do more dynamic calculations
// But for demonstration, we’ll keep the example simple and partially hard-coded.
const MortgageCalculator = () => {
// ---------------------------
// State Management
// ---------------------------
const [homePrice, setHomePrice] = useState(425000);
const [downPayment, setDownPayment] = useState(85000);
const [loanTerm, setLoanTerm] = useState(30);
const [interestRate, setInterestRate] = useState(5);
const [propertyTax, setPropertyTax] = useState(280); // monthly
const [homeInsurance, setHomeInsurance] = useState(66); // monthly
const [activeTab, setActiveTab] = useState(0);
// ---------------------------
// Calculations (simplified)
// ---------------------------
// Principal = homePrice - downPayment
const principal = homePrice - downPayment;
// Monthly interest rate in decimal form
const monthlyInterestRate = interestRate / 100 / 12;
// # of total monthly payments
const numberOfPayments = loanTerm * 12;
// Standard mortgage payment formula
// Payment = P * ( r(1+r)^n ) / ( (1+r)^n - 1 )
const monthlyPrincipalAndInterest =
monthlyInterestRate === 0
? principal / numberOfPayments
: principal *
(monthlyInterestRate * Math.pow(1 + monthlyInterestRate, numberOfPayments)) /
(Math.pow(1 + monthlyInterestRate, numberOfPayments) - 1);
const totalMonthlyPayment =
monthlyPrincipalAndInterest + propertyTax + homeInsurance;
// Donut chart data for monthly payment breakdown
const donutData = [
{ name: 'Principal & interest', value: parseFloat(monthlyPrincipalAndInterest.toFixed(2)) },
{ name: 'Property tax', value: propertyTax },
{ name: 'Homeowner\'s insurance', value: homeInsurance }
];
const COLORS = ['#4285F4', '#34A853', '#9C27B0'];
// Mocked amortization data (for a real app, compute for each month/year)
// The green line might show interest paid, the blue line principal, the red line total balance, etc.
const amortizationData = Array.from({ length: loanTerm + 1 }, (_, i) => {
return {
year: 2025 + i,
principalPaid: i * 4000, // mock
interestPaid: i * 3500, // mock
loanBalance: principal - i * (principal / loanTerm) // mock
};
});
// ---------------------------
// Handlers
// ---------------------------
const handleTabChange = (event, newValue) => {
setActiveTab(newValue);
};
return (
<Container maxWidth="lg" sx={{ py: 4 }}>
<Typography variant="h4" mb={2}>
Mortgage Calculator
</Typography>
<Grid container spacing={4}>
{/* LEFT SIDE FORM */}
<Grid item xs={12} md={4}>
<Paper sx={{ p: 2 }} variant="outlined">
<Typography variant="h6" mb={2}>
Inputs
</Typography>
{/* Home Price */}
<TextField
label="Home price"
fullWidth
variant="outlined"
type="number"
value={homePrice}
onChange={(e) => setHomePrice(+e.target.value)}
InputProps={{
startAdornment: <InputAdornment position="start">$</InputAdornment>
}}
sx={{ mb: 2 }}
/>
{/* Down Payment */}
<Grid container spacing={2}>
<Grid item xs={8}>
<TextField
label="Down payment"
fullWidth
variant="outlined"
type="number"
value={downPayment}
onChange={(e) => setDownPayment(+e.target.value)}
InputProps={{
startAdornment: <InputAdornment position="start">$</InputAdornment>
}}
/>
</Grid>
<Grid item xs={4}>
<TextField
label="%"
variant="outlined"
type="number"
// could auto-calc if needed, but let's keep it static for now
value={((downPayment / homePrice) * 100).toFixed(2)}
disabled
fullWidth
/>
</Grid>
</Grid>
{/* Loan Term */}
<TextField
select
label="Loan term"
fullWidth
variant="outlined"
value={loanTerm}
onChange={(e) => setLoanTerm(+e.target.value)}
sx={{ my: 2 }}
>
<MenuItem value={15}>15 years</MenuItem>
<MenuItem value={20}>20 years</MenuItem>
<MenuItem value={30}>30 years</MenuItem>
</TextField>
{/* Interest Rate */}
<TextField
label="Interest rate"
fullWidth
variant="outlined"
type="number"
value={interestRate}
onChange={(e) => setInterestRate(+e.target.value)}
InputProps={{
endAdornment: <InputAdornment position="end">%</InputAdornment>
}}
sx={{ mb: 2 }}
/>
{/* Property Tax */}
<TextField
label="Property tax"
fullWidth
variant="outlined"
type="number"
value={propertyTax}
onChange={(e) => setPropertyTax(+e.target.value)}
InputProps={{
startAdornment: <InputAdornment position="start">$</InputAdornment>,
endAdornment: <InputAdornment position="end">/mo</InputAdornment>
}}
sx={{ mb: 2 }}
/>
{/* Homeowner's Insurance */}
<TextField
label="Homeowner's insurance"
fullWidth
variant="outlined"
type="number"
value={homeInsurance}
onChange={(e) => setHomeInsurance(+e.target.value)}
InputProps={{
startAdornment: <InputAdornment position="start">$</InputAdornment>,
endAdornment: <InputAdornment position="end">/mo</InputAdornment>
}}
/>
<Box mt={3}>
<Button variant="contained" fullWidth>
Calculate
</Button>
</Box>
</Paper>
</Grid>
{/* RIGHT SIDE TABS (Payment Breakdown + Amortization) */}
<Grid item xs={12} md={8}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs value={activeTab} onChange={handleTabChange}>
<Tab label="Payment breakdown" />
<Tab label="Amortization" />
</Tabs>
</Box>
{/** PAYMENT BREAKDOWN TAB */}
{activeTab === 0 && (
<Box p={2}>
<Typography variant="h5" gutterBottom>
Monthly payment breakdown
</Typography>
<Typography variant="h3" color="primary" mb={2}>
${totalMonthlyPayment.toFixed(0)}/mo
</Typography>
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
{/* Donut Chart */}
<PieChart width={300} height={250}>
<Pie
data={donutData}
dataKey="value"
nameKey="name"
cx="50%"
cy="50%"
innerRadius={60}
outerRadius={80}
fill="#8884d8"
label
>
{donutData.map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
<Tooltip />
<Legend />
</PieChart>
</Grid>
<Grid item xs={12} md={6}>
<Box>
<Typography>
Principal & Interest:
<strong> ${monthlyPrincipalAndInterest.toFixed(2)}/mo</strong>
</Typography>
<Typography>
Property Tax:
<strong> ${propertyTax.toFixed(2)}/mo</strong>
</Typography>
<Typography>
Homeowner’s Insurance:
<strong> ${homeInsurance.toFixed(2)}/mo</strong>
</Typography>
</Box>
</Grid>
</Grid>
</Box>
)}
{/** AMORTIZATION TAB */}
{activeTab === 1 && (
<Box p={2}>
<Typography variant="h5" gutterBottom>
Amortization for mortgage loan
</Typography>
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
<Typography variant="body1">
Loan Amount: <strong>${principal}</strong>
</Typography>
<Typography variant="body1">
Total Interest Paid (est.): <strong>...</strong>
</Typography>
<Typography variant="body1">
Total Cost of Loan: <strong>...</strong>
</Typography>
<Typography variant="body1">
Payoff date: <strong>Dec {2024 + loanTerm}</strong>
</Typography>
</Grid>
<Grid item xs={12}>
{/* Multi-Line Chart or multiple lines in one chart */}
<Box width="100%" height={400}>
<ResponsiveContainer>
<LineChart data={amortizationData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="year" />
<YAxis />
<Tooltip />
<Legend />
<Line
type="monotone"
dataKey="principalPaid"
stroke="#155776"
name="Principal Paid"
/>
<Line
type="monotone"
dataKey="interestPaid"
stroke="#2085B5"
name="Interest Paid"
/>
<Line
type="monotone"
dataKey="loanBalance"
stroke="#FF0000"
name="Loan Balance"
/>
</LineChart>
</ResponsiveContainer>
</Box>
</Grid>
</Grid>
</Box>
)}
</Grid>
</Grid>
</Container>
);
};
export default MortgageCalculator;
Mortgage Calculator
Inputs
Monthly payment breakdown
$2,171/mo
Donut Chart
Principal & Interest: $1,825.19/mo
Property Tax: $280/mo
Homeowner’s Insurance: $66/mo
Amortization for mortgage loan
Loan Amount: $340,000
Total Interest Paid (est.): $317,070
Total Cost of Loan: $657,070
Payoff date: Dec 2054
Line Chart (Amortization)