APR Calculator code
APR Calculator code
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;
}
.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;
}
}
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="chart-wrapper">
<canvas id="breakdownChart"></canvas>
</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;
// 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;
}
// 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)}`;
// 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>