0% found this document useful (0 votes)
3 views16 pages

General APR Calculator Tool

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)
3 views16 pages

General APR Calculator Tool

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

<!

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="[Link]
<script src="[Link]
<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([Link]('loanAmount').value);
const years = parseInt([Link]('years').value) || 0;
const months = parseInt([Link]('months').value) || 0;
const interestRate = parseFloat([Link]('interestRate').value);
const compoundFrequency = [Link]('compoundFrequency').value;
const paymentFrequency = [Link]('paymentFrequency').value;
const loanedFees = parseFloat([Link]('loanedFees').value) || 0;
const upfrontFees = parseFloat([Link]('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 = [Link](interestRate / 100) - 1;
effectiveRatePerPeriod = [Link](1 + ear, 1 / paymentPeriodsPerYear) - 1;
} else {
const ear = [Link](1 + (interestRate / 100) / compoundPeriodsPerYear,
compoundPeriodsPerYear) - 1;
effectiveRatePerPeriod = [Link](1 + ear, 1 / paymentPeriodsPerYear) - 1;
}

// Calculate monthly payment


const monthlyPayment = loanAmount * effectiveRatePerPeriod * [Link](1 +
effectiveRatePerPeriod, totalPayments) /
([Link](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 * [Link](1 +
aprRatePerPeriod, totalPayments) /
([Link](1 + aprRatePerPeriod, totalPayments) - 1);
const totalWithAPR = calculatedPayment * totalPayments + loanedFees +
upfrontFees;

if ([Link](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;

[Link]({
paymentNumber: i,
paymentAmount: [Link](2),
interestPaid: [Link](2),
principalPaid: [Link](2),
remainingBalance: [Link](2)
});
}

// Display results
[Link]('realAPR').textContent = `Real APR: ${[Link](4)}%`;
[Link]('amountFinanced').textContent = `$$
{[Link](2)}`;
[Link]('upfrontFeesResult').textContent = `$$
{[Link](2)}`;
[Link]('paymentFrequencyResult').textContent =
[Link](0).toUpperCase() + [Link](1);
[Link]('paymentAmount').textContent = `$$
{[Link](2)}`;
[Link]('totalPayments').textContent = totalPayments;
[Link]('totalPaymentsAmount').textContent = `$$
{[Link](2)}`;
[Link]('totalInterest').textContent = `$${[Link](2)}`;
[Link]('allPaymentsFees').textContent = `$${[Link](2)}`;

// Populate amortization table


const tableBody = [Link]('amortizationTableBody');
[Link] = '';
[Link](row => {
const tr = [Link]('tr');
[Link] = `
<td>${[Link]}</td>
<td>$${[Link]}</td>
<td>$${[Link]}</td>
<td>$${[Link]}</td>
<td>$${[Link]}</td>
`;
[Link](tr);
});

// Destroy previous chart if it exists


if (breakdownChart) [Link]();

// Create breakdown chart


const ctx = [Link]('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 = [Link] || '';
const value = [Link] || 0;
const total = [Link]((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return `${label}: $${[Link](2)} (${percentage}%)`;
}
}
},
datalabels: {
color: '#fff',
formatter: (value, context) => {
const total = [Link]((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return `${percentage}%`;
},
font: {
weight: 'bold',
size: 14
}
}
}
},
plugins: [ChartDataLabels]
});

// Show results
[Link]('results').[Link] = 'block';
}

function toggleTable() {
const table = [Link]('amortizationTable');
const button = [Link]('.toggle-table');
if ([Link] === 'none' || [Link] === '') {
[Link] = 'block';
[Link] = 'Hide Amortization Table';
} else {
[Link] = 'none';
[Link] = 'View Amortization Table';
}
}

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

You might also like