Get and SUM the value of dynamic and multiple element using jQuery/Javascript

Viewed 222

I have a list of product in a cart. Now, i want to calculate all of the product price in cart. But i still didn't get how to get and calculate the value from dynamic element. Here's my code for the dynamic product in a cart:

<div class="modal fixed-right fade" id="modalShoppingCart" tabindex="-1" role="dialog" aria-hidden="true">
  <div class="modal-dialog modal-dialog-vertical" role="document">
    <div class="modal-content">
      <ul class="list-group list-group-lg list-group-flush">
        <?php 
          $no = 1;
          $query = mysqli_query($con, "SELECT c.id, c.quantity, c.product_id, p.name, p.thumbnail, p.sale_price FROM cart AS c LEFT JOIN product AS p ON c.product_id= p.id LEFT JOIN user AS u ON c.user_id=u.id WHERE c.product_id = p.id GROUP BY p.id")or die(mysqli_error($con));

          while($data = mysqli_fetch_array($query)){
            $product_id = $data['product_id'];
            $sql  = mysqli_query($con, "SELECT COUNT(product_id) FROM cart WHERE product_id='$product_id' GROUP BY product_id ");

            $row = mysqli_fetch_array($sql);
            $quantity = $row['COUNT(product_id)'];

            $sale_price = (int)$data['sale_price'] * $quantity;
        ?>
        <li class="list-group-item">
          <div class="row align-items-center">
            <div class="col-4">
              <a href="product.html">
                <img class="img-fluid" src="../assets/img/<?php echo $data['thumbnail']; ?>" alt="...">
              </a>
            </div>
            <div class="col-8">
              <p class="font-size-sm font-weight-bold mb-6">
                <a class="text-body" href="product.php"><?php echo $data['name']; ?></a> <br>
                <span class="text-muted"><?php echo 'Rp'.(str_replace(',', '.', number_format($sale_price))) ?? 'Rp0'; ?></span>
                <input type="hidden" name="sale_price" class="sale_price<?php echo $no++; ?>" value="<?php echo $sale_price; ?>">
              </p>
              <div class="d-flex align-items-center">
                <input type="number" class="d-inline-block form-control form-control-xxs w-auto m-width-65" name="quantity" value="<?php echo $quantity; ?>">
                <a class="font-size-xs text-gray-400 ml-auto" href="hapus-produk-cart.php?id=<?php echo $data['id']; ?>">
                  <i class="fe fe-x"></i> Hapus
                </a>
              </div>
            </div>
          </div>
        </li>
        <?php } ?>
      </ul>

      <div class="modal-footer line-height-fixed font-size-sm bg-light mt-auto">
        <strong>Total</strong> <strong class="ml-auto"></strong>
      </div>

      <div class="modal-body">
        <a class="btn btn-block btn-dark" href="checkout.php">Checkout Pesanan</a>
      </div>
    </div>
  </div>
</div>

since the products is dynamic, i didn't know how to get the value in <input type="hidden" name="sale_price" class="sale_price<?php echo $no++; ?>" value="<?php echo $sale_price; ?>">. and how to calculate it using jQuery or javascript. Would u help me how to do that? I really need your help guys. Thank you in advance.

1 Answers

Where to start? I am not going to deal with the need to use prepared statements but I suggest you do some reading about SQL injection. So, let's try starting with your first query -

SELECT c.id, c.quantity, c.product_id, p.name, p.thumbnail, p.sale_price
FROM cart AS c
LEFT JOIN product AS p ON c.product_id= p.id
LEFT JOIN user AS u ON c.user_id=u.id
WHERE c.product_id = p.id
GROUP BY p.id

Why the LEFT joins? These should be INNER joins, surely? Why join to the user table at all if it is not being returned in the SELECT list? This current query is going to return all carts with their respective products and users. Probably not what you intended. Maybe you want the cart and associated products for the current user? I will continue on this basis.

SELECT c.id, c.quantity, c.product_id, p.name, p.thumbnail, p.sale_price, c.quantity * p.sale_price AS line_item_total
FROM cart AS c
JOIN product AS p ON c.product_id= p.id
WHERE c.user_id = ? /* where ? is the current user's id */

I have taken the liberty of modifying the query to get the db to return the line_item_total for us.

And now onto the second query, run for each record returned by first query -

SELECT COUNT(product_id)
FROM cart
WHERE product_id='$product_id'
GROUP BY product_id

