<div class="container">
	<div class="header">
		<h1 style="color: #6258A8">Loan Calculator</h1>
		<button>
			<i class="bi bi-list"></i>
		</button>
	</div>
	<div class="sub-container">
		<div class="view">
			<div class="details">
				<div>
					<div class="detail">
						<p style="color: #9088D2">Amount</p>
						<p id="loan-amt-text" style="color: #6258A8"></p>
					</div>
					<input type="range" id="loan-amount" min="0" max="10000000" step="50000">
				</div>
				<div>
					<div class="detail">
						<p style="color: #9088D2">Length</p>
						<p id="loan-period-text" style="color: #6258A8"></p>
					</div>
					<input type="range" id="loan-period" min="1" max="30" step="1">
				</div>
				<div>
					<div class="detail">
						<p style="color: #9088D2">% Interest</p>
						<p id="interest-rate-text" style="color: #6258A8"></p>
					</div>
					<input type="range" id="interest-rate" min="1" max="15" step="0.5">
				</div>
			</div>
			<div class="footer">
				<p id="price-container"><span id="price">0</span>/mo</p>
			</div>
		</div>
		<div class="breakup">
			<canvas id="pieChart"></canvas>
		</div>
	</div>
	<div>
		<div class="loan-details">
			<div class='chart-details'>
				<p style="color: #9088D2">Principal</p>
				<p id="cp" style="color: #130F31; font-size: 17px;"></p>
			</div>
			<div class='chart-details'>
				<p style="color: #9088D2">Interest</p>
				<p id="ci" style="color: #130F31; font-size: 17px;"></p>
			</div>
			<div class='chart-details'>
				<p style="color: #9088D2">Total Payable</p>
				<p id="ct" style="color: #130F31; font-size: 17px;"></p>
			</div>
		</div>
		<canvas id="lineChart" height="200px" width="200px"></canvas>
	</div>
</div>
body {
	font-family: "Open Sans", sans-serif;
	font-size: 15px;
	height: 100%;
	width: 100%;
	display: flex;
	justify-content: center;
	align-items: center;
	background-color: #bab5e3;
}

.container {
	height: auto;
	width: 700px;
	border-radius: 20px;
	padding: 20px;
	margin: 50px 0;
	background-image: linear-gradient(to bottom left, #e4dfec, white, white);
}
.sub-container {
	display: flex;
	width: 100%;
	gap: 50px;
	height: max-content;
}

.header {
	width: 100%;
	height: auto;
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 30px;
}

.header button {
	height: max-content;
	width: max-content;
	padding: 10px;
	border: none;
	background-color: transparent;
	font-size: 35px;
	color: #9088d2;
}

.header button:hover {
	cursor: pointer;
}

.view,
.breakup {
	width: 50%;
}
.details input {
	width: 100%;
}

.detail {
	display: flex;
	justify-content: space-between;
}

.footer {
	display: flex;
	justify-content: space-between;
}

/*----- Styling the sliders ----*/
input[type="range"] {
	-webkit-appearance: none;
	margin: 10px 0;
	width: 100%;
}

input[type="range"]:focus {
	outline: none;
}

input[type="range"]::-webkit-slider-runnable-track {
	width: 100%;
	height: 6px;
	cursor: pointer;
	background: #9088d2;
	border-radius: 10px;
}

input[type="range"]::-webkit-slider-thumb {
	box-shadow: 2px 2px 5px #b3b3b3, -1px -1px 3px grey;
	border: 5px solid #ffffff;
	height: 20px;
	width: 20px;
	border-radius: 50%;
	background: #9088d2;
	cursor: pointer;
	margin-top: -6px;
	-webkit-appearance: none;
}

input[type="range"]:focus::-webkit-slider-runnable-track {
	background: #b3b3b3;
}

input[type="range"]::-moz-range-track {
	width: 100%;
	height: 6px;
	cursor: pointer;
	background: #9088d2;
	border-color: transparent;
	border-width: 16px 0;
	color: transparent;
	border-radius: 10px;
}

input[type="range"]::-moz-range-thumb {
	box-shadow: 2px 2px 5px #b3b3b3, -1px -1px 3px grey;
	border: 5px solid #ffffff;
	height: 20px;
	width: 20px;
	border-radius: 50%;
	background: #9088d2;
	cursor: pointer;
	margin-top: -6px;
}

input[type="range"]::-ms-track {
	width: 100%;
	height: 6px;
	cursor: pointer;
	background: #9088d2;
	border-color: transparent;
	border-width: 16px 0;
	color: transparent;
	border-radius: 10px;
}

input[type="range"]::-ms-fill-lower {
	background: #9088d2;
	border-radius: 5px;
}

input[type="range"]::-ms-fill-upper {
	background: #9088d2;
	border-radius: 5px;
}

input[type="range"]::-ms-thumb {
	box-shadow: 2px 2px 5px #b3b3b3, -1px -1px 3px grey;
	border: 5px solid #ffffff;
	height: 20px;
	width: 20px;
	border-radius: 50%;
	background: #9088d2;
	cursor: pointer;
	margin-top: -6px;
}

input[type="range"]:focus::-ms-fill-lower {
	background: #9088d2;
}

input[type="range"]:focus::-ms-fill-upper {
	background: #9088d2;
}

/*-------------------------------------*/
#price {
	color: #130f31;
	font-size: 25px;
}

