Search code examples
javascriptreactjssum

Sum numbers inside a table


Can anyone help me how to sum numbers inside a table in React.js?

My scenario is that I have Product table, inside product it has header column (no, product name, quantity, actual price, total price).

Below for screenshot:

enter image description here

Below for my object:

enter image description here

Below for my code (simplified):

 <h5 className="uppercase fw-bold mt-3">Produk</h5>
      <table className="table table-borderless">
        <thead>
          <tr>
            <th className="border">No</th>
            <th className="border">Produk</th>
            <th className="border">Quantity</th>
            <th className="border">Harga Satuan</th>
            <th className="border">Jumlah (Rp)</th>
          </tr>
        </thead>
        <tbody>
          {listProduct?.map((el, i) => {
            return (
              <tr key={i}>
                <td className="border">{i + 1}</td>
                <td className="border">{el.Product.name}</td>
                <td className="border">{el.quantity}</td>
                <td className="border">{el.price}</td>
                <td className="border">{+el.quantity * el.price}</td>
              </tr>
            );
          })}

          {/* <tr>
            <td colSpan={3}></td>
            <td className="border">
              Subtotal ({listProduct?.length} orderDetail)
            </td>
            {listProduct?.map((el, i) => {
              let sum = 0;
              sum += Number(el.price);
              return (
                <td key={i} className="border">
                  {sum}
                </td>
              );
            })}
          </tr> */}

          <tr>
            <td colSpan={3}></td>
            <td className="border">
              Subtotal ({listProduct?.length} orderDetail)
            </td>
            <td className="border">{"-"}</td>
          </tr>
          <tr>
            <td colSpan={3}></td>
            <td className="border">Shipping Fee</td>
            <td className="border">{orderDetail?.deliveryFee}</td>
          </tr>
          <tr>
            <td colSpan={3}></td>
            <td className="border">Discount</td>
            <td className="border">{"-"}</td>
          </tr>
          <tr>
            <td colSpan={3}></td>
            <td
              className="border uppercase"
              style={{
                backgroundColor: "#8FE5E1",
              }}
            >
              Total
            </td>
            <td
              className="border"
              style={{
                backgroundColor: "#8FE5E1",
              }}
            >
              {"-"}
            </td>
          </tr>
        </tbody>
      </table>

What I'm expecting is that in Subtotal -> 20000+5000 = 25000 and in Total -> 25000+9000 = 34000, and if there is discount then Total - Discount.


Solution

  • You should use reduce rather than map to cycle through the listProduct items and sum all their total values.

    const subTotal = listProduct.reduce((acc, product) => {
        return acc + product.price * product.quantity;
    }, 0);
    

    The subtotal row would then look like the following.

    <tr>
        <td colSpan={3}></td>
        <td className="border">
            Subtotal ({listProduct?.length} orderDetail)
        </td>
        <td key={i} className="border">
            {subTotal}
        </td>
    </tr>
    

    You can also use the subTotal value to then calculate the final total amount.

    <tr>
        <td colSpan={3}></td>
        <td className="border uppercase" style={{ backgroundColor: "#8FE5E1" }}>
            Total
        </td>
        <td className="border" style={{ backgroundColor: "#8FE5E1" }}>
            {subTotal + orderDetail?.deliveryFee}
        </td>
    </tr>