How to update the total price of an item according to its quantity?

Viewed 3345

I am developing a shopping cart website. On my cart page, the total price of an item should be updated as per the quantity of that item. https://github.com/darryldecode/laravelshoppingcart I installed this shopping cart package.

How can I update the total price of an item according to its quantity?

CartController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Product;
use App\Category;
use Darryldecode\Cart\Cart;

class CartController extends Controller
{
   
    public function index()
    {
       // $cartItems = \Cart::session(auth()->id())->getContent();
        
         return view ('cart');
     }
   

    public function show($id)
    {
        $product = Product::find($id);
       
        return view('cart')->with(compact('product'));
   }


    public function update($rowId)
    {

        \Cart::session(auth()->id())->update($rowId, [
            'quantity' => [
            'relative' => true, 
            'value'=> request('quantity')
            ]
            ]);
        return back();
        
    }


    public function destroy($itemId)
    {

        \Cart::session(auth()->id())->remove($itemId);
        
        return back();
        
    }

    public function addtocart(Product $product)
    {
    
        \Cart::session(auth()->id())->add(array(
            'id' => $product->id,
            'name' => $product->prod_name,
            'price' => $product->prod_price,
            'quantity' => 1,
            'attributes' => array(),
            'associatedModel' => $product
                 ));
                
                 return redirect()->back();
    }

}

cart.blade.php

                        @foreach(\Cart::session(auth()->id())->getContent() as $items)
                            <tr>
                            <form class="mb-4" action="{{route('cart.update',$items->id)}}">    
                            
                                <td data-title="Product">
                                    <a href="#" class="text-gray-90">{{ $items ['name'] }}</a>
                                </td>
                            
                                <td data-title="Price">
                                    <span class="">LKR {{ $items ['price'] }}.00</span>
                                </td>
                            
                                <td data-title="Quantity">
                                    <span class="sr-only">Quantity</span>
                                    <!-- <form class="mb-4" action="{{route('cart.update',$items->id)}}"> -->
                                        <br>
                                        <div class="border rounded-pill py-1 width-122 w-xl-80 px-3 border-color-1">
                                             <div class="js-quantity row align-items-center">
                                                <div class="col">
                                                    <input class="js-result form-control h-auto border-0 rounded p-0 shadow-none" name="quantity" type="text" value="{{$items->quantity}}">
                                                </div>
                                                    <div class="col-auto pr-1">
                                                    <a class="js-minus btn btn-icon btn-xs btn-outline-secondary rounded-circle border-0" href="javascript:;">
                                                        <small class="fas fa-minus btn-icon__inner"></small>
                                                    </a>
                                                    <a class="js-plus btn btn-icon btn-xs btn-outline-secondary rounded-circle border-0" href="javascript:;">
                                                        <small class="fas fa-plus btn-icon__inner"></small>
                                                    </a>
                                                </div> 
                                            </div>
                                        </div>
                                    <!-- </form> -->
                                </td>

                                 
                                                
                                        <!-- Quantity -->
                                        <!-- <div class="border rounded-pill py-1 width-122 w-xl-80 px-3 border-color-1">
                                            <div class="js-quantity row align-items-center">
                                                <div class="col">
                                                    <input class="js-result form-control h-auto border-0 rounded p-0 shadow-none" name="quantity" type="number" value="{{$items->quantity}}">
                                                    <button type="submit" class="btn btn-soft-secondary mb-3 mb-md-0 font-weight-normal px-5 px-md-4 px-lg-5 w-100 w-md-auto">Update cart</button>
                                                </div>
                                                <div class="col-auto pr-1">
                                                    <a class="js-minus btn btn-icon btn-xs btn-outline-secondary rounded-circle border-0" href="javascript:;">
                                                        <small class="fas fa-minus btn-icon__inner"></small>
                                                    </a>
                                                    <a class="js-plus btn btn-icon btn-xs btn-outline-secondary rounded-circle border-0" href="javascript:;">
                                                        <small class="fas fa-plus btn-icon__inner"></small>
                                                    </a>
                                                </div>
                                            </div>
                                        </div>  -->
                                   
                                    <!-- End Quantity -->
                                </td>
                                
                                <td data-title="Total">
                                    <span class="">
                                    LKR  {{Cart::session(auth()->id())->get($items->id)->getPriceSum()}}.00
                                    </span>
                                </td>
                                
                                    <td>
                                         <button type="submit" class="btn btn-soft-secondary mb-3 mb-md-0 font-weight-normal px-5 px-md-4 px-lg-5 w-100 w-md-auto"><i class="fas fa-pen-nib text-primary fa-2x"></i></button>
                                         <a href="{{ route('cart.destroy', $items->id)}}" class="btn btn-soft-secondary mb-3 mb-md-0 font-weight-normal px-5 px-md-4 px-lg-5 w-100 w-md-auto"><i class="fas fa-trash-alt text-danger fa-2x"></i></a>
                                    </td>
                               
                                <!-- <td>
                                    <div class="d-md-flex">
                                        <form class="mb-4" action="{{route('cart.update',$items->id)}}">
                                            <button type="submit" class="btn btn-soft-secondary mb-3 mb-md-0 font-weight-normal px-5 px-md-4 px-lg-5 w-100 w-md-auto">Update cart</button>
                                            <a href="../shop/checkout.html" class="btn btn-primary-dark-w ml-md-2 px-5 px-md-4 px-lg-5 w-100 w-md-auto d-none d-md-inline-block">Proceed to checkout</a>
                                        </form>
                                    </div>
                                </td> -->
                                </form>
                             </tr>
                         @endforeach

