DEV Community

Cover image for Debugging Your Finances: Open Source Future Wealth Calculator for your investments
Lakshit Somani
Lakshit Somani

Posted on

Debugging Your Finances: Open Source Future Wealth Calculator for your investments

Hey there, fellow devs! 👋 Lakshit here, and I'm excited to share a project I've been working on. I've built a Future Value Calculator, and I thought I'd walk you through the process, highlighting some key features and the tech behind it.

The Future Value Calculator I built isn't your typical financial planning tool. Sure, it has all the standard features you'd expect - the ability to input your initial capital, monthly contributions, interest rate, and time horizon. But what sets this calculator apart are two key features:

  1. Inflation Adjustments: Most calculators give you the raw future value number, but fail to account for the eroding effects of inflation. This tool lets you input an inflation rate, so you can see the real purchasing power of your future savings.

  2. Investment Growth Adjustments: Rather than assuming a static investment amount, this calculator allows you to factor in an annual investment growth rate. This means you have option to increase your investments every year and see how it potentially increases your future wealth.

🚀 Performance First
It is blazingly fast as it is built upon a single HTML file.

💡 Comprehensive Algorithm
The calculator takes into account:

  1. Initial capital
  2. Monthly deposits
  3. Annual interest rate
  4. Inflation rate
  5. Investment growth rate
  6. Time horizon

It then computes:

  • Future value without inflation
  • Future value with inflation (real purchasing power)
  • Total amount invested

