Build a Cash Register Project - Build a Cash Register

Tell us what’s happening:

When I test my code manually it clears all the tests but when the tests run it says I failed. I don’t wanna have to rewrite my code from scratch.

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Issac's Cash Register</title>
  <link rel="stylesheet" href="styles.css" />
</head>

<body>
  <main>
    <div class="computer">
      <div class="screen">
        <div id="change-due">Status: </div>
        <div class="info-box">
          <button id="change-price-btn" type="button" class="btn">
          Change Price
        </button>
        <div class="info" id="price-element">PRICE: $</div>
          <input type="text" class="cash" id="cash" placeholder="Amount of Cash..."></input>
          <button id="purchase-btn" type="button" class="btn">
            Purchase
          </button>
        <button id="reset-btn" type="button" class="btn">
          Reset
        </button>
          </div>
      </div>
      <div class="register">
        <div class="total-change drawer">Total Change: $</div>
        <div class="ONE drawer"></div>
        <div class="PENNY drawer"></div>
        <div class="FIVE drawer"></div>
        <div class="NICKEL drawer"></div>
        <div class="TEN drawer"></div>
        <div class="DIME drawer"></div>
        <div class="TWENTY drawer"></div>
        <div class="QUARTER drawer"></div>
        <div class="HUNDRED drawer"></div>
      </div>
    </div>
  </main>
  <script src="./script.js"></script>
</body>
</html>
/* file: script.js */
const changePriceBtn = document.getElementById("change-price-btn");
const priceElement = document.getElementById("price-element");
const cash = document.getElementById("cash");
const changeDue = document.getElementById("change-due");
const purchaseBtn = document.getElementById("purchase-btn");
const resetBtn = document.getElementById("reset-btn");
const changeDrawer = document.querySelectorAll(".drawer");

let price = 1.87;
let pricePrime = price;
let bills = [];
let amounts = [];
let amountsTwo = [];
let amountsThree = [];
let change = 0;
let cid = [
  ['PENNY', 1.01],
  ['NICKEL', 2.05],
  ['DIME', 3.1],
  ['QUARTER', 4.25],
  ['ONE', 90],
  ['FIVE', 55],
  ['TEN', 20],
  ['TWENTY', 60],
  ['ONE HUNDRED', 100]
];
/*let cid = [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]];*/
let cidPrime = JSON.parse(JSON.stringify(cid));
let newCid = true
let cidTwo = []
const worth = [0.01,0.05,0.1,0.25,1,5,10,20,100]
////////////////////////////////////////////////////////////
const sortRegister = () => {
  for (let i = 0; i < cid.length; i++) {
    for (let j = 0; j < cid[i].length; j++) {
      if (typeof cid[i][j] === 'number') {
        amounts.push(cid[i][j]);
        amountsTwo.push(cid[i][j])
        amountsThree.push(cid[i][j])
      } else {
        bills.push(cid[i][j])
      }
    }
  }
}
sortRegister()
////////////////////////////////////////////////////////////
const updateCid = () => {
  for (let i = 0; i < cid.length; i++) {
    for (let j = 0; j < cid[i].length; j++) {
      if (typeof cid[i][j] === 'number') {
        cid[i][j] = amounts[i]
      } 
    }
  }
}
////////////////////////////////////////////////////////////
const updateChangeDue = () => {
  console.log("hello")
  let cidTwo = []
  let x = amountsTwo.map(function(item, index) {
  return parseFloat((item - amounts[index]).toFixed(2));
})
  const combinedArray = bills.map((element1, index) => {
  const element2 = x[index] || ""; // Handle cases where array2 is shorter
  if (element2 === "") {
    element1 = ""
  }
  return element1 + ": $" + element2;
});
  console.log(combinedArray)
  for (let i = 0; i < combinedArray.length; i++) {
    if (combinedArray[i] !== ": $") {
      cidTwo.unshift(combinedArray[i])
    }
  }
  let result = cidTwo.join(" ")
  console.log(parseFloat((totalChange + price).toFixed(2)), parseFloat(cash.value))
  console.log(cidTwo)
  parseFloat((totalChange + price).toFixed(2)) !== parseFloat(cash.value) ? (cidTwo.length === 0 ? changeDue.textContent += (" CLOSED " + result) : changeDue.textContent += (" OPEN " + result)) : changeDue.textContent += (" CLOSED " + result)
}
////////////////////////////////////////////////////////////
let totalChange = parseFloat(amounts.reduce((a, b) => a + b, 0).toFixed(2)) 

