JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
CSS
html,
body {
width: 100%;
height: 100%;
margin: 0;
}
JavaScript
import { h, Component, render } from "https://esm.sh/preact";
import { signal, computed } from "https://esm.sh/@preact/signals";
import htm from "https://esm.sh/htm";
const html = htm.bind(h);
const rate = signal(7);
const payment = signal(500);
function balance(amount, rate, payment, years) {
return (
amount * (1 + rate / 12) ** (12 * years) -
payment * (((1 + rate / 12) ** (12 * years) - 1) / (rate / 12))
);
}
const balanceValues = computed(() => {
let values = [];
for (let year = 0; year <= 15; year++) {
values.push([year, balance(50000, rate.value / 100, payment.value, year)]);
}
return values;
});
const balancePolylineStr = computed(() => {
let xRange = [0, 400];
let yRange = [0, 400];
let yearRange = [0, 15];
let balanceRange = [0, 50000];
const mapRange = (value, valueRange, targetRange) => {
const t = (value - valueRange[0]) / (valueRange[1] - valueRange[0]);
return t * (targetRange[1] - targetRange[0]) + targetRange[0];
};
return balanceValues.value
.map(([year, balance]) => {
const x = mapRange(year, yearRange, xRange);
const y = mapRange(balance, balanceRange, yRange);
return `${x},${400 - y}`;
})
.join(" ");
});
const yearsToPayOff = computed(() => {
if (payment.value <= (50000 * rate.value) / 12 / 100) {
return "NEVER";
}
const months =
Math.log(
payment.value / (payment.value - (50000 * rate.value) / 12 / 100)
) / Math.log(1 + rate.value / 12 / 100);
return months / 12;
});
function App(props) {
return html`
<div>
<input
type="range"
min="2"
max="12"
step="0.1"
value=${rate}
onInput=${(event) => {
rate.value = Number(event.target.value);
}}
/>
Rate: ${rate}%
</div>
`;
return html`
<div>Loan amount: $50,000</div>
<div>
<input
type="range"
min="2"
max="12"
step="0.1"
value=${rate}
...