Snurf
Snurf

Reputation: 11

How can I total the values in a table of prices?

How do I go about writing a total function that adds up a users bill at a concession stand? Here is a photo, a certain price is attached to each button and added to the total when clicked. How can I get all displayed prices to add up and be displayed in my total box? Thank you for any help in advance! ja

The function for selecting items:

function orderUp(val) {
            switch(val){
                case "hb":
                if(!voidItem.checked){
                    hbQty++
                    hbSub += 3.00
                    }else{
                        if(hbQty >0){
                            hbQty--
                            hbSub -= 3.00
                        }
                    }
                    break;
                case "cb":
                if(!voidItem.checked){
                    cbQty++
                    cbSub += 3.50
                    }else{
                        if(cbQty >0){
                            cbQty--
                            cbSub -= 3.50
                        }
                    }
                    break;

The function displaying the results:

function recieptOut(){
            var outputStr = ""
            if (hbQty > 0){
                outputStr += "<div class = 'row'><div class = 'col'>" + hbQty + "</div>"
                outputStr += "<div class='col'>" + hbName + "</div>"
                outputStr += "<div class='col'>" + hbSub + "</div></div>"
                }
            if (cbQty > 0){
                outputStr += "<div class = 'row'><div class = 'col'>" + cbQty + "</div>"
                outputStr += "<div class='col'>" + cbName + "</div>"
                outputStr += "<div class='col'>" + cbSub + "</div></div>"   
            }

Upvotes: 0

Views: 84

Answers (1)

Mulan
Mulan

Reputation: 135197

You have a very broad question but I can tell you're way off in the woods. I hope this answer helps show you some ways to go about completing the task -

<body>

  <main id="app"><main>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>

  <script src="shop.js"></script>

  <script>
    /* items on the menu */
    const menuItems =
      [ { name: "Hamburger", price: 3.00 }
      , { name: "Hotdog", price: 2.50 }
      , { name: "Nachos", price: 3.00 }
      , { name: "Chips", price: 0.75 }
      , { name: "Cheeseburger", price: 3.50 }
      , { name: "Bottled Water", price: 2.00 }
      , { name: "Fries", price: 2.50 }
      ]

    /* where to display app */
    const main =
      document.querySelector("main")

    /* run the shop */
    runShop(main, menuItems)
  </script>
</body>

shop.js

The runShop function takes an element to draw the shop and the items that are available to order -

const initialState =
  { cart: [] }

const runShop = (root, items = []) => {
  const menu = makeMenu(items)
  const cart = makeCart()
  const total = makeTotal()
  const reset = makeButton("New Order", newOrder)

  root.appendChild(menu)
  root.appendChild(cart)
  root.appendChild(total)
  root.appendChild(reset)

  let state = initialState

  dispatch = (action) => {
    state = responder(state, action)
    draw(state, { menu, cart, total })
  }

  dispatch({ action: "NEW ORDER" })
}

As we can see, the runShop function breaks the work down into smaller parts too. Here's the makeMenu section -

const makeMenu = (items = []) => {
  const e = document.createElement("div")
  for (const i of items)
    e.appendChild(makeButton(i.name, addToOrder(i)))
  return e
}

const makeButton = (text, onclick) => {
  const e = document.createElement("button")
  e.appendChild(document.createTextNode(text))
  e.onclick = onclick
  return e
}

We continue breaking things down like this for the other sections too, makeCart and makeTotal -

const makeCart = () => {
  return document.createElement("div")
}

const makeCartItem = (item = {}) => {
  const e = document.createElement("div")
  const t = `${item.name} x ${item.qty} (${drawMoney(item.price)} each)`
  e.appendChild(document.createTextNode(t))
  return e
}

const makeTotal = () => {
  return document.createElement("div")
}

Now we need a way to draw the shop. This function calls for drawMoney and calcTotal functions which we also implement -

const draw = (state = {}, { menu, cart, total }) => {
  /* menu */
  // no changes...

  /* cart */
  cart.textContent = ""
  for (const item of state.cart)
    cart.appendChild(makeCartItem(item))

  /* total */
  total.textContent =
    `Total: ${drawMoney(calcTotal(state.cart))}`
}

const drawMoney = (m = 0) =>
  m.toLocaleString
    ( "en-US"
    , { style: "currency" , currency: "USD" }
    )

const calcTotal = (items = []) =>
  items.reduce
    ( (total, { qty = 0, price = 0 }) =>
        total + (qty * price)
    , 0
    )

The menu buttons call addToOrder(item) and the reset button calls newOrder. These are simple calls to the shop's dispatch which is implemented in runShop -

const addToOrder = (item = {}) => event =>
  dispatch({ action: "ADD ITEM", item })

const newOrder = event =>
  dispatch({ action: "NEW ORDER" })

The responder receives a call from dispatch and gives you a place to update your shop's state for each user action -

const responder = (state, action) => {
  switch (action.action) {

    case "NEW ORDER":
      return initialState

    case "ADD ITEM":
      return { ...state, cart: insert(state.cart, action.item) }

    /* implement other actions */
    // case ...

    default:
      throw Error(`unsupported action ${action.action}`)
  }
  return state
}

The "NEW ORDER" action is easy to handle, we simply return the empty state, initialState. The "ADD ITEM" must insert an item in state.cart. We use an insert helper function because we want fine control over how an item is added -

  • If the item is not already in the cart, add it to the cart with qty = 0
  • Otherwise, update the matching item's qty to qty + 1
const { fromJS } = require("immutable")

const insert = (cart = [], item = {}) => {
  /* find item in cart? */
  const location =
    cart.findIndex(i => i.name === item.name)

  /* insert new item */
  if (location === -1)
    return [...cart, { ...item, qty: 1 } ]

  /* update existing item */
  else
    return fromJS(cart)
      .update
        ( location
        , item => item.update("qty", n => n + 1)
        )
      .toJS()
}

code demo

Click "Run code snippet" below to see this program run in your own browser -

<main id="app"><main>

<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>

<script>
  /* shop.js */
  const { fromJS } = Immutable;

  let dispatch = _ => {
    throw Error("must initialize shop first")
  }

  /* element constructors */
  const makeMenu = (items = []) => {
    const e = document.createElement("div")
    for (const i of items)
      e.appendChild(makeButton(i.name, addToOrder(i)))
    return e
  }

  const makeButton = (text, onclick) => {
    const e = document.createElement("button")
    e.appendChild(document.createTextNode(text))
    e.onclick = onclick
    return e
  }

  const makeCart = () => {
    return document.createElement("div")
  }

  const makeCartItem = (item = {}) => {
    const e = document.createElement("div")
    const t = `${item.name} x ${item.qty} (${drawMoney(item.price)} each)`
    e.appendChild(document.createTextNode(t))
    return e
  }

  const makeTotal = () => {
    return document.createElement("div")
  }

  /* actions */
  const addToOrder = (item = {}) => event =>
    dispatch({ action: "ADD ITEM", item })

  const newOrder = event =>
    dispatch({ action: "NEW ORDER" })


  /* renderers */
  const draw = (state = {}, { menu, cart, total }) => {
    /* menu */
    // no changes...

    /* cart */
    cart.textContent = ""
    for (const item of state.cart)
      cart.appendChild(makeCartItem(item))

    /* total */
    total.textContent =
      `Total: ${drawMoney(calcTotal(state.cart))}`
  }

  const drawMoney = (m = 0) =>
    m.toLocaleString
      ( "en-US"
      , { style: "currency" , currency: "USD" }
      )

  const calcTotal = (items = []) =>
    items.reduce
      ( (total, { qty = 0, price = 0 }) =>
          total + (qty * price)
      , 0
      )

  /* state */
  const initialState =
    { cart: [] }

  const responder = (state, action) => {
    switch (action.action) {
      case "NEW ORDER":
        return initialState
      case "ADD ITEM":
        return { ...state, cart: insert(state.cart, action.item) }
      default:
        throw Error(`unsupported action ${action.action}`)
    }
    return state
  }

  const insert = (cart = [], item = {}) => {
    /* find item in cart? */
    const location =
      cart.findIndex(i => i.name === item.name)

    /* insert new item */
    if (location === -1)
      return [...cart, { ...item, qty: 1 } ]

    /* update existing item */
    else
      return fromJS(cart)
        .update
          ( location
          , item => item.update("qty", n => n + 1)
          )
        .toJS()
  }

  /* run */
  const runShop = (root, items = []) => {
    const menu = makeMenu(items)
    const cart = makeCart()
    const total = makeTotal()
    const reset = makeButton("New Order", newOrder)

    root.appendChild(menu)
    root.appendChild(cart)
    root.appendChild(total)
    root.appendChild(reset)

    let state = initialState

    dispatch = (action) => {
      state = responder(state, action)
      draw(state, { menu, cart, total })
    }

    dispatch({ action: "NEW ORDER" })
  }
</script>

<script>
  /* items on the menu */
  const menuItems =
    [ { name: "Hamburger", price: 3.00 }
    , { name: "Hotdog", price: 2.50 }
    , { name: "Nachos", price: 3.00 }
    , { name: "Chips", price: 0.75 }
    , { name: "Cheeseburger", price: 3.50 }
    , { name: "Bottled Water", price: 2.00 }
    , { name: "Fries", price: 2.50 }
    ]

  /* where to display app */
  const main =
    document.querySelector("main")

  /* run the shop */
  runShop(main, menuItems)
</script>


remarks

I understand it's probably a lot to take in but hopefully this shows you how you can organise your data and some practical ways to break the big problem down into smaller parts. Each section of the program can be sensibly expanded to accommodate your other needs.

I don't know exactly where you're coming from, but I'm happy to help with specific questions when you encounter them. The code structures presented here are closely related to ReactJS. I would strongly encourage learning how others solve your problem so you can see the pros and cons of various approaches.

Upvotes: 1

Related Questions