priceElement.textContent += `${price}`;
////////////////////////////////////////////////////////////
const fillRegister = (bills, amounts) => {
  for (let i = 0; i < changeDrawer.length; i++) {
    for (let j = 0; j < bills.length; j++) {
      if (changeDrawer[i].classList.contains(bills[j])) {
        changeDrawer[i].textContent = `${bills[j]}: $${amounts[j]}`
      } else if (changeDrawer[i].classList.contains("HUNDRED") && bills[j] === "ONE HUNDRED") {
        changeDrawer[i].textContent = `${bills[j]}: $${amounts[j]}`
      } else if (changeDrawer[i].classList.contains("total-change")) {
        changeDrawer[i].textContent = `Total Change: $${parseFloat(amounts.reduce((a, b) => a + b, 0).toFixed(2))}`
      }
    }
  } 
};
fillRegister(bills, amounts)
////////////////////////////////////////////////////////////
const checkChange = (cash) => {
  let highest = -Infinity;
  let newhigh = -Infinity;
  let first = 0
  
  for (let i = amountsThree.length -1 ; i > -1 ; i--) {
      if (cash >= worth[i] && amountsThree[i] >= worth[i] && first === 0) {
        console.log(first, worth[i] , amountsThree[i])
        first++
        let remainder = parseFloat((cash % worth[i]).toFixed(2));
        highest = cash >= amountsThree[i] ? amountsThree[i] : cash - remainder
        amountsThree[i] -= highest;
        newhigh = parseFloat((cash - highest).toFixed(2));        
      }
    }
  console.log(highest)
  return cash != 0 ? (highest == -Infinity ? false : checkChange(newhigh)) : true
}
//console.log(checkChange(41))
////////////////////////////////////////////////////////////
const giveChange = (cash) => {
  console.log("giving",cash)
  let conditionMet = false;
  newCid = false
  fillRegister(bills, amounts);
  cash = parseFloat(cash.toFixed(2))
  let highest = -Infinity;
  let newhigh = -Infinity;
  let first = 0
  
  if (cash !== 0) {
    for (let i = amounts.length -1 ; i > -1 ; i--) {
      if (cash >= worth[i] && amounts[i] >= worth[i] && first === 0) {
        first++
        conditionMet = true;
        let remainder = parseFloat((cash % worth[i]).toFixed(2));
        highest = cash >= amounts[i] ? amounts[i] : cash - remainder
        amounts[i] -= highest;
        updateCid();
        newhigh = parseFloat((cash - highest).toFixed(2));
        giveChange(newhigh)
      } 
    }
  } else if (cash === 0) {
    updateChangeDue()
  }
}
////////////////////////////////////////////////////////////
const resetRegister = () => {
  changeDue.textContent = ""
  if (newCid) {
    cidPrime = JSON.parse(JSON.stringify(cid));
    console.log(`New cid ${cidPrime}`)
  } else if (!newCid) {
    console.log(`Old cid ${cidPrime}`)
  }
  newCid = true
  cid = JSON.parse(JSON.stringify(cidPrime))
  console.log(pricePrime)
  
  bills = [];
  amounts = [];
  amountsTwo = [];
  amountsThree = [];
  sortRegister();
  fillRegister(bills, amounts)
}
resetBtn.addEventListener("click", () => {
  resetRegister()
  price = pricePrime
  priceElement.textContent = `PRICE: $${price}`;
})
////////////////////////////////////////////////////////////
purchaseBtn.addEventListener("click", () => {
  resetRegister()
  changeDue.textContent = ""
  let str = cash.value
  const isValid = str.search(/^\$?\d*(\.\d{1,2})?$/) >= 0;
  let num = Number(str.replace(/[\$,]/g, ''));
  let leftover = parseFloat((num - price).toFixed(2));
  let register = parseFloat((totalChange + price).toFixed(2))
  console.log(leftover, totalChange)
  
  if (isValid && leftover <= totalChange) {
    console.log("yep1")
    if (leftover === 0) {
      changeDue.textContent = ""
      giveChange(leftover);
      changeDue.textContent = "No change due - customer paid with exact cash"
    } else if (leftover <= totalChange && leftover > 0) {
      changeDue.textContent = "Status: "
      if (checkChange(leftover)) {
        giveChange(leftover);
      }  else if (!checkChange(leftover)) {
        changeDue.textContent += "INSUFFICIENT_FUNDS"
      }
    } else if (leftover < totalChange && leftover < 0) {
      changeDue.textContent += "Status: INSUFFICIENT_FUNDS"
      alert("Customer does not have enough money to purchase the item")
    }
  } else if (isValid && leftover > totalChange) {
    changeDue.textContent += "Status: INSUFFICIENT_FUNDS"
  } else if (!isValid) {
    alert("Enter a valid price (Ex $12.23, .45, 67.89)")
  }
  cash.value = ""
})
////////////////////////////////////////////////////////////
changePriceBtn.addEventListener("click", () => {
  let str = cash.value
  const isValid = str.search(/^\$?\d*(\.\d{1,2})?$/) >= 0;
  let num = Number(str.replace(/[\$,]/g, ''));
  
  
  if (isValid && num) {
    priceElement.textContent = "PRICE: $"
    price = parseFloat(cash.value)
    priceElement.textContent += `${price}`;
    cash.value = ""
  } else {
    alert("Enter a valid price (Ex $12.23, .45, 67.89)")
  }
})
/* file: styles.css */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.computer {
  background: gray;
  width: 400px;
  height: 250px;
  margin-left: 33%;
  margin-top: 10px
}