web.php

Route::get('/cart', 'CartController@index')->name('cart.index')->middleware('auth');;
Route::get('/cart/{cartItems}', 'CartController@add')->name('cart.add')->middleware('auth');
Route::get('/cart/destroy/{itemId}', 'CartController@destroy')->name('cart.destroy')->middleware('auth');
Route::get('/cart/update/{itemId}', 'CartController@update')->name('cart.update')->middleware('auth');
Route::get('/add-to-cart/{product}','CartController@addtocart')->name('addToCart');
3 Answers

Not much idea about Laravel, but this solution in javascript will give you an idea how you can proceed...

function getPriceSum() {
    YOUR_ARRAY.reduce((sum, item) => { return sum + (item.price * item.quantity), 0 })
}

You have to change some codes:

1- Add a new route and method to retrieve all card items

Route::get('/cart/items', 'CartController@allItems')->name('cart.all-items')->middleware('auth');

method:

public function allItems()
    {
      return \Cart::session(auth()->id())->getContent();
    }

2- next, you need to move and alter this block of code into Javascript and retrieve data from the above route by Ajax.

 @foreach(\Cart::session(auth()->id())->getContent() as $items)
                                <tr>
                                    <td class="text-center">
                                    <a href="{{ route('cart.destroy', $items->id)}}">x</a>
                                    </td>
                                    <td data-title="Product">
                                        <a href="#" class="text-gray-90">{{ $items ['name'] }}</a
                                    </td>
                                    <td data-title="Price">
                                        <span class="">LKR {{ $items ['price'] }}.00</span>
                                    </td>
                                    <td data-title="Quantity">
                                        <span class="sr-only">Quantity</span>
                                        <!-- Quantity -->
                                        <div class="border rounded-pill py-1 width-122 w-xl-80 px-3 border-color-1">
                                            <div class="js-quantity row align-items-center">
                                                <div class="col">
                                                    <input class="js-result form-control h-auto border-0 rounded p-0 shadow-none" name="quantity" type="text" value="{{$items->quantity}}">
                                                </div>
                                                <div class="col-auto pr-1">
                                                    <a class="js-minus btn btn-icon btn-xs btn-outline-secondary rounded-circle border-0" href="javascript:;">
                                                        <small class="fas fa-minus btn-icon__inner"></small>
                                                    </a>
                                                    <a class="js-plus btn btn-icon btn-xs btn-outline-secondary rounded-circle border-0" href="javascript:;">
                                                        <small class="fas fa-plus btn-icon__inner"></small>
                                                    </a>
                                                </div>
                                            </div>
                                        </div> 
                                        <!-- End Quantity -->
                                    </td>
                                    <td data-title="Total">
                                        <span class="">
                                            {{Cart::session(auth()->id())->get($items->id)->getPriceSum()}}
                                        </span>
                                    </td>
                                @endforeach

whenever a new product adds into your card or by an interval timer you can call the method of Javascript to get the latest products without refreshing the page.

I'm starting to forget Laravel and I do not have one near me, so this code below is just theoretical.

First of all, you need a backend to be able to update quantity on-the-fly. This is just your "normal" update, but it will return JSON with new total.

public function updateQuantity($rowId)
{
    \Cart::session(auth()->id())->update($rowId, [
        'quantity' => [
        'relative' => true, 
        'value'=> request('quantity')
        ]
        ]);
    $newTotal = Cart::session(auth()->id())->get($items->id)->getPriceSum();
    return [ 'total' => $newTotal ];
}

New route for that:

Route::get('/cart/updateQuantity/{itemId}', 'CartController@updateQuantity')->name('cart.updateQuantity')->middleware('auth');

Now we need to prepare frontend to be able to update quantity and total dynamically.

<!-- we will change this line: -->
<input class="js-result form-control h-auto border-0 rounded p-0 shadow-none" name="quantity" type="number" value="{{$items->quantity}}">
<!-- to this line: -->
<input class="js-result form-control h-auto border-0 rounded p-0 shadow-none" name="quantity" id="quantity{{$items->id}}" data-id="{{$items->id}}" type="number" value="{{$items->quantity}}" onchange="updateQuantity({{$items->id}})">
<!-- yes, we just added ID to be able to use this later, and added callback -->
<!-- after previous line with "input" we can add an element to keep the route,
  this is because routes are calculated by Laravel dynamically -->
<span id="updateQuantityRoute{{$items->id}}" style="display:none">{{route('cart.updateQuantity',$items->id)}}</span>

<!-- also we need to prepare "total", so this line: -->
<span class="">{{Cart::session(auth()->id())->get($items->id)->getPriceSum()}}</span>
<!-- change to this line: -->
<span class="" id="total{{$items->id}}">{{Cart::session(auth()->id())->get($items->id)->getPriceSum()}}</span>

So the magic is in updateQuantity function:

function updateQuantity(itemId) {
  // here I will use jQuery just to show the idea
  const route = $('#updateQuantityRoute' + itemId);
  const newQuantity = $('#quantity' + itemId).val();
  $.post(route, {'quantity': newQuantity}).done(function( data ) {
    // here we have response
    if (typeof data === 'string') data = JSON.parse(data);
    const updatedTotal = data.total;
    $('#total' + itemId).innerText = updatedTotal; // update in DOM
  });
}
Related