Skip to content

Commit

Permalink
more loan breakdowns
Browse files Browse the repository at this point in the history
  • Loading branch information
wkelsey-apple committed May 30, 2024
1 parent 7d4aee4 commit 48f1944
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 91 deletions.
27 changes: 18 additions & 9 deletions trgmc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ Currently, two official plugins are available:
# Todo

## Important
- Show breakdown of total repayments
-- Add a reset button
-- Add a share button
-- save it to cookie
-- Add footer with ym name and link to git
- tax should reduce if loan length decreases
- show new finish date after events
- double check maths against other sites
- get a domain, make the site live
- fix total repayment when overpayment & refinance added
- show amount saved by doing overpayment
- CLIO FEEDBACK
-- show standard loan types and autofill length
-- overpayment shows remaining balance reduction
-- show “yearly”, “monthly”
-- add comments section
-- move export fn to common file to enable fast refresh
-- google analytics


## Later
-- show standard loan types and autofill length
- hover over explains how th eboxes were calculated
- refinance has option to change loan length
- Show loan length and new monthly payment
Expand All @@ -57,6 +57,15 @@ Currently, two official plugins are available:


# Done
- Show breakdown of total repayments
-- fix total repayment when overpayment & refinance added
-- show amount saved by doing overpayment
-- overpayment shows remaining balance reduction

-- new monthly payment when re-cast is chosen
-- show “yearly”, “monthly”
-- move export fn to common file to enable fast refresh
-- add comments section
-- screen vertical too small
-- note that monthly includes all
-- refinance on same date crashes site
Expand Down

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions trgmc/dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<link rel="icon" type="image/svg+xml" href="./vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
<script type="module" crossorigin src="./assets/index-gJjfRCWf.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-8iGur0UO.css">
<script type="module" crossorigin src="./assets/index-BptAHnls.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-CCIrZKUt.css">
</head>
<body>
<div id="root"></div>
Expand Down
25 changes: 18 additions & 7 deletions trgmc/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ function runCalculations(userInput, loanEvent, chosenInput, userSetDownPercent)
: parseFloat(userInput["homeVal"]) - parseFloat(userInput["downPayCash"]);
const downPay = userSetDownPercent ? parseFloat(userInput.downPayPercent) * 0.01 : parseFloat(userInput.downPayCash);

// console.log("loanAmount_1", loanAmount)