.screen {
  background: blue;
  width: 380px;
  height: 200px;
  margin-left: 10px;
  margin-top: 30px;
  display: flex
}

#change-due {
  background: white;
  width: 152px;
  height: 170px;
  text-align: center;
  padding-top: 15px;
  margin-top: 15px;
  margin-left: 14px
}

.info-box {
  background: green;
  width: 180px;
  height: 170px;
  margin-left: 14px;
  padding-top: 15px;
  margin-top: 15px;
  padding-left: 10px;
}

.info{
  margin-top: 15px;
  margin-bottom: 12px
}

#change-price-btn {
}

.register {
  width: 400px;
  height: 200px;
  margin-top: 50px;
  display: grid;
  grid-template-columns: auto auto
}

.drawer {
  background: white;
  border: dotted black
}

.myStyle {
  background-color: coral;
  padding: 16px;
}

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 OPR/115.0.0.0 (Edition std-1)

Challenge Information:

Build a Cash Register Project - Build a Cash Register

You shouldn’t use global variables like this - it means your function can only run once but the tests call your function many times back to back.

I don’t get it; wouldn’t the same be true for the cid and price variables? What makes them different?

you don’t change cid and price

Your code contains global variables that are changed each time the function is run. This means that after each function call completes, subsequent function calls start with the previous value. To fix this, make sure your function doesn’t change any global variables, and declare/assign variables within the function if they need to be changed.

Example:

var myGlobal = [1];
function returnGlobal(arg) {
  myGlobal.push(arg);
  return myGlobal;
} // unreliable - array gets longer each time the function is run

function returnLocal(arg) {
  var myLocal = [1];
  myLocal.push(arg);
  return myLocal;
} // reliable - always returns an array of length 2

I updated my code to have the global variables in an object, but am getting the same result. Does the object need to also be inside a function? If so, how do I access the info?

const changePriceBtn = document.getElementById("change-price-btn");
const priceElement = document.getElementById("price-element");
const cash = document.getElementById("cash");
const changeDue = document.getElementById("change-due");
const purchaseBtn = document.getElementById("purchase-btn");
const resetBtn = document.getElementById("reset-btn");
const changeDrawer = document.querySelectorAll(".drawer");

