Mortgage Calculator Challenge

Mortgage Calculator Challenge

Challenge from: https://frontendeval.com

Repository: Github


It was a cold winters day and the stove was emitting the most glorious heat from the combustion of burly chunks of wood...

My thoughts...

The challenge is marked as "Easy" and to be accomplished within a 45 minute window. Could this be done? I believe so. At least the code, but the styling would be left to be desired.

I decided to do both the code and make it look at least a little presentable.

This challenge is amazing and gives you a lot of information in order to accept and conquer the requirements.

Steps:

  • I read through the requirements listed until the brain kicked into gear and put the puzzle pieces together. Starting was the overall plan. "Create a calculator that accepts three inputs and calculates your monthly mortgage payment" Okay, so far understandable... A math equation is given to help solve the calculator, which is "P(r(1+r)^n/((1+r)^n)-1))". "P is the principal loan amount", "r is the monthly interest rate", and "n is the total number of payments on your mortgage". And users will make 12 payments per year and the monthly interest rate is the annual interest rate divided by 12. This was starting to get a little more complicated, but there was a link provided to the standard math equation, which became very helpful to solve the challenge. Also given, was a beautiful image of what the finished product should somewhat resemble, so I could start building out the HTML framework.

mortgage-calculator.png These diagrams are very helpful as one can visualize how somethings is meant to work, without needing to ask any further questions.

  • I have a basic understanding of what is required, so I start with the HTML framework and build on the basics based on the diagram or image presented, link to the CSS and JavaScript file. Added labels and inputs of type, number, and added min="0", so that no negative numbers could be used. Then added a input of type submit, so that the number inputs could be calculated when the submit is clicked.
<div class="container">
        <label for="principal">Principal loan amount</label>
        <input id="principal" type="number" name="principal" min="0" />
      </div>
  • After getting the framework in place, I worked on a little bit of styling. I know that if this was timed, I would have jumped into figuring out the JavaScript next to get the actual functionality working, but I wanted to first make it a little prettier, since I was doing this for fun.

I changed the font-family to cursive, because that's fun, added a little background color, a little font color. I added the colors as variables in CSS, so that I could easily change them in the future for the whole project if needed. Now that the calculator is worth looking at, I proceed to the JavaScript file to get the functionality working.

  • Jumping into JavaScript I pondered what needed to be done. Okay, what happens? Someone inputs the principle loan amount, inputs an interest rate, inputs the length of loan, clicks on the Calculate submit button and the program presents them with the monthly mortgage payment amount.

Okay, so when the submit button is clicked, I need to connect to the DOM and capture the values of these three inputs, calculate the math equation from these inputs, and then present this information as a single number back to the page.

First started out by creating the connections to the DOM for the individual inputs and the placeholder when the final output will be displayed.

Example:

const principal = document.getElementById("principal");

Now, I know that I need to add an event listener to the submit input, so that when it's clicked, it will do something.

submit.addEventListener("click", calculate);

I first used the function within the event listener (function(){}), but changed it to call the "calculate" function in case I needed to call the function later on for any reason yet to be known. I'm always thinking about how to make the code more reusable.

I created the calculate() function and think about what needs to be done. From the equation given earlier, I create variables to capture the parts needed for the equation. I name them the same as in the equation to make it simpler on the brain. These can always be refactored to make more sense in the future. The main point is to get it working and then make it better. I always use "const" variables first unless the variable needs to be assigned later one and then I will change the variable to "let".

 const p = principal.value;
 const r = interest.value / 100 / 12;
 const n = length.value * 12;

From the variables above, I know that the principle value (p) will only be the value entered. The interest rate (r) however, is entered in as a percentage, but needs to be represented as a decimal to be calculated, so we divide that value by 100. We then need it to represent the interest per month, so that value is then divided by 12, meaning the 12 months in the year, to give the interest per month. The length of loan (n) is entered in as years and there are 12 equal payments in a year or 1 payment per month, so we times that value by 12 to get the total amount of payments.

We now can use these variables in the equation to calculate the monthly mortgage amount, which I assigned to the variable "let tot", so we can print that variable out. Looking at the given equation of "P(r(1+r)^n/((1+r)^n)-1))", I was a little lost. I plugged in the variables and couldn't get it to work. I was thinking, why am I squaring and then squaring, and is there an extra parenthesis?

I went to the link of the standard math equation provided and found the answer I was looking for. A simpler equation that my brain could understand. The equation was "((6.5 / 100 / 12) 200000) / (1 - ((1 + (6.5 / 100 / 12)) ^ (-30 12)))". Now we're cooking. I already calculated the variables needed, so I plugged those in and came up with the following:

 let tot = (r * p) / (1 - (1 + r) ** -n);
 tot = Math.floor(tot);

I also used the Math.floor() to get the result in a readable fashion to be presented.

Now we are getting what we want, so we can now present that out. I chose to use to .textContent connected to the DOM connecter created earlier and came up with this:

const total = document.getElementById("total");
total.textContent = `$${tot}`

I LOVE template strings! So awesome!

  • Okay, now that we have a number presented out, we are basically done with the basic functionality. I start looking at what else can be done to improve the functionality, input validation, negative numbers, etc. The next piece I added was to only allow the calculation to go though if there were actual values in the input fields. I added:
if (principal.value > 0 && interest.value >= 0 && length.value > 0) {}

This seemed to do the trick with not presenting the user the "NaN" or "undefined" errors. There was an additional challenge and that was to "Format the monthly payment amount nicely, as pictured" Meaning to add a dollar sign and comma where one is needed. I've already added the dollar sign in the template string, so I'll work on adding a comma.

Knowing that a comma is used when digits are greater than three and every three after that, but how was I going to do that? How, how, how... I didn't know how to loop through the calculated number and add a comma in the third position, so I went the long route. Basically the route that made sense in my mind. Here is the code:

const string = tot.toString();
const amountLength = string.length;

    if (amountLength < 4) {
      total.textContent = `$${string}`;
    } else if (amountLength === 4) {
      total.textContent = `$${string[0]},${string.slice(-3)}`;
    } else if (amountLength === 5) {
      total.textContent = `$${string[0]}${string[1]},${string.slice(-3)}`;
    } else {
      total.textContent = ` Not worth it!`;
    }

Basically, I need to know how long the calculated monthly payment is and then from there I can break it a part and add a comma where needed. I need to turn the number into a string in order to separate or pull out each digit. I use the toString() method to do this and save it to the const variable of "string". I also create another variable to keep track of the length of the calculated monthly payment. I save that to the const "amountLength" variable. So the first time that a comma is needed is if the calculated monthly payment or amountLength is equal to at least 4. So anything under 4 digits get printed as is to the total.texContent(). Next, if the length of the amountLength of the calculated monthly payment is 4 digits, we print out the first digit. Since it's a string, we can access the digits like an array. We then print a comma, and then slice the last 3 and print out those digits. An example of this output is, "2,108". The next is what to do if the amountLength is 5? We do the same as 4 with printing the first digit, then we print the second digit, print out the comma, and then slice and print out the last 3 digits. For anything greater than 5, I thought I would have a little fun and just print out, "Not worth it!" It's totally worth continuing the calculations, but NOT at all worth having a mortgage payment of above $100,000 a month.

I know there is a lot of refactoring needed, but with my limited knowledge at the moment, I did the best I could. As time goes on, I will continue learning, my skills will improve, and my knowledge will grow.

Thanks for taking the time to read this and happy coding!