The Code (Because We're All Here for That, Right?)

The Tech Stack
Frontend: HTML5, CSS3, and vanilla JavaScript (because sometimes, less is more)

HTML Structure:

1. Basic Setup and Metadata: We begin with the standard <!DOCTYPE html> declaration and opening <html> tag with a specified lang attribute. Within the <head> section, we define character encoding, viewport settings for responsive design, the title of the document, and links to external resources like Bootstrap for CSS styling and custom fonts from Google.

2. Form Creation: Within the <body>, centered using Bootstrap's grid system, we introduce a card-style layout (<div class="card">) that contains all other elements. The card header (<div class="card-header text-white">) announces the tool's purpose. The body of the card (<div class="card-body">) houses the user input form (<form id="investmentForm">). This form includes several input fields for users to enter details such as initial capital, monthly deposits, and rates. Each input is wrapped in a <div class="form-group"> for proper spacing and labeling.

3. Results Display: Below the form, we prepare placeholders for displaying the calculation results. These are initially hidden and are shown dynamically when the calculations are made.

CSS Styling:

1. Layout and Design: We utilize modern CSS properties to enhance the visual appeal and user experience. This includes custom fonts, background colors, padding, and transitions for smooth visual effects. The use of CSS Grid and Flexbox ensures that the layout is responsive and elements are well-organized.

2. Form Aesthetics: Input fields and buttons are styled with rounded borders and transition effects to provide feedback when interacted with. The overall form design is clean and minimalistic, focusing user attention on the task at hand.

3. Animations: Subtle animations such as 'fadeIn' are defined to make the appearance of results more engaging.

JavaScript Functionality:

1. Form Handling: The JavaScript included at the bottom of the HTML document is crucial for the dynamic aspects of the calculator. It prevents the default form submission to handle calculations directly within the page. It also validates the input fields, ensuring that all necessary data is entered before proceeding.

2. Calculation Logic: The script houses the logic for calculating the future value of investments based on user-provided data. It dynamically updates the DOM with the results, showing what the investments will look like with and without considering inflation.

3. Event Listeners: Listeners for 'submit' and 'keydown' events are set up to enhance the form's interactivity, allowing users to either click the calculate button or press 'Enter' to trigger the calculation.

Below is the complete code:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Future Value Calculator</title>
    <link rel="shortcut icon" type="image/jpg" href="favicon.jpg"/>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,300..900;1,300..900&display=swap');

        body {
            font-family: Rubik, sans-serif;
            background: #f0f2f5;
            padding: 20px;
            transition: background 0.5s ease-in-out;
            /* overflow: hidden; */
            overflow-y: scroll;
            /* Enable vertical scrolling */
            overflow-x: hidden;
            /* Hide horizontal scrollbar */
            scrollbar-width: none;
            /* For Firefox */
        }

        .container {
            margin-top: 50px;
            transition: margin-top 0.5s ease-in-out;
            overflow: auto;
            padding-right: 15px;
        }

        .alert,
        .warning {
            display: none;
            animation: fadeIn 0.75s ease-in-out;
        }

        .card {
            border-radius: 15px !important;
            border: none;
            transition: transform 0.5s ease-in-out, box-shadow 0.5s ease-in-out;
        }

        .card:hover {
            /* transform: scale(1.02); */
            box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
        }

        .card-header {
            background: rgb(0, 0, 0);
            border-top-left-radius: 15px !important;
            border-top-right-radius: 15px !important;
            transition: background 0.5s ease-in-out;
        }

        .form-control {
            border-radius: 10px !important;
            transition: border-color 0.5s ease-in-out;
        }

        .btn {
            border-radius: 10px !important;
            background: #000000;
            transition: background-color 0.5s ease-in-out, transform 0.5s ease-in-out;
        }
        .alert {
            border-radius: 10px !important;
            animation: fadeIn 0.5s ease-in-out;
        }


        @keyframes fadeIn {
            from {
                opacity: 0;
            }

            to {
                opacity: 1;
            }
        }
    </style>
</head>

<body>
    <div class="container mt-5">
        <div class="row justify-content-center">
            <div class="col-md-8 col-lg-6">
                <div class="card">
                    <div class="card-header text-white">
                        <h3 class="text-center">Future Value Calculator</h3>
                    </div>
                    <div class="card-body">
                        <form id="investmentForm">
                            <div class="form-group">
                                <label for="initialCapital">Initial Capital</label>
                                <input type="number" class="form-control" id="initialCapital" name="initialCapital"
                                    required>
                            </div>
                            <div class="form-group">
                                <label for="monthlyDeposit">Monthly Deposit</label>
                                <input type="number" class="form-control" id="monthlyDeposit" name="monthlyDeposit"
                                    required>
                            </div>
                            <div class="form-group">
                                <label for="rateOfReturn">Annual Interest Rate</label>
                                <input type="number" class="form-control" id="rateOfReturn" name="rateOfReturn"
                                    required>
                            </div>
                            <div class="form-group">
                                <label for="inflationRate">Annual Inflation Rate</label>
                                <input type="number" class="form-control" id="inflationRate" name="inflationRate"
                                    required>
                            </div>
                            <div class="form-group">
                                <label for="increaseRate">Annual Increase Rate of Investments</label>
                                <input type="number" class="form-control" id="increaseRate" name="increaseRate"
                                    required>
                            </div>
                            <div class="form-group">
                                <label for="years">Number of Years</label>
                                <input type="number" class="form-control" id="years" name="years" required>
                            </div>
                            <button type="button" class="btn btn-primary btn-block"
                                onclick="checkFieldsAndCalculate()">Calculate</button>
                        </form>

                        <div id="results" class="mt-3">
                            <p class="alert alert-info" id="resultWithoutInflation"></p>
                            <p class="alert alert-success" id="resultWithInflation"></p>
                            <p class="alert alert-warning" id="totalInvested"></p>
                        </div>

                    </div>
                </div>
                <footer class="text-center mt-5">
                    <p>With ❤️ by <b>Lakshit Somani</b></p>
                    <a href="https://www.linkedin.com/in/lakshit-somani" target="_blank">
                        <img src="https://cdn-icons-png.flaticon.com/512/174/174857.png" alt="LinkedIn"
                            style="width: 30px; margin: 0 10px;">
                    </a>
                    <a href="https://github.com/lakshits11" target="_blank">
                        <img src="https://cdn-icons-png.flaticon.com/512/25/25231.png" alt="GitHub"
                            style="width: 30px; margin: 0 10px;">
                    </a>
                </footer>
            </div>
        </div>
    </div>

    <script>
        document.getElementById('investmentForm').addEventListener('submit', function (event) {
            event.preventDefault(); // Prevent the form from submitting
            checkFieldsAndCalculate();
        });

        function checkFieldsAndCalculate() {
            const form = document.getElementById('investmentForm');
            const inputs = form.querySelectorAll('input');
            let allFieldsFilled = true;

            // Check if all fields are filled and highlight empty fields
            inputs.forEach(input => {
                if (!input.value) {
                    input.style.borderColor = 'red'; 
                    input.style.borderWidth = '1.5px';
                    allFieldsFilled = false;
                } else {
                    input.style.borderColor = ''; // Reset the border color if filled
                }
            });

            if (allFieldsFilled) {
                calculateFutureValue();
            }
        }

        function calculateFutureValue() {
            const P = parseFloat(document.getElementById('initialCapital').value);
            const x = parseFloat(document.getElementById('monthlyDeposit').value);
            const r = parseFloat(document.getElementById('rateOfReturn').value) / 100;
            const i = parseFloat(document.getElementById('inflationRate').value) / 100;
            const z = parseFloat(document.getElementById('increaseRate').value) / 100;
            const t = parseFloat(document.getElementById('years').value);

            const monthlyRate = r / 12;
            const totalMonths = t * 12;

            let futureValueWithoutInflation = P * Math.pow(1 + monthlyRate, totalMonths);
            const effectiveMonthlyRate = (1 + r / 12) / (1 + i / 12) - 1;
            let futureValueWithInflation = P * Math.pow(1 + effectiveMonthlyRate, totalMonths);
            let totalInvested = P;

            for (let year = 1; year <= t; year++) {
                for (let month = 1; month <= 12; month++) {
                    const n = (year - 1) * 12 + month;
                    const adjustedDeposit = x * Math.pow(1 + z, year - 1);
                    totalInvested += adjustedDeposit;
                    futureValueWithoutInflation += adjustedDeposit * Math.pow(1 + monthlyRate, totalMonths - n);
                    futureValueWithInflation += adjustedDeposit * Math.pow(1 + effectiveMonthlyRate, totalMonths - n);
                }
            }

            const returnWithoutInflation = ((futureValueWithoutInflation - totalInvested) / totalInvested) * 100;
            const returnWithInflation = ((futureValueWithInflation - totalInvested) / totalInvested) * 100;

            document.getElementById('resultWithoutInflation').innerText = `Future Value without Inflation: ${futureValueWithoutInflation.toFixed(2)} (${returnWithoutInflation.toFixed(2)}%)`;
            document.getElementById('resultWithInflation').innerText = `Future Value with Inflation: ${futureValueWithInflation.toFixed(2)} (${returnWithInflation.toFixed(2)}%)`;
            document.getElementById('totalInvested').innerText = `Total Amount Invested: ${totalInvested.toFixed(2)}`;

            // Show results
            document.querySelectorAll('.alert').forEach(alert => {
                alert.style.display = 'block';
                alert.style.animation = 'fadeIn 0.5s ease-in-out';
            });
        }

        document.getElementById('investmentForm').addEventListener('keydown', function (event) {
            if (event.key === 'Enter') {
                event.preventDefault();
                checkFieldsAndCalculate();
            }
        });
    </script>

    <script defer src="/_vercel/insights/script.js"></script>
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.7.0/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>

</html>
Enter fullscreen mode Exit fullscreen mode

Try It Out for Yourself!

Ready to start planning your financial future? Head over to the live demo and give the Future Value Calculator a try. Whether you're saving for retirement, a big purchase, or just curious about your investment potential, this tool will give you the insights you need to make informed decisions.

Happy Coding and Investing :)

Top comments (0)