Tell us what’s happening:
I cannot get past Step 11. Apparently my #change-due element is not formatted correctly. It should output: STATUS: OPEN QUARTER: $0.5. Which my #cash-due is displaying but each bill and status are separated by paragraphs. This shouldn’t be an issue and I tried to remove the p elements and have everything as one paragraph. Only thing I have not tried is, changing #change-due element to something other than div element.
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>Cash Register</title>
<link rel="stylesheet" href="./styles.css">
<link rel="icon" type="img/png" href="https://d1nhio0ox7pgb.cloudfront.net/_img/o_collection_png/green_dark_grey/512x512/plain/cash_register.png">
</head>
<body>
<main>
<h1>Cash Register Project</h1>
<div id="change-due">
</div><!-- should output change amount as p elements for every bill/coin used whose sum is the change amount-->
<div id="input-container">
<label for="cash">Enter cash amount from customer:</label>
<input id="cash" type="number" value="" step="0.01" min="0" required/>
<!-- if the cash amount is lower than the price of item, alert the user with msg: "Customer does not have enough money to purchase the item"-->
<button id="purchase-btn">Purchase</button>
</div>
<div class="register">
<div class="price-display-container">
<p>Total: <span id="item-price"><strong>$1.87</strong></span></p>
</div>
<div class="bridge"></div>
<div class="register-body">
<div class="number-pad">
<button class="pad-btn" disabled></button>
<button class="pad-btn" disabled></button>
<button class="pad-btn" disabled></button>
<button class="pad-btn" disabled></button>
<button class="pad-btn" disabled></button>
<button class="pad-btn" disabled></button>
<button class="pad-btn" disabled></button>
<button class="pad-btn" disabled></button>
<button class="pad-btn" disabled></button>
</div>
<div id="drawer-cash-display">
<p><strong>Change in drawer:</strong></p>
<p>Pennies: $1.01</p>
<p>Nickels: $2.05</p>
<p>Dimes: $3.1</p>
<p>Quarters: $4.25</p>
<p>Ones: $90</p>
<p>Fives: $55</p>
<p>Tens: $20</p>
<p>Twenties: $60</p>
<p>Hundreds: $100</p>
</div>
</div>
<div class="register-drawer">
<div class="register-handle"></div>
</div>
</div>
</main>
<script src="script.js"></script>
</body>
</html>
/* file: script.js */
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]
];
const changeDue = document.getElementById("change-due");
const cashInput = document.getElementById("cash");
const purchaseBtn = document.getElementById("purchase-btn");
const priceSpan = document.getElementById("item-price");
const drawerCashDisplay = document.getElementById("drawer-cash-display");
function getAmountFromCurrency(currencyStr) {
switch (currencyStr) {
case "PENNY":
return 0.01;
case "NICKEL":
return 0.05;
case "DIME":
return 0.1;
case "QUARTER":
return 0.25;
case "ONE":
return 1;
case "FIVE":
return 5;
case "TEN":
return 10;
case "TWENTY":
return 20;
case "ONE HUNDRED":
return 100;
default:
return NaN;
}
}
function getFormattedCurrencyNames(currencyStr) {
switch (currencyStr) {
case "PENNY":
return "Pennies"
case "NICKEL":
return "Nickels"
case "DIME":
return "Dimes";
case "QUARTER":
return "Quarters";
case "ONE":
return "Ones";
case "FIVE":
return "Fives";
case "TEN":
return "Tens";
case "TWENTY":
return "Twenties";
case "ONE HUNDRED":
return "Hundreds";
default:
return '';
}
}
const cashInDrawer = () => {
return cid.reduce((sum, currency) => sum + currency[1], 0);
}
const subtractFromDrawer = (amountInCents) => {
const cashReturned = [
['PENNY', 0],
['NICKEL', 0],
['DIME', 0],
['QUARTER', 0],
['ONE', 0],
['FIVE', 0],
['TEN', 0],
['TWENTY', 0],
['ONE HUNDRED', 0]
];
let cidCopy = JSON.parse(JSON.stringify(cid));
cidCopy.forEach((unit) => unit[1] = Math.round(unit[1] * 100));
for (let i = cidCopy.length - 1; i >= 0;) {
const currencyInCents = Math.round(getAmountFromCurrency(cidCopy[i][0]) * 100);
const cidInCents = cidCopy[i][1];
if (amountInCents < currencyInCents || cidInCents === 0) {
i--;
continue;
}
subInCents = (amountInCents < cidInCents) ? Math.floor(amountInCents/currencyInCents) * currencyInCents : cidInCents;
amountInCents -= subInCents;
cidCopy[i][1] -= subInCents;
cashReturned[i][1] += subInCents;
}
if (amountInCents != 0) {
return undefined;
}
cidCopy.forEach((unit) => unit[1] = unit[1] / 100)
cid = [...cidCopy];
/*
remember - map() returns a shallow copy, the callback function must return the element modified, not remapped to a new type hence, we have to return an array with callback function in map()
*/
return cashReturned.filter((unit) => unit[1] !== 0).map((unit) => [unit[0],unit[1]/100]); // set to !== comparator for debugging purposes
};
const addToDrawer = (amountInCents) => {
for (let i = cid.length - 1; i >= 0;) {
const currencyInCents = Math.round(getAmountFromCurrency(cid[i][0]) * 100);
if(amountInCents < currencyInCents){
i--;
continue;
}
const addInCents = Math.floor(amountInCents / currencyInCents) * currencyInCents;
amountInCents -= addInCents;
cid[i][1] = (Math.round(cid[i][1] * 100) + addInCents) / 100;
}
}
const displayDrawer = () => {
drawerCashDisplay.innerHTML = `<p><strong>Change in drawer:</strong></p>`;
for(currency of cid){
drawerCashDisplay.innerHTML += `
<p>${getFormattedCurrencyNames(currency[0])}: $${currency[1]}</p>
`;
}
}
const displayChange = (amount) =>{
const statusFlags = [
"No change due - customer paid with exact cash",
"Status: CLOSED",
"Status: OPEN",
"Status: INSUFFICIENT_FUNDS"
];
let status;
changeDue.style.display = "block";
if(amount){
if(amount.length === 0){
status = statusFlags[0];
}
else if(cashInDrawer() == 0){
status = statusFlags[1];
}
else{
status = statusFlags[2]
}
}
else{
status = statusFlags[3];
}
changeDue.innerHTML = `<p>${status}</p>`;
for(currency of amount.reverse()){
changeDue.innerHTML += `
<p>${currency[0]}: $${currency[1]}</p>
`;
}
}
const getInputValueFrom = (element) => {
return Number(element.value);
}
const updateUI = () => {
const cash = getInputValueFrom(cashInput);
priceSpan.textContent = `$${price}`;
if (isNaN(cash) || isNaN(price)) {
alert("Please enter a dollar amount");
return;
}
const priceInCents = Math.round(price * 100);
const cashInCents = Math.round(cash * 100);
if(cashInCents < priceInCents){
alert("Customer does not have enough money to purchase the item");
return;
}
const changeAmount = subtractFromDrawer(cashInCents - priceInCents);
displayChange(changeAmount);
displayDrawer();
}
purchaseBtn.addEventListener("click", updateUI);
cashInput.addEventListener("keydown", (event) => {
if (event.key == "Enter") {
updateUI();
}
});
/* file: styles.css */
*,
*::before,
*::after{
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root{
--bg-col: #18223f;
--register-col: #5c5c7e;
--register-screen-col: #a0a0a0;
--register-btn-col: #c5a86a;
--purchase-btn-col: #d8c34d;
--purchase-btn-col2: #AE8D44;
--input-bg-col: #d8d8d8;
font-size: 1.3rem;
}
h1{
margin: 15px 0;
}
main{
display:flex;
flex-direction: column;
align-items: center;
padding: 35px 50px;
min-width: fit-content;
}
body{
text-align:center;
color: white;
background-color: var(--bg-col);
}
#change-due{
display:none;
margin: 0 auto;
border: 3px double white;
text-align:left;
width: fit-content;
max-width: 600px;
height: fit-content;
padding: 15px;
}
#input-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
margin: 15px auto 35px auto;
}
#input-container > *{
display:block;
margin: 0 auto;
}
#cash {
font-size: 1.4rem;
height: 1.5rem;
width: 15ch;
background-color: var(--input-bg-col);
border: solid 1px rgba(0, 0, 0, 0.699);
border-radius: 4px;
outline:none;
}
#cash:focus{
outline: 2px solid var(--register-col);
}
#purchase-btn{
font-size: 1rem;
background: linear-gradient(to bottom, var(--purchase-btn-col), var(--purchase-btn-col) 30%, var(--purchase-btn-col2));
padding: 3px;
border-color: var(--purchase-btn-col2);
}
#purchase-btn:hover{
cursor: pointer;
}
.register{
display:flex;
flex-direction: column;
justify-content: space-between;
align-items:center;
margin: 0 auto;
width: fit-content;
height: fit-content;
}
.price-display-container{
display: flex;
flex-direction: row;
justify-content:space-between;
align-items: center;
margin-left: 250px;
background-color: var(--register-screen-col);
border: 8px solid var(--register-col);
border-radius: 6px;
padding: 3px;
}
#price-display{
height: 1rem;
color:black;
text-align: center;
font-size: 1rem;
}
.bridge{
margin-left: 250px;
width: 20px;
height: 30px;
background-color: var(--register-col);
}
.register-body{
display:flex;
flex-direction: row;
justify-content:space-around;
align-items: center;
width: 400px;
height: 250px;
background-color: var(--register-col);
border-radius: 30px 30px 0 0;
margin: 0 auto;
}
.number-pad{
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: auto auto auto;
gap: 10px;
width: 100px;
height: 100px;
}
.pad-btn{
background-color: var(--input-bg-col);
border-radius: 3px;
border-style:none;
outline: none;
pointer-events: none;
cursor: not-allowed;
box-shadow: none;
}
#drawer-cash-display{
background-color: var(--register-screen-col);
color: black;
height: 200px;
width: 200px;
padding: 10px;
font-family:'Times New Roman', Times, serif;
text-align: left;
overflow: auto;
}
.register-drawer{
position:relative;
margin: 0 auto;
width: 470px;
height: 90px;
background-color: var(--register-col);
border-radius: 30px 30px 0 0;
border: 10px solid var(--bg-col);
}
.register-handle{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 30px;
height: 30px;
border-radius: 50%;
border: 5px solid var(--bg-col);
}
Your browser information:
User Agent is: Mozilla/5.0 (X11; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0
Challenge Information:
Build a Cash Register Project - Build a Cash Register