Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.

Script HTML Kalkulator Dana Pendidikan – Script Siap Pakai untuk Website Anda

Tambahkan fitur perhitungan dana pendidikan profesional ke website Anda hanya dengan satu script.
Script ini dibuat dengan HTML, Tailwind CSS, dan Chart.js, serta dilengkapi:

  • Form Input Validasi Otomatis untuk biaya, tahun, inflasi, dan return investasi.
  • Perhitungan Finansial Akurat termasuk proyeksi biaya masa depan dan tabungan bulanan.
  • Grafik Interaktif menggunakan Chart.js untuk memvisualisasikan pertumbuhan tabungan.
  • Tabel Rinci Bulanan yang dapat diekspor langsung ke CSV.
  • UI Modern & Responsif siap integrasi ke proyek Anda tanpa banyak modifikasi.

💻 Cocok untuk developer yang ingin menambah value pada situs finansial, portal edukasi, atau aplikasi perencanaan keuangan — tanpa harus membangun kalkulator dari nol.

Script HTML

Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Kalkulator Dana Pendidikan</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
    <style>
        body {
            font-family: 'Inter', sans-serif;
            background: linear-gradient(135deg, #1e3a8a, #3b82f6);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: flex-start;
            padding: 1rem;
        }
        .calculator-container {
            background: white;
            border-radius: 1.5rem;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
            padding: 2.5rem;
            width: 100%;
            max-width: 800px;
            max-height: 90vh;
            overflow-y: auto;
            animation: fadeIn 0.5s ease-in-out;
        }
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(20px); }
            to { opacity: 1; transform: translateY(0); }
        }
        .result-card {
            background: #f8fafc;
            border-radius: 1rem;
            padding: 2rem;
            margin-top: 2rem;
            transition: all 0.3s ease;
        }
        .input-group {
            position: relative;
            display: flex;
            align-items: center;
            background: #f9fafb;
            border-radius: 0.75rem;
            border: 2px solid #e5e7eb;
            transition: all 0.3s ease;
            padding: 0.5rem 1rem;
        }
        .input-group:focus-within {
            border-color: #3b82f6;
            box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1);
        }
        .input-field {
            background: transparent;
            border: none;
            outline: none;
            width: 100%;
            padding: 0.5rem;
            font-size: 0.875rem;
            color: #1f2937;
        }
        .input-icon {
            color: #6b7280;
            margin-right: 0.5rem;
        }
        .btn-primary {
            background: #3b82f6;
            transition: background 0.3s ease, transform 0.2s ease;
        }
        .btn-primary:hover {
            background: #1d4ed8;
            transform: translateY(-2px);
        }
        .btn-secondary {
            background: #6b7280;
            transition: background 0.3s ease, transform 0.2s ease;
        }
        .btn-secondary:hover {
            background: #4b5563;
            transform: translateY(-2px);
        }
        .table-container {
            max-height: 400px;
            overflow-y: auto;
            border-radius: 0.75rem;
            margin-top: 1rem;
        }
        table {
            border-collapse: separate;
            border-spacing: 0;
            width: 100%;
        }
        th, td {
            border-bottom: 1px solid #e5e7eb;
            padding: 0.75rem 1rem;
        }
        th:first-child, td:first-child {
            border-left: 1px solid #e5e7eb;
        }
        th:last-child, td:last-child {
            border-right: 1px solid #e5e7eb;
        }
        th {
            background: #f1f5f9;
            position: sticky;
            top: 0;
            z-index: 10;
        }
        .error-message {
            color: #dc2626;
            font-size: 0.75rem;
            margin-top: 0.25rem;
        }
        @media (max-width: 640px) {
            .calculator-container {
                padding: 1.5rem;
            }
            .table-container {
                max-height: 300px;
            }
        }
    </style>
