Demo

Mortgage Calculator

Inputs
  • Payment breakdown
  • Amortization
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
  • Payment breakdown
  • Amortization
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)