let price = 1.87;
let cid = [
  ['PENNY', 1.01],
  ['NICKEL', 2.05],
  ['DIME', 3.1],
  ['QUARTER', 4.25],
  ['ONE', 90],
  ['FIVE', 55],
  ['TEN', 20],
  ['TWENTY', 60],
  ['ONE HUNDRED', 100]
];
/*let cid = [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]];*/
const worth = [0.01,0.05,0.1,0.25,1,5,10,20,100]
let obj = {
  pricePrime : price,
  bills : [],
  amounts : [],
  amountsTwo : [],
  amountsThree : [],
  change : 0,
  cidPrime : JSON.parse(JSON.stringify(cid)),
  newCid : true,
}
////////////////////////////////////////////////////////////
const sortRegister = () => {
  for (let i = 0; i < cid.length; i++) {
    for (let j = 0; j < cid[i].length; j++) {
      if (typeof cid[i][j] === 'number') {
        obj.amounts.push(cid[i][j]);
        obj.amountsTwo.push(cid[i][j])
        obj.amountsThree.push(cid[i][j])
      } else {
        obj.bills.push(cid[i][j])
      }
    }
  }
}
sortRegister()
////////////////////////////////////////////////////////////
const updateCid = () => {
  for (let i = 0; i < cid.length; i++) {
    for (let j = 0; j < cid[i].length; j++) {
      if (typeof cid[i][j] === 'number') {
        cid[i][j] = obj.amounts[i]
      } 
    }
  }
}
////////////////////////////////////////////////////////////
const updateChangeDue = () => {
  console.log("hello")
  let cidTwo = []
  let x = obj.amountsTwo.map(function(item, index) {
  return parseFloat((item - obj.amounts[index]).toFixed(2));
})
  const combinedArray = obj.bills.map((element1, index) => {
  const element2 = x[index] || ""; // Handle cases where array2 is shorter
  if (element2 === "") {
    element1 = ""
  }
  return element1 + ": $" + element2;
});
  console.log(combinedArray)
  for (let i = 0; i < combinedArray.length; i++) {
    if (combinedArray[i] !== ": $") {
      cidTwo.unshift(combinedArray[i])
    }
  }
  let result = cidTwo.join(" ")
  console.log(parseFloat((totalChange + price).toFixed(2)), parseFloat(cash.value))
  console.log(cidTwo)
  parseFloat((totalChange + price).toFixed(2)) !== parseFloat(cash.value) ? (cidTwo.length === 0 ? changeDue.textContent += (" CLOSED " + result) : changeDue.textContent += (" OPEN " + result)) : changeDue.textContent += (" CLOSED " + result)
}
////////////////////////////////////////////////////////////
let totalChange = parseFloat(obj.amounts.reduce((a, b) => a + b, 0).toFixed(2)) 