</head>
<body>
    <div class="calculator-container">
        <h1 class="text-3xl font-extrabold text-gray-800 mb-8 text-center">Kalkulator Dana Pendidikan</h1>
        <div class="grid gap-8">
            <div>
                <label for="currentCost" class="block text-sm font-medium text-gray-700 mb-2">Biaya Pendidikan Saat Ini (IDR)</label>
                <div class="input-group">
                    <span class="input-icon">Rp</span>
                    <input type="text" id="currentCost" class="input-field" placeholder="Masukkan biaya saat ini" required>
                </div>
                <p id="currentCostError" class="error-message hidden">Biaya harus lebih dari Rp 0</p>
            </div>
            <div>
                <label for="years" class="block text-sm font-medium text-gray-700 mb-2">Tahun Hingga Dibutuhkan</label>
                <div class="input-group">
                    <span class="input-icon">📅</span>
                    <input type="number" id="years" class="input-field" placeholder="Masukkan jumlah tahun" required>
                </div>
                <p id="yearsError" class="error-message hidden">Tahun harus antara 1-30 tahun</p>
            </div>
            <div>
                <label for="inflationRate" class="block text-sm font-medium text-gray-700 mb-2">Tingkat Inflasi (% per Tahun)</label>
                <div class="input-group">
                    <span class="input-icon">%</span>
                    <input type="number" id="inflationRate" step="0.01" class="input-field" placeholder="Masukkan tingkat inflasi" required>
                </div>
                <p id="inflationRateError" class="error-message hidden">Inflasi harus antara 0-20%</p>
            </div>
            <div>
                <label for="returnRate" class="block text-sm font-medium text-gray-700 mb-2">Tingkat Pengembalian Investasi (% per Tahun)</label>
                <div class="input-group">
                    <span class="input-icon">📈</span>
                    <input type="number" id="returnRate" step="0.01" class="input-field" placeholder="Masukkan tingkat pengembalian" required>
                </div>
                <p id="returnRateError" class="error-message hidden">Pengembalian harus antara 0-20%</p>
            </div>
            <div class="flex space-x-4">
                <button onclick="calculateSavings()" class="w-full btn-primary text-white font-semibold py-3 rounded-lg shadow-md">Hitung</button>
                <button onclick="exportToCSV()" class="w-full btn-secondary text-white font-semibold py-3 rounded-lg shadow-md hidden" id="exportButton">Ekspor ke CSV</button>
            </div>
        </div>
        <div id="result" class="result-card hidden">
            <h2 class="text-xl font-semibold text-gray-800 mb-6">Hasil Perhitungan</h2>
            <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
                <div class="bg-blue-50 p-4 rounded-lg">
                    <p class="font-medium text-gray-700">Biaya Masa Depan</p>
                    <p id="futureCost" class="text-lg font-bold text-blue-600"></p>
                </div>
                <div class="bg-blue-50 p-4 rounded-lg">
                    <p class="font-medium text-gray-700">Tabungan Bulanan</p>
                    <p id="monthlySavings" class="text-lg font-bold text-blue-600"></p>
                </div>
                <div class="bg-blue-50 p-4 rounded-lg">
                    <p class="font-medium text-gray-700">Total Tabungan</p>
                    <p id="totalSavings" class="text-lg font-bold text-blue-600"></p>
                </div>
                <div class="bg-blue-50 p-4 rounded-lg">
                    <p class="font-medium text-gray-700">Total Bunga</p>
                    <p id="totalInterest" class="text-lg font-bold text-blue-600"></p>
                </div>
            </div>
            <div class="mb-6">
                <h3 class="text-lg font-semibold text-gray-700 mb-4">Grafik Pertumbuhan Tabungan</h3>
                <canvas id="savingsChart" height="200"></canvas>
            </div>
            <div id="savingsTable">
                <h3 class="text-lg font-semibold text-gray-700 mb-4">Tabel Tabungan Bulanan</h3>
                <div class="table-container">
                    <table class="w-full text-sm text-left text-gray-600">
                        <thead>
                            <tr class="bg-gray-100">
                                <th class="px-4 py-3 rounded-tl-lg">Bulan</th>
                                <th class="px-4 py-3">Tabungan Awal</th>
                                <th class="px-4 py-3">Kontribusi</th>
                                <th class="px-4 py-3">Bunga</th>
                                <th class="px-4 py-3">Tabungan Akhir</th>
                            </tr>
                        </thead>
                        <tbody id="savingsBody"></tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>

    <script>
        let chartInstance = null;

        function formatRupiah(number) {
            return new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', minimumFractionDigits: 2 }).format(number);
        }

        function formatRupiahForCSV(number) {
            return formatRupiah(number).replace(/\u00A0/g, ' ');
        }

        function formatInputNumber(value) {
            value = value.replace(/[^\d]/g, '');
            return value.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
        }

        function parseRupiah(value) {
            return parseFloat(value.replace(/[^\d]/g, '')) || 0;
        }

        function validateInputs(currentCost, years, inflationRate, returnRate) {
            let isValid = true;
            document.getElementById('currentCostError').classList.add('hidden');
            document.getElementById('yearsError').classList.add('hidden');
            document.getElementById('inflationRateError').classList.add('hidden');
            document.getElementById('returnRateError').classList.add('hidden');

            if (currentCost <= 0) {
                document.getElementById('currentCostError').classList.remove('hidden');
                isValid = false;
            }
            if (years < 1 || years > 30 || isNaN(years)) {
                document.getElementById('yearsError').classList.remove('hidden');
                isValid = false;
            }
            if (inflationRate < 0 || inflationRate > 20 || isNaN(inflationRate)) {
                document.getElementById('inflationRateError').classList.remove('hidden');
                isValid = false;
            }
            if (returnRate < 0 || returnRate > 20 || isNaN(returnRate)) {
                document.getElementById('returnRateError').classList.remove('hidden');
                isValid = false;
            }
            return isValid;
        }

        document.getElementById('currentCost').addEventListener('input', function(e) {
            const cursorPosition = e.target.selectionStart;
            const value = e.target.value.replace(/[^\d]/g, '');
            e.target.value = formatInputNumber(value);
            const newValue = e.target.value;
            const newCursorPosition = cursorPosition + (newValue.length - value.length);
            e.target.setSelectionRange(newCursorPosition, newCursorPosition);
        });

        function calculateSavings() {
            const currentCost = parseRupiah(document.getElementById('currentCost').value);
            const years = parseInt(document.getElementById('years').value);
            const inflationRate = parseFloat(document.getElementById('inflationRate').value) / 100;
            const returnRate = parseFloat(document.getElementById('returnRate').value) / 100 / 12; // Bulanan
            const resultDiv = document.getElementById('result');
            const exportButton = document.getElementById('exportButton');
            const savingsBody = document.getElementById('savingsBody');

            if (!validateInputs(currentCost, years, inflationRate, returnRate * 12 * 100)) {
                return;
            }

            const futureCost = currentCost * Math.pow(1 + inflationRate, years);
            const monthlySavings = futureCost * returnRate / (Math.pow(1 + returnRate, years * 12) - 1);
            const totalSavings = monthlySavings * years * 12;

            let schedule = [];
            let balance = 0;
            let totalInterest = 0;
            for (let i = 1; i <= years * 12; i++) {
                const startBalance = balance;
                const contribution = monthlySavings;
                const interest = balance * returnRate;
                balance = startBalance + contribution + interest;
                totalInterest += interest;
                schedule.push({
                    month: i,
                    startBalance,
                    contribution,
                    interest,
                    endBalance: balance
                });
            }

            document.getElementById('futureCost').textContent = formatRupiah(futureCost);
            document.getElementById('monthlySavings').textContent = formatRupiah(monthlySavings);
            document.getElementById('totalSavings').textContent = formatRupiah(totalSavings);
            document.getElementById('totalInterest').textContent = formatRupiah(totalInterest);
            resultDiv.classList.remove('hidden');
            exportButton.classList.remove('hidden');

            savingsBody.innerHTML = '';
            schedule.forEach(row => {
                const tr = document.createElement('tr');
                tr.classList.add('hover:bg-gray-50');
                tr.innerHTML = `
                    <td class="px-4 py-3">${row.month}</td>
                    <td class="px-4 py-3">${formatRupiah(row.startBalance)}</td>
                    <td class="px-4 py-3">${formatRupiah(row.contribution)}</td>
                    <td class="px-4 py-3">${formatRupiah(row.interest)}</td>
                    <td class="px-4 py-3">${formatRupiah(row.endBalance)}</td>
                `;
                savingsBody.appendChild(tr);
            });

            if (chartInstance) {
                chartInstance.destroy();
            }
            const ctx = document.getElementById('savingsChart').getContext('2d');
            chartInstance = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: schedule.map(row => `Bulan ${row.month}`),
                    datasets: [{
                        label: 'Tabungan Akhir',
                        data: schedule.map(row => row.endBalance),
                        borderColor: '#3b82f6',
                        backgroundColor: 'rgba(59, 130, 246, 0.1)',
                        fill: true,
                        tension: 0.4
                    }]
                },
                options: {
                    responsive: true,
                    scales: {
                        y: {
                            beginAtZero: true,
                            ticks: {
                                callback: function(value) {
                                    return formatRupiah(value);
                                }
                            }
                        }
                    },
                    plugins: {
                        tooltip: {
                            callbacks: {
                                label: function(context) {
                                    return formatRupiah(context.parsed.y);
                                }
                            }
                        }
                    }
                }
            });

            window.savingsData = {
                currentCost,
                years,
                inflationRate: inflationRate * 100,
                returnRate: returnRate * 12 * 100,
                futureCost,
                monthlySavings,
                totalSavings,
                totalInterest,
                schedule
            };
        }

        function exportToCSV() {
            if (!window.savingsData) {
                alert('Silakan hitung terlebih dahulu.');
                return;
            }

            const { currentCost, years, inflationRate, returnRate, futureCost, monthlySavings, totalSavings, totalInterest, schedule } = window.savingsData;

            let csvContent = 'data:text/csv;charset=utf-8,';
            csvContent += 'Informasi Tabungan\n';
            csvContent += `Biaya Pendidikan Saat Ini,"${formatRupiahForCSV(currentCost)}"\n`;
            csvContent += `Tahun Hingga Dibutuhkan,${years}\n`;
            csvContent += `Tingkat Inflasi (% per Tahun),${inflationRate.toFixed(2)}\n`;
            csvContent += `Tingkat Pengembalian Investasi (% per Tahun),${returnRate.toFixed(2)}\n`;
            csvContent += '\nRingkasan\n';
            csvContent += `Biaya Masa Depan,"${formatRupiahForCSV(futureCost)}"\n`;
            csvContent += `Tabungan Bulanan,"${formatRupiahForCSV(monthlySavings)}"\n`;
            csvContent += `Total Tabungan,"${formatRupiahForCSV(totalSavings)}"\n`;
            csvContent += `Total Bunga,"${formatRupiahForCSV(totalInterest)}"\n`;
            csvContent += '\nTabel Tabungan Bulanan\n';
            const headers = [
                'Bulan',
                'Tabungan Awal (IDR)',
                'Kontribusi (IDR)',
                'Bunga (IDR)',
                'Tabungan Akhir (IDR)'
            ];
            const rows = schedule.map(row => [
                row.month,
                `"${formatRupiahForCSV(row.startBalance)}"`,
                `"${formatRupiahForCSV(row.contribution)}"`,
                `"${formatRupiahForCSV(row.interest)}"`,
                `"${formatRupiahForCSV(row.endBalance)}"`
            ]);

            csvContent += headers.join(',') + '\n';
            rows.forEach(row => {
                csvContent += row.join(',') + '\n';
            });

            const encodedUri = encodeURI(csvContent);
            const link = document.createElement('a');
            link.setAttribute('href', encodedUri);
            link.setAttribute('download', 'kalkulator_dana_pendidikan.csv');
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    </script>
</body>
</html>
Iklan
Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.

Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.

Beri komentar

Kamu yakin ingin keluar?

Ya, Keluar
Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.
Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.
Kami harap dukungan Anda via iklan ini membantu kami terus menyajikan konten bermanfaat.
Tunggu hingga iklan selesai untuk menyalin atau mendownload kode.
Situs ini menggunakan cookie untuk memberikan pengalaman menjelajah yang lebih baik. Dengan menggunakan situs web ini, Anda menyetujui penggunaan cookie kami.