I have a “calculator” that gives an estimated payout from a data table. It works pretty good, except the total gets wonky when I choose a marital status or a parent status PLUS a children selection. The html won’t update correctly, and the child fee does not add correctly.
But, the child selection works perfectly fine when a marital or parent status is not selected, and vice versa. What am I missing? Here’s the git repo too: https://github.com/strozilla/va-calculator
const compensationRates = {
10: {
single: 171.23
},
20: {
single: 338.49
},
30: {
single: 524.31,
withSpouse: 586.31,
withSpousewithoneParent: 636.31,
withSpousewithTwoParents: 686.31,
withOneParent: 574.31,
withTwoParents: 624.331,
withOneChild: 565.31,
withSpousewithOneChild: 632.21,
withSpousewithoneParentwithOneChild: 682.31,
withSpousewithTwoParentswithOneChild: 732.31,
withOneParentwithOneChild: 615.31,
withTwoParentswithOneChild: 665.31,
additionalChildUnder18: 31.0,
additionalChildOver18: 100.0,
aidAndAttendance: 57.0
},
40: {
single: 755.28,
withSpouse: 838.28,
withSpousewithOneParent: 904.28,
withSpousewithTwoParents: 970.28,
withOneParent: 821.28,
withTwoParents: 887.28,
withOneChild: 810.28,
withSpousewithOneChild: 899.28,
withSpousewithoneParentwithOneChild: 965.28,
withSpousewithTwoParentswithOneChild: 1031.28,
withOneParentwithOneChild: 876.28,
withTwoParentswithOneChild: 942.28,
additionalChildUnder18: 41.0,
additionalChildOver18: 133.0,
aidAndAttendance: 76.0
},
50: {
single: 1075.16,
withSpouse: 1179.16,
withSpousewithOneParent: 1262.16,
withSpousewithTwoParents: 1345.16,
withOneParent: 1158.16,
withTwoParents: 1144.16,
withOneChild: 1241.16,
withSpousewithOneChild: 1255.16,
withSpousewithoneParentwithOneChild: 1338.16,
withSpousewithTwoParentswithOneChild: 1421.16,
withOneParentwithOneChild: 1227.16,
withTwoParentswithOneChild: 1310.16,
additionalChildUnder18: 51.0,
additionalChildOver18: 167.0,
aidAndAttendance: 95.0
},
60: {
single: 1361.88,
withSpouse: 1486.88,
withSpousewithOneParent: 1586.88,
withSpousewithTwoParents: 1686.88,
withOneParent: 1461.88,
withTwoParents: 1561.88,
withOneChild: 1444.88,
withSpousewithOneChild: 1577.88,
withSpousewithoneParentwithOneChild: 1677.88,
withSpousewithTwoParentswithOneChild: 1777.88,
withOneParentwithOneChild: 1544.88,
withTwoParentswithOneChild: 1644.88,
additionalChildUnder18: 62.0,
additionalChildOver18: 200.0,
aidAndAttendance: 114.0
},
70: {
single: 1716.28,
withSpouse: 1861.28,
withSpousewithOneParent: 1978.28,
withSpousewithTwoParents: 2095.28,
withOneParent: 1833.28,
withTwoParents: 1950.28,
withOneChild: 1813.28,
withSpousewithOneChild: 1968.28,
withSpousewithoneParentwithOneChild: 2085.28,
withSpousewithTwoParentswithOneChild: 2202.28,
withOneParentwithOneChild: 1930.28,
withTwoParentswithOneChild: 2047.28,
additionalChildUnder18: 72.0,
additionalChildOver18: 234.0,
aidAndAttendance: 134.0
},
80: {
single: 1995.01,
withSpouse: 2161.01,
withSpousewithOneParent: 2294.01,
withSpousewithTwoParents: 2427.01,
withOneParent: 2128.01,
withTwoParents: 2261.01,
withOneChild: 2106.01,
withSpousewithOneChild: 2283.01,
withSpousewithoneParentwithOneChild: 2416.01,
withSpousewithTwoParentswithOneChild: 2549.01,
withOneParentwithOneChild: 2239.01,
withTwoParentswithOneChild: 2372.01,
additionalChildUnder18: 82.0,
additionalChildOver18: 267.0,
aidAndAttendance: 153.0
},
90: {
single: 2241.91,
withSpouse: 2428.91,
withSpousewithOneParent: 2578.91,
withSpousewithTwoParents: 2728.91,
withOneParent: 2391.91,
withTwoParents: 2541.91,
withOneChild: 2366.91,
withSpousewithOneChild: 2565.91,
withSpousewithoneParentwithOneChild: 2715.91,
withSpousewithTwoParentswithOneChild: 2865.91,
withOneParentwithOneChild: 2516.91,
withTwoParentswithOneChild: 2666.91,
additionalChildUnder18: 93.0,
additionalChildOver18: 301.0,
aidAndAttendance: 172.0
},
100: {
single: 3737.85,
withSpouse: 3946.25,
withSpousewithOneParent: 4113.51,
withSpousewithTwoParents: 4280.77,
withOneParent: 3905.11,
withTwoParents: 4072.37,
withOneChild: 3877.22,
withSpousewithOneChild: 4098.87,
withSpousewithoneParentwithOneChild: 4266.13,
withSpousewithTwoParentswithOneChild: 4433.39,
withOneParentwithOneChild: 4044.48,
withTwoParentswithOneChild: 4211.74,
additionalChildUnder18: 1033.55,
additionalChildOver18: 334.49,
aidAndAttendance: 191.14
}
}
let limb = []
let disabilities = []
let bilateralDisabilities = []
let selectedOptions = []
let totalCompensation = 0
let combinedPercentage = 0
let selectedBodyPart = null
let resultSpan = document.getElementById('result')
function calculateCompensation() {
document.querySelectorAll('.body-part').forEach(function(bodyPart) {
bodyPart.addEventListener('click', function() {
selectedBodyPart = bodyPart.textContent // Update the selected body part
})
})
document.querySelectorAll('.percentage').forEach(function(button) {
button.addEventListener('click', function() {
var value = parseInt(button.value)
var selectionText = `${value}%`
if (selectedBodyPart) {
selectionText = `${selectedBodyPart} ${value}%`
limb.push(selectedBodyPart)
selectedBodyPart = null
}
disabilities.push(value)
addSelectionBox(selectionText)
if (disabilities.length > 1 && limb.length > 1) {
disabilities.forEach(function(disability) {
bilateralDisabilities.push(disability)
})
}
button.classList.remove('selected')
updateTotalCompensation()
})
})
document.querySelectorAll('.optional').forEach(function(element) {
element.addEventListener('change', function() {
updateTotalCompensation()
})
})
compensation.innerHTML = '$' + totalCompensation.toFixed(2)
resultSpan.innerHTML = combinedPercentage + '%'
updateTotalCompensation()
}
function addSelectionBox(text) {
var selectionsDisplay = document.getElementById('selectionsDisplay')
var box = document.createElement('div')
box.className = 'selection-box'
box.innerHTML = `${text} <span class="remove-box">X</span>`
selectionsDisplay.appendChild(box)
box.querySelector('.remove-box').addEventListener('click', function() {
removeSelection(text, box)
})
}
function removeSelection(text, box) {
var index
if (text.endsWith('%')) {
var value = parseInt(text)
index = disabilities.indexOf(value)
if (index !== -1) disabilities.splice(index, 1)
} else {
index = limb.indexOf(text)
if (index !== -1) limb.splice(index, 1)
}
box.remove()
updateTotalCompensation()
}
function updateTotalCompensation() {
var selectionsDisplay = document.getElementById('selectionsDisplay')
if (selectionsDisplay.childNodes.length === 0) {
combinedPercentage = 0
totalCompensation = 0
document.getElementById('result').innerHTML = '0%'
document.getElementById('compensation').innerHTML = '$0.00'
return
}
combinedPercentage =
disabilities.reduce(function(acc, cur) {
return acc * (1 - cur / 100)
}, 1) * 100
combinedPercentage = 100 - combinedPercentage
combinedPercentage = Math.round(combinedPercentage / 10) * 10
console.log(combinedPercentage)
selectedOptions = []
document.querySelectorAll('.optional:checked').forEach(function(optional) {
selectedOptions.push(optional.id)
})
console.log(selectedOptions)
if (bilateralDisabilities.length > 1) {
var bilateralCombined =
bilateralDisabilities.reduce(function(acc, cur) {
return acc * (1 - cur / 100)
}, 1) * 100
bilateralCombined = 100 - bilateralCombined
bilateralCombined = Math.round(bilateralCombined - 10)
combinedPercentage =
Math.round((combinedPercentage + bilateralCombined) / 20) * 10
}
document.getElementById('result').innerHTML = combinedPercentage + '%'
var compensation = document.getElementById('compensation')
document.getElementById('result').innerHTML = combinedPercentage + '%'
console.log(totalCompensation)
// Default to single rate
var totalCompensation = compensationRates[combinedPercentage]['single']
// Watch dropdowns for changes
var childrenUnder18 = parseInt(
document.getElementById('childrenUnder18').value
)
var childrenOver18 = parseInt(document.getElementById('childrenOver18').value)
// Update selectedOptions array
if (childrenUnder18 > 0) {
if (!selectedOptions.includes('withOneChild')) {
selectedOptions.push('withOneChild')
totalCompensation =
compensationRates[combinedPercentage][selectedOptions.join('')]
console.log(totalCompensation + ' with one child')
}
if (childrenUnder18 > 1) {
var addChildUnder18 = childrenUnder18 - 1
console.log(addChildUnder18)
if (addChildUnder18 > 0) {
totalCompensation +=
addChildUnder18 *
compensationRates[combinedPercentage]['additionalChildUnder18']
}
} else {
totalCompensation =
compensationRates[combinedPercentage][selectedOptions.join('')]
}
} else {
selectedOptions = selectedOptions.filter(
(option) => option !== 'withOneChild'
)
}
if (childrenOver18 > 0) {
if (!selectedOptions.includes('withOneChild')) {
selectedOptions.push('withOneChild')
}
if (childrenOver18 > 1) {
var addChildOver18 = childrenOver18 - 1
if (addChildOver18 > 0) {
totalCompensation +=
addChildOver18 *
compensationRates[combinedPercentage]['additionalChildOver18']
}
} else {
totalCompensation = compensationRates[combinedPercentage]['withOneChild']
}
} else {
selectedOptions = selectedOptions.filter(
(option) => option !== 'withOneChild'
)
}
const selectedOptionKey = selectedOptions.join('')
if (compensationRates[combinedPercentage][selectedOptionKey]) {
totalCompensation = compensationRates[combinedPercentage][selectedOptionKey]
}
console.log(totalCompensation)
// Update total compensation display
compensation = document.getElementById('compensation')
compensation.innerHTML = '$' + totalCompensation.toFixed(2)
document.getElementById('result').innerHTML = combinedPercentage + '%'
document
.getElementById('childrenUnder18')
.addEventListener('change', updateTotalCompensation)
document
.getElementById('childrenOver18')
.addEventListener('change', updateTotalCompensation)
// Adjust based on selected options
if (compensationRates[combinedPercentage][selectedOptions.join('')]) {
totalCompensation =
compensationRates[combinedPercentage][selectedOptions.join('')]
}
console.log(totalCompensation)
compensation.innerHTML = '$' + totalCompensation.toFixed(2)
resultSpan.innerHTML = combinedPercentage + '%'
}
function clearTotals() {
document
.querySelectorAll('input[type="checkbox"]')
.forEach(function(checkbox) {
checkbox.checked = false
let label = checkbox.closest('label')
if (label) {
label.classList.remove('checked')
}
})
document.getElementById('childrenUnder18').value = '0'
document.getElementById('childrenOver18').value = '0'
limb = []
disabilities = []
bilateralDisabilities = []
selectedOptions = []
totalCompensation = 0
combinedPercentage = 0
var selectionsDisplay = document.getElementById('selectionsDisplay')
selectionsDisplay.innerHTML = ''
compensation = document.getElementById('compensation')
compensation.innerHTML = '$' + 0.0
document.getElementById('result').innerHTML = 0 + '%'
updateTotalCompensation()
}
document.addEventListener('DOMContentLoaded', (event) => {
function handleCheckboxChange(event) {
const group = event.target.closest('div')
const checkboxes = group.querySelectorAll('.optional')
checkboxes.forEach((checkbox) => {
if (checkbox !== event.target) {
checkbox.checked = false
const otherLabel = checkbox.closest('label')
otherLabel.classList.remove('checked')
}
})
let label = event.target.closest('label')
if (event.target.checked) {
label.classList.add('checked')
} else {
label.classList.remove('checked')
}
updateTotalCompensation()
console.log(totalCompensation)
}
document.querySelectorAll('.optional').forEach((checkbox) => {
checkbox.addEventListener('change', handleCheckboxChange)
})
})
calculateCompensation()
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.calculator {
max-width: 1150px;
margin: 50px;
padding: 20px 40px;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.body-part-sec {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(175px, 1fr));
gap: 1em;
margin: 2em 0;
}
.top-left,
.top-right,
.bottom-left,
.bottom-right {
width: fit-content;
margin: auto;
}
.body-part-sec button {
width: 150px;
height: 50px;
}
.body-part-container {
margin-bottom: 2em;
}
.selections {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 1em;
}
.optional {
position: absolute;
display: none;
}
.body-part-container button {
background-color: #ccc;
font-weight: bold;
font-size: 1.5em;
padding: 1em 2em;
margin: 0.5em;
}
.body-part-container button:hover,
.selections button:hover,
.marital-status label:hover,
.dependent-parents label:hover {
background-color: #2d5b87;
color: #fff;
cursor: pointer;
}
.selections button,
.marital-status label,
.dependent-parents label {
display: flex;
justify-content: center;
align-items: center;
border: 1px solid #ccc;
font-weight: bold;
font-size: 1em;
padding: .5em 2em;
margin: 0.5em;
}
.checked {
background-color: #2d5b87;
color: #fff;
}
.options-sec,
.dependent-children-container,
.percent-dollar {
display: flex;
justify-content: center;
align-items: center;
gap: 2em;
margin: 2em 0;
}
.dependent-children {
display: flex;
flex-direction: column;
gap: 1em;
}
.dependent-children select {
appearance: none;
background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23131313%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E");
background-repeat: no-repeat;
background-position: right 0.7rem top 50%;
background-size: 0.65rem auto;
}
.dependent-dropdown {
position: relative;
font-size: 1.5em;
padding: .25em .5em;
}
.estimated-total {
position: sticky;
bottom: 0;
color: #fff;
background-color: #2d5b87;
display: flex;
justify-content: center;
align-items: center;
gap: .5em;
margin: 2em 0;
padding: 1em 2em;
}
.totals {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: .5em;
}
.percent-dollar div {
font-size: 1.5em;
}
.percent-dollar span {
font-size: 2.5em;
}
.clear-btn {
padding: .5em 1em;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 1.25em;
margin-left: 2em;
}
.selections-display {
margin-top: 20px;
}
.selection-box {
display: inline-block;
padding: 10px;
margin: 5px;
background-color: #2d5b87;
color: #fff;
border-radius: 4px;
position: relative;
width: auto;
}
.selection-box .remove-box {
cursor: pointer;
color: #f1f1f1;
padding: 5px;
font-size: .75em;
}
<div class="calculator">
<h2>Veteran Disability Calculator</h2>
<div class="instructions"><span>Enter your disabilities using the buttons below.</span>
<span>If your disability is on an extremity push that proper leg or arm button then push the percentage</span>
</div>
<div class="body-part-sec">
<div class="top-left">
<button class="body-part arm" type="button" data-body-limb="arm">Left Arm</button>
</div>
<div class="top-right">
<button class="body-part arm" type="button" data-body-limb="arm">Right Arm</button>
</div>
<div class="bottom-left">
<button class="body-part leg" type="button" data-body-limb="leg">Left Leg</button>
</div>
<div class="bottom-right">
<button class="body-part leg" type="button" data-body-limb="leg">Right Leg</button>
</div>
</div>
<div>
<div class="selections">
<button class="percentage" value="10">10%</button>
<button class="percentage" value="20">20%</button>
<button class="percentage" value="30">30%</button>
<button class="percentage" value="40">40%</button>
<button class="percentage" value="50">50%</button>
<button class="percentage" value="60">60%</button>
<button class="percentage" value="70">70%</button>
<button class="percentage" value="80">80%</button>
<button class="percentage" value="90">90%</button>
<button class="percentage" value="100">100%</button>
</div>
</div>
<div id="selectionsDisplay" class="selections-display"></div>
<div class="options-sec">
<div class="marital-status">
<div>What is Your Marital Status?</div>
<label class="checked"><input class="optional" type="checkbox" id="single">Single</label>
<label><input class="optional" type="checkbox" id="withSpouse">Married</label>
</div>
<div class="dependent-parents">
<div>Do You Have Any Dependent Parents?</div>
<label class="checked"><input class="optional" type="checkbox" id="">None</label>
<label><input class="optional" type="checkbox" id="withOneParent">One Parent</label>
<label><input class="optional" type="checkbox" id="withTwoParents">Two Parents</label>
</div>
</div>
<div class="dependent-children-container">
<div class="dependent-children">
<label for="childrenUnder18">Dependent Children Under 18: </label>
<select class="dependent-dropdown" id="childrenUnder18">
<option id="0" value="0">0</option>
<option id="1" value="1">1</option>
<option id="2" value="2">2</option>
<option id="3" value="3">3</option>
<option id="4" value="4">4</option>
<option id="5" value="5">5</option>
<option id="6" value="6">6</option>
<option id="7" value="7">7</option>
<option id="8" value="8">8</option>
<option id="9" value="9">9</option>
<option id="10" value="10">10</option>
</select>
</div>
<div class="dependent-children">
<label for="childrenOver18">Dependent Children Over 18:</label>
<select class="dependent-dropdown" id="childrenOver18">
<option id="11" value="0">0</option>
<option id="12" value="1">1</option>
<option id="13" value="2">2</option>
<option id="14" value="3">3</option>
<option id="15" value="4">4</option>
<option id="16" value="5">5</option>
<option id="17" value="6">6</option>
<option id="18" value="7">7</option>
<option id="19" value="8">8</option>
<option id="20" value="9">9</option>
<option id="21" value="10">10</option>
</select>
</div>
</div>
<div class="estimated-total">
<div class="percent-dollar">
<div class="totals">Combined Disability: <span id="result">0%</span></div>
<div class="totals">Estimated Monthly Compensation: <span id="compensation">$0.00</span></div>
</div>
<button id="clearSelections" class="clear-btn" onclick="clearTotals()">Clear Selections</button>
</div>
</div>