My Course — Membangun Website Food Store Dengan Laravel Filament, Livewire dan Payment Gateway

Membuat Component Button Add to Cart Full


Sekarang kita akan membuat komponen baru untuk tombol Add to Cart. Mungkin teman-teman bertanya, mengapa kita membuat komponen baru padahal sebelumnya sudah pernah membuatnya? Alasannya adalah karena gaya (style) tombol yang akan kita gunakan kali ini akan berbeda.

Langkah 1 - Membuat Component Button Add to Cart Full

Silahkan teman-teman jalankan perintah berikut ini di dalam terminal/CMD dan pastikan berada di dalam project Laravel-nya.

go
php artisan make:livewire Web/Cart/BtnAddToCartFull

Jika perintah di atas berhasil dijalankan, maka kita akan mendapatkan 2 file baru, yaitu:

  1. Class Component: app/Livewire/Web/Cart/BtnAddToCartFull.php
  2. View Component: resources/views/livewire/web/cart/btn-add-to-cart-full.blade.php

Langkah 2 - Menambahkan Fungsi Add to Cart

Sekarang kita akan menambahkan sebuah method yang berfungsi untuk melakukan proses add to cart atau memasukkan data product ke keranjang belanja.

Silahkan buka file app/Livewire/Web/Cart/BtnAddToCartFull.php, kemudian ubah semua kode-nya menjadi seperti berikut ini.

php
<?php namespace App\Livewire\Web\Cart; use App\Models\Cart; use Livewire\Component; class BtnAddToCartFull extends Component { /** * product_id * * @var mixed */ public $product_id; /** * addToCart * * @param mixed $product_id * @return void */ public function addToCart() { //check user is logged in if(!auth()->guard('customer')->check()) { session()->flash('warning', 'Silahkan login terlebih dahulu'); return $this->redirect('/login', navigate: true); } //check cart $item = Cart::where('product_id', $this->product_id) ->where('customer_id', auth()->guard('customer')->user()->id) ->first(); //if cart already exist if ($item) { //update cart qty $item->increment('qty'); } else { //store cart $item = Cart::create([ 'customer_id' => auth()->guard('customer')->user()->id, 'product_id' => $this->product_id, 'qty' => 1 ]); } // session flash session()->flash('success', 'Produk ditambahkan ke keranjang'); //redirect to cart return $this->redirect('/cart', navigate: true); } /** * render * * @return void */ public function render() { return view('livewire.web.cart.btn-add-to-cart-full'); } }

Dari perubahan kode di atas, pertama kita import Model Cart.

perl
use App\Models\Cart;

Kemudian di dalam class kita membuat public properti.

php
public $product_id;

Selanjutnya, kita membuat method yang bernama addToCart, method ini akan dijalankan ketika button add to cart diklik.

csharp
public function addToCart() { //... }

Di dalamnya, pertama kita akan cek apakah customer sudah login atau belum, jika belum maka akan kita redirect ke halaman login terlebih dahulu.

scss
//check user is logged in if(!auth()->guard('customer')->check()) { session()->flash('warning', 'Silahkan login terlebih dahulu'); return $this->redirect('/login', navigate: true); }

Jika customer sudah login, maka akan menjalankan kode dibawahnya, yaitu mengecek data cart di dalam table database berdasarkan product_id yang dikirimkan dan customer_id.

php
//check cart $item = Cart::where('product_id', $this->product_id) ->where('customer_id', auth()->guard('customer')->user()->id) ->first();

Jika data cart ada, artinya kita cukup mengupdate qty di dalam cart. Disini kita menggunakan fitur yang bernama increment dari Laravel.

php
//update cart qty $item->increment('qty');

Tapi jika data cart tidak ada, maka kita akan insert ke dalam database menggunakan Model.

php
//store cart $item = Cart::create([ 'customer_id' => auth()->guard('customer')->user()->id, 'product_id' => $this->product_id, 'qty' => 1 ]);

Setelah itu, kita buat session flash dengan status success dan kita redirect ke halaman /carts.

kotlin
// session flash session()->flash('success', 'Produk ditambahkan ke keranjang'); //redirect to cart return $this->redirect('/cart', navigate: true);

Langkah 3 - Menambahkan Button Add to Cart

Sekarang kita akan membuat sebuah button di dalam view component, dimana nantinya component ini akan kita panggil di dalam detail product

Silahkan teman-teman buka file resources/views/livewire/web/cart/btn-add-to-cart-full.blade.php, kemudian ubah kode-nya menjadi seperti berikut ini.

xml
<div class="container fixed-total"> <div class="row justify-content-center"> <div class="col-12 col-md-6 mb-5"> <div class="mt-5"> <div class=""> <button wire:click="addToCart({{ $product_id }})" class="btn btn-orange-2 rounded w-100"> <svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" fill="currentColor" class="bi bi-cart3 mb-2 mt-1" viewBox="0 0 16 16"> <path d="M0 1.5A.5.5 0 0 1 .5 1H2a.5.5 0 0 1 .485.379L2.89 3H14.5a.5.5 0 0 1 .49.598l-1 5a.5.5 0 0 1-.465.401l-9.397.472L4.415 11H13a.5.5 0 0 1 0 1H4a.5.5 0 0 1-.491-.408L2.01 3.607 1.61 2H.5a.5.5 0 0 1-.5-.5M3.102 4l.84 4.479 9.144-.459L13.89 4zM5 12a2 2 0 1 0 0 4 2 2 0 0 0 0-4m7 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4m-7 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2m7 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2" /> </svg> <span class="ms-1">Add to Cart</span> </button> </div> </div> </div> </div> </div>

Di atas kita menambahkan event wire:click yang mengarah ke method addToCart yang sudah kita buat sebelumnya pada class component dan di dalamnya kita berikan parameter $product_id, dimana nantinya value-nya akan berisi data props yang dikirimkan oleh parent component.

Langkah 4 - Memanggil Component BtnAddToCartFull di Product Show

Silahkan teman-teman buka file resources/views/livewire/web/products/show.blade.php, kemudian ubah kode-nya menjadi seperti berikut ini.

typescript
@section('title') {{ $product->title }} - Eat Your Favorite Foods @stop @section('keywords') Food Store, Eat Your Favorite Foods @stop @section('description') {{ $product->description }} @stop @section('image') {{ asset('/storage/' . $product->image) }} @stop <div class="container" style="margin-bottom: 200px;"> <div class="row justify-content-center mt-0"> <div class="col-md-6"> <div class="bg-white rounded-bottom-custom shadow-sm p-3 mb-5" :style="{ backgroundImage: `url({{ asset('storage/' . $product->image) }})`,height: '300px',backgroundSize: 'cover',backgroundPosition: 'center'}"> <div class="d-flex justify-content-start"> <div> <x-buttons.back /> </div> </div> </div> <div class="card border-0 shadow-sm rounded" style="margin-top: -85px;"> <div class="card-body mt-4"> <h5>{{ $product->title }}</h5> <div class="d-flex justify-content-between mt-3"> <div> <p class="fw-bold text-success">Rp. {{ number_format($product->price) }}</p> </div> <div> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-star-fill text-orange mb-1 me-2" viewBox="0 0 16 16"> <path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z" /> </svg> <span class="fw-bold">{{ number_format($product->ratings_avg_rating, 1) }} ({{ $product->ratings_count }} Reviews )</span> </div> </div> <h5 class="mt-3">Description</h5> <p> {!! $product->description !!} </p> </div> </div> <h6 class="mt-4"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat-left-text me-1" viewBox="0 0 16 16"> <path d="M14 1a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H4.414A2 2 0 0 0 3 11.586l-2 2V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12.793a.5.5 0 0 0 .854.353l2.853-2.853A1 1 0 0 1 4.414 12H14a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z" /> <path d="M3 3.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5M3 6a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9A.5.5 0 0 1 3 6m0 2.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5" /> </svg> Rating & Review </h6> <div class="row mt-3"> @foreach($product->ratings()->latest()->get() as $rating) <div class="col-6 mb-4"> <div class="card border-0 shadow-sm rounded h-100"> <div class="card-body"> <!-- Display Stars --> <div class="d-flex justify-content-center mt-3"> @for ($i = 1; $i <= 5; $i++) <label for="star{{ $i }}-{{ $rating->id }}"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="cursor-pointer @if($rating->rating >= $i) text-warning @else text-secondary @endif" viewBox="0 0 20 20"> <path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" /> </svg> </label> @endfor </div> <!-- Review text --> <blockquote class="bsb-blockquote-icon mb-3 mt-4"> <p>{{ $rating->review }}</p> </blockquote> <!-- Customer Info --> <figure class="d-flex align-items-center m-0 p-0"> <img class="img-fluid rounded-circle m-0 border border-3" width="50" loading="lazy" src="{{ asset('/storage/avatars/' . $rating->customer->image) }}" alt="{{ $rating->customer->name }}"> <figcaption class="ms-2 mt-1"> <h6 class="mb-1">{{ $rating->customer->name }}</h6> </figcaption> </figure> </div> </div> </div> @endforeach </div> <!-- button add to cart --> <livewire:web.cart.btn-add-to-cart-full :product_id="$product->id" /> </div> </div> </div>

Di atas, kita memanggil component BtnAddToCartFull yang sudah kita buat sebelumnya.

sql
<livewire:web.cart.btn-add-to-cart-full :product_id="$product->id" />

Dan di dalamnya kita juga mengirimkan props :product_id dan berisi id dari data product.

Langkah 5 - Uji Coba Menampilkan Button Add To Cart

Sekarang jika teman-teman buka salah satu data product, maka sekarang di dalamnya akan terdapat button untuk proses add to cart.