var loanRes = loanMaths(
parseFloat(loanAmount),
parseFloat(userInput["loanLength"]),
Expand All @@ -52,6 +54,7 @@ function runCalculations(userInput, loanEvent, chosenInput, userSetDownPercent)
displayState["monthlyPayment"] = parseFloat(loanRes["monthlyPayment"][0]);
}
displayState["monthlyPaymentToLoan"] = parseFloat(loanRes["monthlyInterest"][0]) + parseFloat(loanRes["monthlyPrincipal"][0]);
// console.log("homeVal",homeVal)
if (userSetDownPercent) {
displayState["downPayPercent"] = userInput["downPayPercent"];
displayState["downPayCash"] = homeVal * parseFloat(userInput["downPayPercent"]) * 0.01;
Expand All @@ -68,6 +71,7 @@ function runCalculations(userInput, loanEvent, chosenInput, userSetDownPercent)
displayState["interestRate"] = userInput["interestRate"];
displayState["loanLength"] = userInput["loanLength"];
displayState["loanAmount"] = loanRes["loanAmount"];
// console.log("loanAmount_2", loanRes["loanAmount"])

displayState["propertyTax"] = userInput["propertyTax"];
displayState["hoa"] = userInput["hoa"];
Expand Down Expand Up @@ -100,10 +104,11 @@ function loanEventDecoder(e) {
}

var accurateDate = new Date();
const dateLu = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
var dStr = `${accurateDate.getFullYear()}-${dateLu[accurateDate.getMonth()]}-01`;
// const dateLu = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
// var dStr = `${accurateDate.getFullYear()}-${dateLu[accurateDate.getMonth()]}-05`;
var dStr = `${accurateDate.getFullYear()}-01-05`; //Always defaultstarting at month 01 so graph looks symetrical
var coarseDate = Date.parse(dStr); //only care about month - don't want minor date changes going in URL
console.log("coarseDate", dStr, coarseDate);
// console.log("coarseDate", dStr, coarseDate);
const initialState = {
homeVal: "500000",
monthlyPayment: "0",
Expand Down Expand Up @@ -198,7 +203,6 @@ function App() {
var newValid = { ...valid };
var newUserSetDownPercent = userSetDownPercent;
var newDisplayState = { ...displayState };
console.log("bp2");

// if (userSetDownPercent) {
// var downPayCash = (loanRes["loanAmount"] * userInput["downPayPercent"]) / 100;
Expand Down Expand Up @@ -244,16 +248,22 @@ function App() {
// newFlash["loanAmount"] = !flash["loanAmount"];
} else if (field == "insurance") {
newUserInput.insurance = value;
if (newChosenInput == "homeVal") newFlash["loanAmount"] = !newFlash["loanAmount"];
} else if (field == "insuranceUnit") {
newUserInput.insuranceUnit = value;
if (newChosenInput == "homeVal") newFlash["loanAmount"] = !newFlash["loanAmount"];
} else if (field == "hoa") {
newUserInput.hoa = value;
if (newChosenInput == "homeVal") newFlash["loanAmount"] = !newFlash["loanAmount"];
} else if (field == "hoaUnit") {
newUserInput.hoaUnit = value;
if (newChosenInput == "homeVal") newFlash["loanAmount"] = !newFlash["loanAmount"];
} else if (field == "propertyTax") {
newUserInput.propertyTax = value;
if (newChosenInput == "homeVal") newFlash["loanAmount"] = !newFlash["loanAmount"];
} else if (field == "propertyTaxUnit") {
newUserInput.propertyTaxUnit = value;
if (newChosenInput == "homeVal") newFlash["loanAmount"] = !newFlash["loanAmount"];
} else if (field == "startDate") {
newUserInput.startDate = value;
}
Expand Down Expand Up @@ -359,7 +369,7 @@ function App() {
<nav className="navbar bg-body-tertiary mb-2">
<div className="container-xxl">
<a className="navbar-brand" href="#">
<b>t</b>he <b>R</b>eally <b>G</b>ood <b>M</b>ortgage <b>C</b>alculator
the <b>R</b>eally <b>G</b>ood <b>M</b>ortgage <b>C</b>alculator <small>.net</small>
</a>
</div>
</nav>
Expand All @@ -380,7 +390,7 @@ function App() {
monthlyPaymentPerEvent={loanRes["monthlyPaymentPerEvent"]}
/>

<LoanStats loanRes={loanRes} loanEvent={loanEvent} />
<LoanStats loanRes={loanRes} loanEvent={loanEvent} userInput={userInput} />
</div>
<div className="col-md-7 col-12">
<LoanPlot
Expand All @@ -390,11 +400,12 @@ function App() {
propertyTax={userInput["propertyTax"] * unitScaler(userInput["propertyTaxUnit"])}
hoa={userInput["hoa"] * unitScaler(userInput["hoaUnit"])}
insurance={userInput["insurance"] * unitScaler(userInput["insuranceUnit"])}
startDate={new Date(Number(userInput["startDate"]))}
/>
</div>
</div>
<div className="row">
<p>Leave some feedback!</p>
<p>It would be great to hear your feedback!</p>
</div>
<div className="row">
<Comments website-id={11189} page-id="" />
Expand Down
24 changes: 12 additions & 12 deletions trgmc/src/EventsForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function EventsForm({ loanMonths, loanEvent, setLoanEvent, monthlyPaymentPerEven
const [newChange, setNewChange] = useState(1000);
const [chosenDate, setChosenDate] = useState(loanMonths[1]);
const [newLength, setNewLength] = useState(0);
const [cost, setCost] = useState(100);
const [cost, setCost] = useState(0);

//prevent hanging when url params set up illegal state
if (loanMonths.length < 2) return null;
Expand Down Expand Up @@ -279,7 +279,7 @@ function EventsForm({ loanMonths, loanEvent, setLoanEvent, monthlyPaymentPerEven
maximumFractionDigits: 0,
}).format(x["cost"])}
</td>
<td>{`${x["change"]}${x["event"] == "Refinance" ? "%" : ""}`}</td>
<td>{x["event"] == "Refinance" ? `${x["change"]}%` : x["event"] == "Over-payment" ? cashFormat(x["change"]) : x["change"]}</td>
<td key="pen">
<span
style={{ cursor: "pointer" }}
Expand Down Expand Up @@ -316,16 +316,16 @@ function EventsForm({ loanMonths, loanEvent, setLoanEvent, monthlyPaymentPerEven
</td>
</tr>
{x["event"] == "Refinance" ? (
<>
<tr key={"refi1"}>
<td></td>
<td colSpan={5}>New loan length: {x["newLength"] == "" ? <em>unchanged</em> : `${x["newLength"]}yr`}</td>
</tr>
<tr key={"refi2"}>
<td></td>
<td colSpan={5}>New monthly payment: {cashFormat(monthlyPaymentPerEvent[i + 1])}</td>
</tr>
</>
<tr key={"refi1"}>
<td></td>
<td colSpan={5}>New loan length: {x["newLength"] == "" ? <em>unchanged</em> : `${x["newLength"]}yr`}</td>
</tr>
) : null}
{x["event"] == "Refinance" || x["event"] == "Recast" ? (
<tr key={"refi2"}>
<td></td>
<td colSpan={5}>New monthly payment: {cashFormat(monthlyPaymentPerEvent[i + 1])}</td>
</tr>
) : null}
</tbody>
))}
Expand Down
1 change: 0 additions & 1 deletion trgmc/src/LoanForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ function ValidFbComp({ x }) {
function LoanForm({ displayState, flash, updateUserInput, valid }) {
const [show, setShow] = useState(false);
const feeOptions = ["$ / year", "$ / month", "% / year", "% / month"];
// const loanAmount = displayState["loanAmount"];

// var validClass = {};
// for (const i in valid) validClass[i] = valid[i] === null ? null : "is-invalid";
Expand Down
76 changes: 53 additions & 23 deletions trgmc/src/LoanPlot.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,59 @@ import { useState } from "react";
// BarController
// );

function LoanPlot({ maxMonthly, loanRes, loanMonths, propertyTax, hoa, insurance }) {
const [monthsPerYearToPlot, setMonthsPerYearToPlot] = useState(1);
const indexPlot = 12 / monthsPerYearToPlot;
function LoanPlot({ maxMonthly, loanRes, loanMonths, propertyTax, hoa, insurance, startDate }) {
const [monthsPerYearToPlot, setMonthsPerYearToPlot] = useState("yearly payments");
const indexPlot = monthsPerYearToPlot == "monthly payments" ? 1 : 12;
const yTitle = monthsPerYearToPlot == "monthly payments" ? "Monthly Payments" : "Yearly Payments";
const startMonth = startDate.getMonth();
// console.log(startDate, startMonth)

// console.log('rem',loanRes["remaining"])
var monthlyPrincipalFiltered;
var monthlyInterestFiltered;
var loanMonthsFiltered;
var remainingFiltered;

var loanMonthsFiltered = loanMonths.filter(function (element, index) {
return index % indexPlot === 0;
});
var monthlyPrincipalFiltered = loanRes["monthlyPrincipal"].filter(function (element, index) {
return index % indexPlot === 0;
});
var monthlyInterestFiltered = loanRes["monthlyInterest"].filter(function (element, index) {
return index % indexPlot === 0;
});
// var monthlyTaxFiltered = loanRes["monthlyTax"].filter(function (element, index, array) {
// return index % indexPlot === 0;
// });
var remainingFiltered = loanRes["remaining"].filter(function (element, index) {
return index % indexPlot === 0;
});
if (monthsPerYearToPlot == "monthly payments") {
loanMonthsFiltered = loanMonths;
monthlyPrincipalFiltered = loanRes["monthlyPrincipal"];
monthlyInterestFiltered = loanRes["monthlyInterest"];
remainingFiltered = loanRes["remaining"];
} else {
// var loanMonthsFiltered = [0]
monthlyPrincipalFiltered = [0];
monthlyInterestFiltered = [0];
// var remainingFiltered = [0]

var loanMonthsFiltered_full = loanMonths.filter(function (element, index) {
return index % 12 === 0;
});
loanMonthsFiltered = loanMonthsFiltered_full.map((d) => d.substring(4, 8));
remainingFiltered = loanRes["remaining"].filter(function (element, index) {
return index % indexPlot === 0;
});

for (var i = 0; i < loanMonths.length; i++) {
var yearIndex = Math.floor((startMonth + i) / 12);
// console.log(yearIndex)
// if ((yearIndex==0) || (i==0)) {
// monthlyPrincipalFiltered.push(0);// = 0
// monthlyInterestFiltered[yearIndex] = 0
// }
if (yearIndex >= monthlyPrincipalFiltered.length) monthlyPrincipalFiltered.push(0);
if (yearIndex >= monthlyInterestFiltered.length) monthlyInterestFiltered.push(0);
monthlyPrincipalFiltered[yearIndex] = monthlyPrincipalFiltered[yearIndex] + loanRes["monthlyPrincipal"][i];
monthlyInterestFiltered[yearIndex] = monthlyInterestFiltered[yearIndex] + loanRes["monthlyInterest"][i];
}
// console.log(yearIndex, loanRes["monthlyPrincipal"], loanRes["monthlyInterest"])

// var monthlyPrincipalFiltered = loanRes["monthlyPrincipal"].filter(function (element, index) {
// return index % indexPlot === 0;
// });
// var monthlyInterestFiltered = loanRes["monthlyInterest"].filter(function (element, index) {
// return index % indexPlot === 0;
// });
}

const DEFAULT_PLOTLY_COLORS = [
"rgba(31, 119, 180, 0.6)",
Expand Down Expand Up @@ -126,7 +158,7 @@ function LoanPlot({ maxMonthly, loanRes, loanMonths, propertyTax, hoa, insurance
// return '$' + value;
},
},
title: { text: "Monthly Payments", display: true },
title: { text: yTitle, display: true },
},
x1: {
ticks: {
Expand Down Expand Up @@ -192,7 +224,7 @@ function LoanPlot({ maxMonthly, loanRes, loanMonths, propertyTax, hoa, insurance
<div className="col-12 px-0">
<div className="input-group ">
<span className="pe-3">Show: </span>
{[1, 2, 12].map((x) => (
{["monthly payments", "yearly payments"].map((x) => (
<div className="form-check form-check-inline" key={x}>
<input
className="form-check-input"
Expand All @@ -202,9 +234,7 @@ function LoanPlot({ maxMonthly, loanRes, loanMonths, propertyTax, hoa, insurance
value={x}
onChange={() => setMonthsPerYearToPlot(x)}
/>
<label className="form-check-label">
{x} month{x > 1 ? "s" : null} per year
</label>
<label className="form-check-label">{x}</label>
</div>
))}
</div>
Expand Down
Loading

0 comments on commit 48f1944

Please sign in to comment.