interest calculator

document.addEventListener(‘DOMContentLoaded’, function() { // DOM Elements const calculator = document.querySelector(‘.interest-calculator’); const principalInput = document.getElementById(‘principal’); const rateInput = document.getElementById(‘rate’); const timeInput = document.getElementById(‘time’); const timeUnitSelect = document.getElementById(‘time-unit’); const frequencySelect = document.getElementById(‘frequency’); const calculateBtn = document.getElementById(‘calculate’); const resetBtn = document.getElementById(‘reset’); const resultsContainer = document.getElementById(‘results’); const darkModeToggle = document.getElementById(‘darkModeToggle’); const darkIcon = document.getElementById(‘darkIcon’); const lightIcon = document.getElementById(‘lightIcon’); // Chart variable let growthChart = null; // Initialize dark mode from localStorage or system preference function initDarkMode() { const isDark = localStorage.getItem(‘darkMode’) === ‘true’ || (!localStorage.getItem(‘darkMode’) && window.matchMedia(‘(prefers-color-scheme: dark)’).matches); if (isDark) { document.documentElement.classList.add(‘dark’); darkIcon.classList.add(‘hidden’); lightIcon.classList.remove(‘hidden’); } else { document.documentElement.classList.remove(‘dark’); darkIcon.classList.remove(‘hidden’); lightIcon.classList.add(‘hidden’); } } // Toggle dark mode function toggleDarkMode() { const isDark = document.documentElement.classList.toggle(‘dark’); localStorage.setItem(‘darkMode’, isDark); if (isDark) { darkIcon.classList.add(‘hidden’); lightIcon.classList.remove(‘hidden’); } else { darkIcon.classList.remove(‘hidden’); lightIcon.classList.add(‘hidden’); } // Re-render chart with new theme colors if (growthChart) { growthChart.destroy(); renderChart(); } } // Format currency function formatCurrency(amount) { return new Intl.NumberFormat(‘en-US’, { style: ‘currency’, currency: ‘USD’, minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(amount); } // Calculate interest function calculateInterest() { // Get input values const principal = parseFloat(principalInput.value); const rate = parseFloat(rateInput.value) / 100; const time = parseFloat(timeInput.value); const timeUnit = timeUnitSelect.value; const frequency = parseInt(frequencySelect.value); // Validate inputs if (isNaN(principal) || principal <= 0) { alert('Please enter a valid principal amount'); return; } if (isNaN(rate) || rate <= 0) { alert('Please enter a valid interest rate'); return; } if (isNaN(time) || time <= 0) { alert('Please enter a valid time period'); return; } // Convert time to years const timeInYears = timeUnit === 'months' ? time / 12 : time; // Calculate results let totalInterest, finalAmount, breakdown = []; if (frequency === 0) { // Simple interest totalInterest = principal * rate * timeInYears; finalAmount = principal + totalInterest; // Simple breakdown (start and end) breakdown.push({ period: 'Start', interest: 0, balance: principal }); breakdown.push({ period: 'End', interest: totalInterest, balance: finalAmount }); } else { // Compound interest const periods = Math.round(frequency * timeInYears); const periodicRate = rate / frequency; finalAmount = principal * Math.pow(1 + periodicRate, periods); totalInterest = finalAmount - principal; // Generate detailed breakdown let balance = principal; const breakdownPoints = Math.min(12, periods); // Show max 12 points for (let i = 0; i <= periods; i++) { // Only include specific points to keep table manageable if (i === 0 || i === periods || (periods > breakdownPoints && i % Math.floor(periods / breakdownPoints) === 0)) { const interest = i === 0 ? 0 : balance * periodicRate; if (i > 0) balance += interest; breakdown.push({ period: i === 0 ? ‘Start’ : i === periods ? ‘Final’ : `Year ${(i / frequency).toFixed(1)}`, interest: interest, balance: balance }); } else if (i > 0) { balance += balance * periodicRate; } } } // Update results display document.getElementById(‘result-principal’).textContent = formatCurrency(principal); document.getElementById(‘result-interest’).textContent = formatCurrency(totalInterest); document.getElementById(‘result-amount’).textContent = formatCurrency(finalAmount); // Update breakdown table const breakdownBody = document.getElementById(‘breakdown-body’); breakdownBody.innerHTML = ”; breakdown.forEach(item => { const row = document.createElement(‘tr’); row.className = ‘hover:bg-gray-50 dark:hover:bg-gray-500’; const periodCell = document.createElement(‘td’); periodCell.className = ‘px-4 py-3 whitespace-nowrap text-sm text-gray-800 dark:text-gray-200’; periodCell.textContent = item.period; row.appendChild(periodCell); const interestCell = document.createElement(‘td’); interestCell.className = ‘px-4 py-3 whitespace-nowrap text-sm text-right text-green-600 dark:text-green-400’; interestCell.textContent = formatCurrency(item.interest); row.appendChild(interestCell); const balanceCell = document.createElement(‘td’); balanceCell.className = ‘px-4 py-3 whitespace-nowrap text-sm text-right text-blue-600 dark:text-blue-400 font-medium’; balanceCell.textContent = formatCurrency(item.balance); row.appendChild(balanceCell); breakdownBody.appendChild(row); }); // Render chart renderChart(breakdown, timeInYears); // Show results resultsContainer.classList.remove(‘hidden’); } // Render growth chart function renderChart(breakdown = [], timeInYears = 1) { const ctx = document.getElementById(‘growthChart’).getContext(‘2d’); // Destroy previous chart if exists if (growthChart) { growthChart.destroy(); } // Only render if we have breakdown data if (breakdown.length === 0) return; // Prepare chart data const labels = breakdown.map(item => item.period); const balanceData = breakdown.map(item => item.balance); const interestData = breakdown.map(item => item.interest); // Get theme colors const isDark = document.documentElement.classList.contains(‘dark’); const bgColor = isDark ? ‘rgba(17, 24, 39, 0.7)’ : ‘rgba(255, 255, 255, 0.7)’; const textColor = isDark ? ‘rgba(229, 231, 235, 0.9)’ : ‘rgba(55, 65, 81, 0.9)’; const gridColor = isDark ? ‘rgba(75, 85, 99, 0.5)’ : ‘rgba(209, 213, 219, 0.5)’; growthChart = new Chart(ctx, { type: ‘line’, data: { labels: labels, datasets: [ { label: ‘Account Balance’, data: balanceData, borderColor: ‘#3B82F6’, backgroundColor: ‘rgba(59, 130, 246, 0.1)’, borderWidth: 2, tension: 0.1, fill: true }, { label: ‘Interest Earned’, data: interestData, borderColor: ‘#10B981’, backgroundColor: ‘rgba(16, 185, 129, 0.1)’, borderWidth: 2, tension: 0.1, fill: true } ] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: ‘top’, labels: { color: textColor } }, tooltip: { callbacks: { label: function(context) { let label = context.dataset.label || ”; if (label) { label += ‘: ‘; } if (context.parsed.y !== null) { label += formatCurrency(context.parsed.y); } return label; } } } }, scales: { x: { grid: { color: gridColor }, ticks: { color: textColor } }, y: { grid: { color: gridColor }, ticks: { color: textColor, callback: function(value) { return formatCurrency(value); } } } } } }); } // Reset calculator function resetCalculator() { principalInput.value = ‘10000’; rateInput.value = ‘5.0’; timeInput.value = ‘5’; timeUnitSelect.value = ‘years’; frequencySelect.value = ’12’; resultsContainer.classList.add(‘hidden’); if (growthChart) { growthChart.destroy(); growthChart = null; } } // Event Listeners calculateBtn.addEventListener(‘click’, calculateInterest); resetBtn.addEventListener(‘click’, resetCalculator); darkModeToggle.addEventListener(‘click’, toggleDarkMode); // Initialize initDarkMode(); // Load Chart.js library dynamically if (typeof Chart === ‘undefined’) { const script = document.createElement(‘script’); script.src = ‘https://cdn.jsdelivr.net/npm/chart.js’; script.onload = function() { // If inputs have values, calculate immediately if (principalInput.value && rateInput.value && timeInput.value) { calculateInterest(); } }; document.head.appendChild(script); } else { // If Chart.js is already loaded if (principalInput.value && rateInput.value && timeInput.value) { calculateInterest(); } } });
Scroll to Top