I am not quite sure what this is supposed to be doing but it won't work as you expect. It will return the COUNT of users who have this product_id in their cart. The only relevant quantity should be the one already returned by your cart query.

This is definitely not beautiful but it should be enough to get you started -

<?php

$current_user_id = 1; // coming from session or ...

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = mysqli_connect('host', 'user', 'pass', 'db');

/* This is a very crude piece of code to handle the AJAX request. The user_id
 * predicate in the UPDATE query is really important to stop people modifying
 * the request to update someone else's cart */
if (isset($_POST['action']) && $_POST['action'] == 'updateCartItem') {
    // Notice the three placeholders used for the prepared statement
    $stmt = mysqli_prepare($link, 'UPDATE cart SET quantity = ? WHERE id = ? AND user_id = ?');
    mysqli_stmt_bind_param($stmt, 'iii', $_POST['quantity'], $_POST['id'], $current_user_id);
    mysqli_stmt_execute($stmt);
    echo (mysqli_affected_rows($link) == 1) ? 'success' : 'failure';
    die;
}

/* Query to retrieve cart and associated products for given user_id  */
$sql = 'SELECT c.id, c.quantity, c.product_id, p.name, p.thumbnail, p.sale_price, c.quantity * p.sale_price AS line_item_total
FROM cart AS c
JOIN product AS p ON c.product_id = p.id
WHERE c.user_id = ?';

$stmt = mysqli_prepare($link, $sql);
mysqli_stmt_bind_param($stmt, 'i', $current_user_id);
mysqli_stmt_execute($stmt);

$result = mysqli_stmt_get_result($stmt);
$cart_items = mysqli_fetch_all($result, MYSQLI_ASSOC);

?>

<div class="modal fixed-right fade" id="modalShoppingCart" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="modal-dialog modal-dialog-vertical" role="document">
        <div class="modal-content">
            <ul class="list-group list-group-lg list-group-flush">
                <?php $cart_total = 0; foreach ($cart_items as $cart_item): ?>

                    <li class="list-group-item cart-item">
                        <span class="cart-item-id"><input type="hidden" name="id" value="<?php echo $cart_item['id']; ?>"></span>
                        <span class="cart-item-img"><img src="../assets/img/<?php echo $cart_item['thumbnail']; ?>"></span>
                        <span class="cart-item-name"><?php echo $cart_item['name']; ?></span>
                        <span class="cart-item-price"><?php echo $cart_item['sale_price']; ?></span>
                        <span class="cart-item-quantity"><input type="number"  name="quantity[<?php echo $cart_item['product_id']; ?>]" value="<?php echo $cart_item['quantity']; ?>"></span>
                        <span class="cart-item-total"><?php echo $cart_item['line_item_total']; ?></span>
                    </li>

                <?php $cart_total += $cart_item['line_item_total']; endforeach; ?>
            </ul>

            <div class="modal-footer line-height-fixed font-size-sm bg-light mt-auto">
                <strong>Total</strong> <span id="cart-total-price" class="ml-auto"><?php echo $cart_total; ?></span>
            </div>

            <div class="modal-body">
                <a class="btn btn-block btn-dark" href="checkout.php">Checkout Pesanan</a>
            </div>
        </div>
    </div>
</div>

<script>
$(document).ready(function() {
    $('.cart-item-quantity input').change(function() {
        updateQuantity(this);
    });

    /* Update quantity */
    function updateQuantity(quantityInput) {
        /* Calculate line price */
        var productRow = $(quantityInput).closest('li.cart-item');
        var cartItemId = productRow.find('.cart-item-id input').val();
        var price = parseFloat(productRow.find('span.cart-item-price').text());
        var quantity = $(quantityInput).val();
        var linePrice = price * quantity;
        productRow.find('span.cart-item-total').text(linePrice.toFixed(2));

        /* Send AJAX request to update line item */
        $.post( '', { action: 'updateCartItem', id: cartItemId, quantity: quantity })
            .done(function( data ) {
                /* Their should be proper handling of the response here */
                console.log( "Result: " + data );
            });
        updateCart();
    }

    function updateCart() {
        var cartTotal = 0;
        $('span.cart-item-total').each(function () {
            cartTotal += parseFloat($(this).text());
        });
        $('span#cart-total-price').text(cartTotal.toFixed(2));
    }
});
</script>
Related