priceElement.textContent += `${price}`;
////////////////////////////////////////////////////////////
const fillRegister = () => {
  for (let i = 0; i < changeDrawer.length; i++) {
    for (let j = 0; j < obj.bills.length; j++) {
      if (changeDrawer[i].classList.contains(obj.bills[j])) {
        changeDrawer[i].textContent = `${obj.bills[j]}: $${obj.amounts[j]}`
      } else if (changeDrawer[i].classList.contains("HUNDRED") && obj.bills[j] === "ONE HUNDRED") {
        changeDrawer[i].textContent = `${obj.bills[j]}: $${obj.amounts[j]}`
      } else if (changeDrawer[i].classList.contains("total-change")) {
        changeDrawer[i].textContent = `Total Change: $${parseFloat(obj.amounts.reduce((a, b) => a + b, 0).toFixed(2))}`
      }
    }
  } 
};
fillRegister()
////////////////////////////////////////////////////////////
const checkChange = (cash) => {
  let highest = -Infinity;
  let newhigh = -Infinity;
  let first = 0
  
  for (let i = obj.amountsThree.length -1 ; i > -1 ; i--) {
      if (cash >= worth[i] && obj.amountsThree[i] >= worth[i] && first === 0) {
        console.log(first, worth[i] , obj.amountsThree[i])
        first++
        let remainder = parseFloat((cash % worth[i]).toFixed(2));
        highest = cash >= obj.amountsThree[i] ? obj.amountsThree[i] : cash - remainder
        obj.amountsThree[i] -= highest;
        newhigh = parseFloat((cash - highest).toFixed(2));        
      }
    }
  console.log(highest)
  return cash != 0 ? (highest == -Infinity ? false : checkChange(newhigh)) : true
}
//console.log(checkChange(41))
////////////////////////////////////////////////////////////
const giveChange = (cash) => {
  console.log("giving",cash)
  let conditionMet = false;
  obj.newCid = false
  fillRegister();
  cash = parseFloat(cash.toFixed(2))
  let highest = -Infinity;
  let newhigh = -Infinity;
  let first = 0
  
  if (cash !== 0) {
    for (let i = obj.amounts.length -1 ; i > -1 ; i--) {
      if (cash >= worth[i] && obj.amounts[i] >= worth[i] && first === 0) {
        first++
        conditionMet = true;
        let remainder = parseFloat((cash % worth[i]).toFixed(2));
        highest = cash >= obj.amounts[i] ? obj.amounts[i] : cash - remainder
        obj.amounts[i] -= highest;
        updateCid();
        newhigh = parseFloat((cash - highest).toFixed(2));
        giveChange(newhigh)
      } 
    }
  } else if (cash === 0) {
    updateChangeDue()
  }
}
//console.log(giveChange(41))
////////////////////////////////////////////////////////////
const resetRegister = () => {
  changeDue.textContent = ""
  if (obj.newCid) {
    obj.cidPrime = JSON.parse(JSON.stringify(cid));
    console.log(`New cid ${obj.cidPrime}`)
  } else if (!obj.newCid) {
    console.log(`Old cid ${obj.cidPrime}`)
  }
  obj.newCid = true
  cid = JSON.parse(JSON.stringify(obj.cidPrime))
  console.log(obj.pricePrime)
  
  obj.bills = [];
  obj.amounts = [];
  obj.amountsTwo = [];
  obj.amountsThree = [];
  sortRegister();
  fillRegister()
}
resetBtn.addEventListener("click", () => {
  resetRegister()
  price = obj.pricePrime
  priceElement.textContent = `PRICE: $${price}`;
})
////////////////////////////////////////////////////////////
purchaseBtn.addEventListener("click", () => {
  resetRegister()
  changeDue.textContent = ""
  let str = cash.value
  const isValid = str.search(/^\$?\d*(\.\d{1,2})?$/) >= 0;
  let num = Number(str.replace(/[\$,]/g, ''));
  let leftover = parseFloat((num - price).toFixed(2));
  let register = parseFloat((totalChange + price).toFixed(2))
  console.log(leftover, totalChange)
  
  if (isValid && leftover <= totalChange) {
    console.log("yep1")
    if (leftover === 0) {
      changeDue.textContent = ""
      giveChange(leftover);
      changeDue.textContent = "No change due - customer paid with exact cash"
    } else if (leftover <= totalChange && leftover > 0) {
      changeDue.textContent = "Status: "
      if (checkChange(leftover)) {
        giveChange(leftover);
      }  else if (!checkChange(leftover)) {
        changeDue.textContent += "INSUFFICIENT_FUNDS"
      }
    } else if (leftover < totalChange && leftover < 0) {
      changeDue.textContent += "Status: INSUFFICIENT_FUNDS"
      alert("Customer does not have enough money to purchase the item")
    }
  } else if (isValid && leftover > totalChange) {
    changeDue.textContent += "Status: INSUFFICIENT_FUNDS"
  } else if (!isValid) {
    alert("Enter a valid price (Ex $12.23, .45, 67.89)")
  }
  cash.value = ""
})
////////////////////////////////////////////////////////////
changePriceBtn.addEventListener("click", () => {
  let str = cash.value
  const isValid = str.search(/^\$?\d*(\.\d{1,2})?$/) >= 0;
  let num = Number(str.replace(/[\$,]/g, ''));
  
  
  if (isValid && num) {
    price = parseFloat(cash.value)
    priceElement.textContent = `PRICE: $${price}`;
    cash.value = ""
  } else {
    alert("Enter a valid price (Ex $12.23, .45, 67.89)")
  }
})
////////////////////////////////////////////////////////////

Putting the global variables in a global variable doesn’t get rid of the problem of having global variables with state, no.

Your function should use arguments and return values to pass information around.