0% found this document useful (0 votes)
7 views

APR Calculator code

The document is an HTML template for a General APR Calculator, featuring input fields for loan amount, term, interest rate, and fees. It includes a responsive design with sections for input, results, and an amortization table, along with JavaScript functions to calculate APR and display results. The layout is styled with CSS for a clean and user-friendly interface, utilizing Chart.js for visual representation of data.

Uploaded by

bestcool06
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

APR Calculator code

The document is an HTML template for a General APR Calculator, featuring input fields for loan amount, term, interest rate, and fees. It includes a responsive design with sections for input, results, and an amortization table, along with JavaScript functions to calculate APR and display results. The layout is styled with CSS for a clean and user-friendly interface, utilizing Chart.js for visual representation of data.

Uploaded by

bestcool06
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 16

<!

DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>APR Calculator</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0"></script>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

body {
background: linear-gradient(135deg, #e6f0fa 0%, #f3f5f9 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}

.calculator-container {
background: white;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
padding: 30px;
width: 100%;
max-width: 900px;
border: 1px solid #e0e4e8;
}

h1 {
color: #0a47b6;
text-align: center;
margin-bottom: 25px;
font-size: clamp(1.8rem, 5vw, 2.2rem);
font-weight: 600;
letter-spacing: 1px;
}
.main-content {
display: flex;
gap: 30px;
flex-wrap: wrap;
justify-content: center;
}

.input-section, .result-section {
flex: 1;
min-width: 300px;
background: #f8f9fa;
border-radius: 10px;
padding: 20px;
box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.05);
}

.input-group {
margin-bottom: 20px;
}

label {
display: block;
color: #333;
font-weight: 500;
font-size: clamp(0.9rem, 2.5vw, 1rem);
margin-bottom: 8px;
}

input, select {
width: 100%;
padding: 10px 15px;
border: 2px solid #d0d4d8;
border-radius: 8px;
font-size: clamp(0.9rem, 2.5vw, 1rem);
transition: border-color 0.3s ease, box-shadow 0.3s ease;
}

input:focus, select:focus {
outline: none;
border-color: #0a47b6;
box-shadow: 0 0 5px rgba(10, 71, 182, 0.2);
}

.input-row {
display: flex;
gap: 15px;
}

.input-row .input-group {
flex: 1;
}

.button-group {
display: flex;
gap: 15px;
justify-content: center;
margin-top: 20px;
}

.calculate-btn, .clear-btn {
padding: 12px 30px;
border: none;
border-radius: 8px;
font-size: clamp(0.9rem, 2.5vw, 1rem);
font-weight: bold;
cursor: pointer;
transition: transform 0.2s ease, background 0.3s ease, box-shadow 0.3s ease;
}

.calculate-btn {
background: #0a47b6;
color: #FFFFFF;
}

.calculate-btn:hover {
background: #083894;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(10, 71, 182, 0.3);
}

.clear-btn {
background: #e0e4e8;
color: #333;
}

.clear-btn:hover {
background: #d0d4d8;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}

.result-section h2 {
color: #0a47b6;
font-size: clamp(1.2rem, 4vw, 1.5rem);
margin-bottom: 15px;
text-align: center;
}

.result-section h3 {
color: #2e7d32;
font-size: clamp(1.5rem, 5vw, 1.8rem);
margin-bottom: 20px;
text-align: center;
background: #e8f5e9;
padding: 10px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}

.result-items {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
margin-bottom: 20px;
}

.result-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
border-bottom: 1px solid #e0e4e8;
font-size: clamp(0.9rem, 2.5vw, 1rem);
color: #333;
transition: background 0.3s ease;
}

.result-item:last-child {
border-bottom: none;
}
.result-item:hover {
background: #f1f5f9;
}

.result-item span {
color: #0a47b6;
font-weight: 600;
font-size: clamp(1rem, 2.5vw, 1.1rem);
}

.result-item .label {
font-weight: 500;
color: #555;
}

.chart-wrapper {
margin-top: 20px;
text-align: center;
}

canvas {
max-width: 200px;
margin: 0 auto;
}

.toggle-table {
display: block;
margin: 20px auto 0;
color: #0a47b6;
font-size: clamp(0.9rem, 2.5vw, 1rem);
text-decoration: underline;
cursor: pointer;
background: none;
border: none;
}

.table-container {
margin-top: 20px;
max-height: 300px;
overflow-y: auto;
display: none;
}

table {
width: 100%;
border-collapse: collapse;
font-size: clamp(0.8rem, 2vw, 0.9rem);
}

th, td {
padding: 10px;
text-align: center;
border: 1px solid #e0e4e8;
}

th {
background: #0a47b6;
color: #FFFFFF;
font-weight: bold;
position: sticky;
top: 0;
z-index: 1;
}

tr:nth-child(even) {
background: #f8f9fa;
}

tr:hover {
background: #e0e4e8;
}

@media (max-width: 768px) {


.main-content {
flex-direction: column;
align-items: center;
}

.input-section, .result-section {
min-width: 100%;
}

.input-row {
flex-direction: column;
gap: 10px;
}

.button-group {
flex-direction: column;
gap: 10px;
}

.calculate-btn, .clear-btn {
padding: 12px;
width: 100%;
max-width: 300px;
}

.table-container {
margin: 0 -20px;
padding: 0 20px;
}

.result-items {
padding: 15px;
}

.result-item {
flex-direction: column;
align-items: flex-start;
gap: 5px;
padding: 15px 0;
}
}

@media (max-width: 480px) {


.calculator-container {
padding: 20px;
}

h1 {
font-size: clamp(1.5rem, 5vw, 1.8rem);
}

.result-section h3 {
font-size: clamp(1.2rem, 4vw, 1.5rem);
}

th, td {
padding: 8px;
}
.result-item span {
font-size: clamp(0.9rem, 2vw, 1rem);
}
}
</style>
</head>
<body>
<div class="calculator-container">
<h1>General APR Calculator</h1>

<div class="main-content">
<div class="input-section">
<div class="input-group">
<label for="loanAmount">Loan Amount</label>
<input type="number" id="loanAmount" placeholder="Enter loan amount"
step="0.01">
</div>

<div class="input-row">
<div class="input-group">
<label for="years">Loan Term (Years)</label>
<input type="number" id="years" placeholder="Years" step="1">
</div>
<div class="input-group">
<label for="months">Loan Term (Months)</label>
<input type="number" id="months" placeholder="Months" step="1">
</div>
</div>

<div class="input-group">
<label for="interestRate">Interest Rate</label>
<input type="number" id="interestRate" placeholder="Enter interest rate"
step="0.01">
</div>

<div class="input-group">
<label for="compoundFrequency">Compound</label>
<select id="compoundFrequency">
<option value="daily">Daily</option>
<option value="bi-weekly">Bi-Weekly</option>
<option value="semi-monthly">Semi-Monthly</option>
<option value="monthly" selected>Monthly</option>
<option value="quarterly">Quarterly</option>
<option value="semi-annual">Semi-Annual</option>
<option value="annual">Annual</option>
<option value="continuous">Continuous</option>
</select>
</div>

<div class="input-group">
<label for="paymentFrequency">Pay Back</label>
<select id="paymentFrequency">
<option value="daily">Every Day</option>
<option value="bi-weekly">Every Bi-Week</option>
<option value="semi-monthly">Every Semi-Month</option>
<option value="monthly" selected>Every Month</option>
<option value="quarterly">Every Quarter</option>
<option value="semi-annual">Every Semi-Year</option>
<option value="annual">Every Year</option>
</select>
</div>

<div class="input-group">
<label for="loanedFees">Loaned Fees</label>
<input type="number" id="loanedFees" placeholder="Enter loaned fees"
step="0.01">
</div>

<div class="input-group">
<label for="upfrontFees">Upfront Fees</label>
<input type="number" id="upfrontFees" placeholder="Enter upfront fees"
step="0.01">
</div>

<div class="button-group">
<button class="calculate-btn" onclick="calculateAPR()">Calculate</button>
<button class="clear-btn" onclick="clearForm()">Clear</button>
</div>
</div>

<div class="result-section" id="results" style="display: none;">


<h3 id="realAPR">Real APR: 0.0000%</h3>
<div class="result-items">
<div class="result-item">
<span class="label">Amount Financed:</span>
<span id="amountFinanced">$0.00</span>
</div>
<div class="result-item">
<span class="label">Upfront Out-of-Pocket Fees:</span>
<span id="upfrontFeesResult">$0.00</span>
</div>
<div class="result-item">
<span class="label">Payment Every <span
id="paymentFrequencyResult"></span>:</span>
<span id="paymentAmount">$0.00</span>
</div>
<div class="result-item">
<span class="label">Total of <span id="totalPayments"></span>
Payments:</span>
<span id="totalPaymentsAmount">$0.00</span>
</div>
<div class="result-item">
<span class="label">Total Interest:</span>
<span id="totalInterest">$0.00</span>
</div>
<div class="result-item">
<span class="label">All Payments and Fees:</span>
<span id="allPaymentsFees">$0.00</span>
</div>
</div>

<div class="chart-wrapper">
<canvas id="breakdownChart"></canvas>
</div>

<button class="toggle-table" onclick="toggleTable()">View Amortization


Table</button>
<div class="table-container" id="amortizationTable">
<table>
<thead>
<tr>
<th>Payment #</th>
<th>Payment Amount ($)</th>
<th>Interest Paid ($)</th>
<th>Principal Paid ($)</th>
<th>Remaining Balance ($)</th>
</tr>
</thead>
<tbody id="amortizationTableBody"></tbody>
</table>
</div>
</div>
</div>
</div>

<script>
let breakdownChart;

function calculateAPR() {
// Get input values
const loanAmount = parseFloat(document.getElementById('loanAmount').value);
const years = parseInt(document.getElementById('years').value) || 0;
const months = parseInt(document.getElementById('months').value) || 0;
const interestRate = parseFloat(document.getElementById('interestRate').value);
const compoundFrequency = document.getElementById('compoundFrequency').value;
const paymentFrequency = document.getElementById('paymentFrequency').value;
const loanedFees = parseFloat(document.getElementById('loanedFees').value) || 0;
const upfrontFees = parseFloat(document.getElementById('upfrontFees').value) || 0;

// Calculate total months based on payment frequency


const periodsPerYear = {
'daily': 365,
'bi-weekly': 26,
'semi-monthly': 24,
'monthly': 12,
'quarterly': 4,
'semi-annual': 2,
'annual': 1
};

const paymentPeriodsPerYear = periodsPerYear[paymentFrequency];


const totalPayments = (years * paymentPeriodsPerYear) + (months *
(paymentPeriodsPerYear / 12));

// Validation
if (isNaN(loanAmount) || isNaN(interestRate) || isNaN(totalPayments) ||
loanAmount <= 0 || interestRate < 0 || totalPayments <= 0) {
alert('Please enter valid positive numbers for loan amount, interest rate, and loan
term');
return;
}

// Convert interest rate to match payment frequency


const compoundPeriodsPerYear = periodsPerYear[compoundFrequency] || Infinity;
let effectiveRatePerPeriod;
if (compoundFrequency === 'continuous') {
const ear = Math.exp(interestRate / 100) - 1;
effectiveRatePerPeriod = Math.pow(1 + ear, 1 / paymentPeriodsPerYear) - 1;
} else {
const ear = Math.pow(1 + (interestRate / 100) / compoundPeriodsPerYear,
compoundPeriodsPerYear) - 1;
effectiveRatePerPeriod = Math.pow(1 + ear, 1 / paymentPeriodsPerYear) - 1;
}

// Calculate monthly payment


const monthlyPayment = loanAmount * effectiveRatePerPeriod * Math.pow(1 +
effectiveRatePerPeriod, totalPayments) /
(Math.pow(1 + effectiveRatePerPeriod, totalPayments) - 1);

// Calculate total payments and interest


const totalPaid = monthlyPayment * totalPayments;
const totalInterest = totalPaid - loanAmount;

// Adjust for fees to calculate APR


const amountFinanced = loanAmount - upfrontFees;
const totalCost = totalPaid + loanedFees + upfrontFees;

// Calculate APR using binary search


let low = 0;
let high = 100;
let apr = 0;
const precision = 0.0001;
let calculatedPayment;

for (let i = 0; i < 100; i++) {


apr = (low + high) / 2;
const aprRatePerPeriod = apr / 100 / paymentPeriodsPerYear;
calculatedPayment = amountFinanced * aprRatePerPeriod * Math.pow(1 +
aprRatePerPeriod, totalPayments) /
(Math.pow(1 + aprRatePerPeriod, totalPayments) - 1);
const totalWithAPR = calculatedPayment * totalPayments + loanedFees +
upfrontFees;

if (Math.abs(totalWithAPR - totalCost) < precision) {


break;
}

if (totalWithAPR > totalCost) {


high = apr;
} else {
low = apr;
}
}

// Amortization schedule
let balance = loanAmount;
let cumulativeInterest = 0;
const amortizationData = [];
for (let i = 1; i <= totalPayments; i++) {
const interest = balance * effectiveRatePerPeriod;
const principal = monthlyPayment - interest;
balance -= principal;
cumulativeInterest += interest;
if (balance < 0) balance = 0;

amortizationData.push({
paymentNumber: i,
paymentAmount: monthlyPayment.toFixed(2),
interestPaid: interest.toFixed(2),
principalPaid: principal.toFixed(2),
remainingBalance: balance.toFixed(2)
});
}

// Display results
document.getElementById('realAPR').textContent = `Real APR: ${apr.toFixed(4)}%`;
document.getElementById('amountFinanced').textContent = `$$
{amountFinanced.toFixed(2)}`;
document.getElementById('upfrontFeesResult').textContent = `$$
{upfrontFees.toFixed(2)}`;
document.getElementById('paymentFrequencyResult').textContent =
paymentFrequency.charAt(0).toUpperCase() + paymentFrequency.slice(1);
document.getElementById('paymentAmount').textContent = `$$
{monthlyPayment.toFixed(2)}`;
document.getElementById('totalPayments').textContent = totalPayments;
document.getElementById('totalPaymentsAmount').textContent = `$$
{totalPaid.toFixed(2)}`;
document.getElementById('totalInterest').textContent = `$${totalInterest.toFixed(2)}`;
document.getElementById('allPaymentsFees').textContent = `$${totalCost.toFixed(2)}`;

// Populate amortization table


const tableBody = document.getElementById('amortizationTableBody');
tableBody.innerHTML = '';
amortizationData.forEach(row => {
const tr = document.createElement('tr');
tr.innerHTML = `
<td>${row.paymentNumber}</td>
<td>$${row.paymentAmount}</td>
<td>$${row.interestPaid}</td>
<td>$${row.principalPaid}</td>
<td>$${row.remainingBalance}</td>
`;
tableBody.appendChild(tr);
});

// Destroy previous chart if it exists


if (breakdownChart) breakdownChart.destroy();

// Create breakdown chart


const ctx = document.getElementById('breakdownChart').getContext('2d');
breakdownChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ['Principal', 'Interest', 'Fees'],
datasets: [{
data: [loanAmount, totalInterest, loanedFees + upfrontFees],
backgroundColor: ['#1E90FF', '#2E7D32', '#D32F2F']
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right'
},
tooltip: {
callbacks: {
label: function(context) {
const label = context.label || '';
const value = context.raw || 0;
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return `${label}: $${value.toFixed(2)} (${percentage}%)`;
}
}
},
datalabels: {
color: '#fff',
formatter: (value, context) => {
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return `${percentage}%`;
},
font: {
weight: 'bold',
size: 14
}
}
}
},
plugins: [ChartDataLabels]
});

// Show results
document.getElementById('results').style.display = 'block';
}

function toggleTable() {
const table = document.getElementById('amortizationTable');
const button = document.querySelector('.toggle-table');
if (table.style.display === 'none' || table.style.display === '') {
table.style.display = 'block';
button.textContent = 'Hide Amortization Table';
} else {
table.style.display = 'none';
button.textContent = 'View Amortization Table';
}
}

function clearForm() {
document.getElementById('loanAmount').value = '';
document.getElementById('years').value = '';
document.getElementById('months').value = '';
document.getElementById('interestRate').value = '';
document.getElementById('compoundFrequency').value = 'monthly';
document.getElementById('paymentFrequency').value = 'monthly';
document.getElementById('loanedFees').value = '';
document.getElementById('upfrontFees').value = '';
document.getElementById('results').style.display = 'none';
document.getElementById('amortizationTable').style.display = 'none';
document.querySelector('.toggle-table').textContent = 'View Amortization Table';
if (breakdownChart) breakdownChart.destroy();
}
</script>
</body>
</html>

You might also like