.loan-details {
	width: 90%;
	display: flex;
	justify-content: space-between;
	gap: 30px;
}

#price-container {
	color: #9088d2;
	margin-top: 50px;
}

#price-container::before {
	content: "Monthly Payable:";
	font-size: 12px;
	display: block;
}
var P, R, N, pie, line;
var loan_amt_slider = document.getElementById("loan-amount");
var int_rate_slider = document.getElementById("interest-rate");
var loan_period_slider = document.getElementById("loan-period");

// update loan amount
loan_amt_slider.addEventListener("input", (self) => {
	document.querySelector("#loan-amt-text").innerText =
		parseInt(self.target.value).toLocaleString("en-US") + "$";
	P = parseFloat(self.target.value);
	displayDetails();
});

// update Rate of Interest
int_rate_slider.addEventListener("input", (self) => {
	document.querySelector("#interest-rate-text").innerText =
		self.target.value + "%";
	R = parseFloat(self.target.value);
	displayDetails();
});

// update loan period
loan_period_slider.addEventListener("input", (self) => {
	document.querySelector("#loan-period-text").innerText =
		self.target.value + " years";
	N = parseFloat(self.target.value);
	displayDetails();
});

// calculate total Interest payable
function calculateLoanDetails(p, r, emi) {
	/*
		p: principal
		r: rate of interest
		emi: monthly emi
	*/
	let totalInterest = 0;
	let yearlyInterest = [];
	let yearPrincipal = [];
	let years = [];
	let year = 1;
	let [counter, principal, interes] = [0, 0, 0];
	while (p > 0) {
		let interest = parseFloat(p) * parseFloat(r);
		p = parseFloat(p) - (parseFloat(emi) - interest);
		totalInterest += interest;
		principal += parseFloat(emi) - interest;
		interes += interest;
		if (++counter == 12) {
			years.push(year++);
			yearlyInterest.push(parseInt(interes));
			yearPrincipal.push(parseInt(principal));
			counter = 0;
		}
	}
	line.data.datasets[0].data = yearPrincipal;
	line.data.datasets[1].data = yearlyInterest;
	line.data.labels = years;
	return totalInterest;
}

// calculate details
function displayDetails() {
	let r = parseFloat(R) / 1200;
	let n = parseFloat(N) * 12;

	let num = parseFloat(P) * r * Math.pow(1 + r, n);
	let denom = Math.pow(1 + r, n) - 1;
	let emi = parseFloat(num) / parseFloat(denom);

	let payabaleInterest = calculateLoanDetails(P, r, emi);

	let opts = '{style: "decimal", currency: "US"}';

	document.querySelector("#cp").innerText =
		parseFloat(P).toLocaleString("en-US", opts) + "$";

	document.querySelector("#ci").innerText =
		parseFloat(payabaleInterest).toLocaleString("en-US", opts) + "$";

	document.querySelector("#ct").innerText =
		parseFloat(parseFloat(P) + parseFloat(payabaleInterest)).toLocaleString(
			"en-US",
			opts
		) + "$";

	document.querySelector("#price").innerText =
		parseFloat(emi).toLocaleString("en-US", opts) + "$";

	pie.data.datasets[0].data[0] = P;
	pie.data.datasets[0].data[1] = payabaleInterest;
	pie.update();
	line.update();
}

// Initialize everything
function initialize() {
	document.querySelector("#loan-amt-text").innerText =
		parseInt(loan_amt_slider.value).toLocaleString("en-US") + "$";
	P = parseFloat(document.getElementById("loan-amount").value);

	document.querySelector("#interest-rate-text").innerText =
		int_rate_slider.value + "%";
	R = parseFloat(document.getElementById("interest-rate").value);

	document.querySelector("#loan-period-text").innerText =
		loan_period_slider.value + " years";
	N = parseFloat(document.getElementById("loan-period").value);

	line = new Chart(document.getElementById("lineChart"), {
		data: {
			datasets: [
				{
					type: "line",
					label: "Yearly Principal paid",
					borderColor: "rgb(54, 162, 235)",
					data: []
				},
				{
					type: "line",
					label: "Yearly Interest paid",
					borderColor: "rgb(255, 99, 132)",
					data: []
				}
			],
			labels: []
		},
		options: {
			plugins: {
				title: {
					display: true,
					text: "Yearly Payment Breakdown"
				}
			},
			scales: {
				x: {
					title: {
						color: "grey",
						display: true,
						text: "Years Passed"
					}
				},
				y: {
					title: {
						color: "grey",
						display: true,
						text: "Money in Rs."
					}
				}
			}
		}
	});

	pie = new Chart(document.getElementById("pieChart"), {
		type: "doughnut",
		data: {
			labels: ["Principal", "Interest"],
			datasets: [
				{
					label: "Home Loan Details",
					data: [0, 0],
					backgroundColor: ["rgb(54, 162, 235)", "rgb(255, 99, 132)"],
					hoverOffset: 4
				}
			]
		},
		options: {
			plugins: {
				title: {
					display: true,
					text: "Payment Breakup"
				}
			}
		}
	});
	displayDetails();
}
initialize();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.2.0/chart.min.js