Build a Cash Register Project - Build a Cash Register

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

If you scroll down the console you will see few Uncaught ReferenceError errors. Editor on page runs in strict mode, this means every variable has to be declared.

1 Like

Yes, this was my problem with one of the previous projects I just forgot it might be the same problem! :sweat_smile: