Help with Tax Calculator

I am a designer first and foremost, html and css make sense to me. JS has been a whole new nightmare. I love it but I am going the self-taught route. My workplace knows I am pretty good at figuring computer things out so I was asked to put together a calculator for our prepay forms.

I am trying to take the total found in the first half and then figure out the sales tax based off of the subtotal and the tax rates for specific counties. We have about 5 counties that we serve. Currently I have the subtotal being figured out using a checkbox section so they can choose multiple services. And then for tax I have a drop down menu.

Any help would be appreciated. I feel like I have been smashing my head against the wall for the last two weeks trying to learn as much as I can.

document.body.innerHTML ; //refreshes page

const recalculateText = document.querySelector(".recalculate-text");
const checkboxContainer = document.querySelector("#checkbox-container");
let total = 0;

const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});

checkboxContainer.addEventListener('change'); e => {
  if (e.target.tagName == "INPUT") {
    const floatValue = parseFloat(e.target.value);
    if (e.target.checked) {
      total += floatValue;
    } else {
      total -= floatValue;
    }
  }

  recalculateText.innerHTML = formatter.format(total);
});

var county = document.getElementById("dropDown"); //the element getting got is the dropDown list
var subtotal = document.getElementById("recalculateText");
var dropDown = county;

function taxCalculation() { //declaring function as taxCalculation
const "county1" = 0.738;
const "county2" = 0.7875;
const "county3" = 0;
const "county4" = 0.738;
const "county5" = 0.738;

dropDown.addEventListener("change"); event => ;{ //declaring what change is paying attention to

// trying to get subtotal of calculatetext * (1 + county / 100)

 if (event.target.tagName == "option") {
    const floatValue = parseFloat(event.target.value);
    if (event.target.select) {
      "subtotal" * (1 + "county" / 100);
    } else {
      "0";
    }
  }
});
}
1 Like

Okay. Letā€™s start with a basic Array so my brain doesnt melt too much.

const taxrates = [0.738,0.7875,0,0.738,0.738]

(Note that an array is 0-indexed; so taxrates[0] is 0.738.)

You dont show us your select box, but i assume your code is something likeā€¦
<option value="1">county1</option>

Letā€™sā€¦ simplify the referncing a bit.

We already know weā€™re looking at dropDown.
A <select> elementā€™s value matches the current selected optionā€™s value.
So we dont need to do all the event.target stuff.

let tax = 0;
dropDown.addEventListener(ā€œchangeā€, (event) => {
   const selected = parseInt(dropDown.value); //Need it to be an Int, so we can reference the array.
   //Something must be selected - otherwise we wouldnt be in this event... so there is no "else".
   tax = total * (1 + (taxrates[selected] /100))
   // And then do whatever you need to do with the tax value.
 });
3 Likes

You could do this:

<select>
  <option disabled selected>Select county</option>
  <option value="1.00738">County 1</option>
  <option value="1.007875">County 2</option>
  <option value="1">County 3</option>
  <option value="1.00738">County 4</option>
  <option value="1.00738">County 5</option>
</select>
1 Like

Depends somewhat on what if anything else you want to do with County (because at that point, county 1 4 and 5 are indistinguishable), but yeah.

Just another take on that, using a lookup

html

<select id='counties'>
  <option disabled selected>Select county</option>
  <option>Los Angeles</option>
  <option>Cook</option>
  <option>Harris</option>
  <option>Maricopa</option>
  <option>San Diego</option>
</select>

Javascript

const countyTaxRates = {
  'los angeles': 1.00738,
  'cook': 1.007875,
  'harris': 1,
  'maricopa': 1.00738,
  'san diego': 1.00738
};

const countyOptions = document.querySelector('#counties');

countyOptions.addEventListener('change', (event) => {
  const countyName = event.target.value; // e.g. Los Angeles
  // lookup countyTaxRates by name
  const taxRate = countyTaxRates[countyName.toLowerCase()];
  // ... do stuff here
})

2 Likes

We should consider how to handle changes in tax rates. Presumably such changes will occur on a certain day at midnight :tired_face::.

2 Likes

also be careful using event.target, because propogationā€™s a thing.

How in this instance? Itā€™s a listener attached to a select element. The target is always the select element. Or am I missing something obvious?

Got a little carried away, but I was considering how to approach this if you have many counties ā€” there are 3k plus in America if I am right.

You obviously donā€™t want that many in a select options or data-list (which I think is limited to 512 anyway).

I was looking at autoComplete.js last night, and thought this might be an example to try it out on.

So I built a dataset of a thousand counties which I extracted from here, adding on random tax rates.
https://en.wikipedia.org/wiki/List_of_United_States_counties_and_county_equivalents

counties-usa.json

[
   {
      "county":"Los Angeles",
      "state":"California",
      "population":10014009,
      "taxRate":1.000377
   },
   {
      "county":"Cook",
      "state":"Illinois",
      "population":5275541,
      "taxRate":1.005214
   },
   {
      "county":"Harris",
      "state":"Texas",
      "population":4731145,
      "taxRate":1.009747
   } ...

From that fetched data I created a dictionary lookup as before e.g.

countyTaxRates

{
  'los angeles': 1.000377,
  'cook': 1.005214,
  'harris': 1.009747,
  ...
}

And I extracted the county names into an array, which I fed into autoComplete.

countyNames

["Los Angeles", "Cook", "Harris", ...]

The functions I used for wrangling the data were pluck and props, which you can find in ramdaJS and I believe similar in lodash. I opted to write my own as they are quite straightforward.

/**
 * pluck - takes an array of objects and returns
 * each object's specified key value
 * @example
 * const people = [{name: 'Fred', age: 42}, {name: 'Barney', age: 40}]
 * const names = pluck(people, 'name')
 * console.log(names) // ['Fred', 'Barney']
 */
function pluck(collection, key) {
    const plucked = []
    for (const item of collection) {
        plucked.push(item?.[key]);
    }
    return plucked;
}

/**
 * props - A higher order function which gets the value(s) of an object's key(s).
 * If multiple keys are supplied, an array of values is returned.
 * @example
 * const obj = { a: 1, b: 2, c: 3 };
 * const getC = prop('c');
 * getC(obj); // returns 3
 * const getAB = prop('a', 'b');
 * getAB(obj); // returns [1, 2]
 */
function props(...keys) {
    function fromObj (obj) {
        // if only one key return the value
        if (keys.length === 1) {
            return obj?.[keys[0]];
        }
        // if more than one key return an array of values
        const values = [];

        for (const key of keys) {
            values.push(obj?.[key]);
        }
        return values;
    }
    return fromObj;
};

The codepen is here. I donā€™t know my American counties, but ā€˜Sanā€™ is a good one to start with. I am new to autoComplete.js so Iā€™m sure the configuration can be improved on.

2 Likes

Iā€™m glad its not just me that is having the brain melting issue. Thank you for your response! I have been working my way through understanding. I keep getting an error for let tax = 0;

For the recalculate text I am getting it to show up on the form but the moment I put in my coding for the tax calculation it seems to break the form. Are there any things I should keep an eye out for when it comes to overlap or collisions (for lack of an official word in my vocab)

This doesnā€™t necessarily help me now, but it is a very cool bit of code, and it explores something I want to apply in a future project! Thank you for your response!

1 Like

What error?

I did wonder, when I was coding it ā€” Iā€™m glad itā€™s got some value :slight_smile:

I took the weekend and realized when I came back that I was in fact misreading it. It was just talking about the version of JS. Thank you for being so diligent. I really do appreciate it.

1 Like