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

Membuat Component My Orders


Setelah berhasil membuat component untuk menu customer, maka kita akan lanjutkan belajar membuat component livewire untuk menampilkan data my orders / transaksi berdasarkan customer yang sedang login.

Langkah 1 - Membuat Component My Orders

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

go
php artisan make:livewire Account/MyOrders/Index

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

  1. Class Component: app/Livewire/Account/MyOrders/Index.php
  2. View Component: resources/views/livewire/account/my-orders/index.blade.php

Langkah 2 - Membuat Route My Orders Index

Sekarang kita akan lanjutkan membuat route yang nanti digunakan untuk menampilkan halaman my orders.

Silahkan buka file routes/web.php, kemudian ubah semua kode-nya menjadi seperti berikut ini.

php
<?php namespace App\Livewire; use Illuminate\Support\Facades\Route; //route register Route::get('/register', Auth\Register::class)->name('register'); //route login Route::get('/login', Auth\Login::class)->name('login'); //route group account Route::middleware('auth:customer')->group(function () { Route::group(['prefix' => 'account'], function () { //route my order Route::get('/my-orders', Account\MyOrders\Index::class)->name('account.my-orders.index'); }); });

Dari perubahan kode di atas, kita membuat 2 route group, yaitu:

  1. middleware auth:customer - artinya semua route yang dibuat di dalamnya hanya bisa diakses jika sudah melakukan proses login.

    php
    Route::middleware('auth:customer')->group(function () { //... }
  2. prefix account - artinya semua route yang dibuat di dalamnya akan ditambahkan awalan /account pada URL-nya.

    php
    Route::group(['prefix' => 'account'], function () { //... }

Di dalam kedua route group di atas kita membuat route baru untuk halaman my-orders.

css
Route::get('/my-orders', Account\MyOrders\Index::class)->name('account.my-orders.index');

Langkah 3 - Get Data Transaksi di Class Component

Selanjutnya adalah belajar bagaimana mengambil data transaksi berdasarkan customer yang login di dalam class component.

Silahkan teman-teman buka file app/Livewire/Account/MyOrders/Index.php, kemudian ubah semua kode-nya menjadi seperti berikut ini.

php
<?php namespace App\Livewire\Account\MyOrders; use Livewire\Component; use App\Models\Transaction; class Index extends Component { public function render() { //get transactions $transactions = Transaction::query() ->where('customer_id', auth()->guard('customer')->user()->id) ->latest() ->simplePaginate(3); return view('livewire.account.my-orders.index', compact('transactions')); } }

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

perl
use App\Models\Transaction;

Kemudian di dalam method render kita membuat variable $transactions dan berisi get data ke Model Transaction berdasarkan customer_id yang sedang login.

php
//get transactions $transactions = Transaction::query() ->where('customer_id', auth()->guard('customer')->user()->id) ->latest() ->simplePaginate(3);

Kemudian kita kirimkan data di atas ke dalam view component menggunakan compact.

kotlin
return view('livewire.account.my-orders.index', compact('transactions'));

Langkah 4 - Menampilkan Data My Orders / Transactions

Silahkan teman-teman buka file resources/views/livewire/account/my-orders/index.blade.php, kemudian ubah semua kode-nya menjadi seperti berikut ini.

javascript
<div class="container"> <div class="row justify-content-center mt-0" style="margin-bottom: 150px;"> <div class="col-md-6"> <x-menus.customer /> <div class="card border-0 shadow-sm rounded"> <div class="card-body p-4"> <h6> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="bi bi-bag mb-1" viewBox="0 0 16 16"> <path d="M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1m3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4zM2 5h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z" /> </svg> My Orders </h6> <hr /> @forelse ($transactions as $transaction) <div class="card rounded border mb-3"> <div class="row g-0"> <div class="col-12 col-md-12"> <a href="{{ route('account.my-orders.show', $transaction->snap_token) }}" wire:navigate class="text-decoration-none text-dark"> <div class="card-body"> <div class="d-flex justify-content-between"> <div class="mt-2"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-basket3 mb-1 me-2" viewBox="0 0 16 16"> <path d="M5.757 1.071a.5.5 0 0 1 .172.686L3.383 6h9.234L10.07 1.757a.5.5 0 1 1 .858-.514L13.783 6H15.5a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5H.5a.5.5 0 0 1-.5-.5v-1A.5.5 0 0 1 .5 6h1.717L5.07 1.243a.5.5 0 0 1 .686-.172zM3.394 15l-1.48-6h-.97l1.525 6.426a.75.75 0 0 0 .729.574h9.606a.75.75 0 0 0 .73-.574L15.056 9h-.972l-1.479 6z" /> </svg> <span class="fw-bold">Order ID #{{ $transaction->invoice }}</span> </div> <div> @if($transaction->status == 'pending') <button class="btn btn-warning btn-sm rounded shadow-sm border-0">PENDING</button> @elseif($transaction->status == 'success') <button class="btn btn-success btn-sm rounded shadow-sm border-0">SUCCESS</button> @elseif($transaction->status == 'expired') <button class="btn btn-warning btn-sm rounded shadow-sm border-0" disabled>EXPIRED</button> @elseif($transaction->status == 'failed') <button class="btn btn-danger btn-sm rounded shadow-sm border-0">FAILED</button> @endif </div> </div> <hr> <div class="d-flex justify-content-between"> <div> <span class="fw-bold">Grand Total:</span> </div> <div> <span class="fw-bold">Rp. {{ number_format($transaction->total) }}</span> </div> </div> </div> </a> </div> </div> </div> @empty <div class="card rounded border mb-3"> <div class="card-body"> <div class="d-flex justify-content-center"> <div class="mt-2"> <span class="fw-bold">You don't have any orders.</span> </div> </div> </div> </div> @endforelse <!-- Navigasi Pagination --> {{ $transactions->links('vendor.pagination.simple-default') }} </div> </div> </div> </div> </div>

Dari penambahan kode di atas, pertama kita panggil component menu customer.

xml
<x-menus.customer />

Kemudian untuk menampilkan data, kita menggunakan directive @forelse.

less
@forelse ($transactions as $transaction) //data orders @empty //tidak ada data orders @endforelse

Dan untuk menampilkan pagination, kita bisa menggunakan sintaks seperti berikut ini.

php
{{ $transactions->links('vendor.pagination.simple-default') }}

Jika teman-teman perhatikan, di atas pada view pagination kita arahkan ke vendor/pagination/simple-default. Sedangkan view tersebut untuk saat ini belum ada, maka kita akan publish dulu file tersebut pada langkah berikutnya.

Langkah 5 - Publish View Pagination

Di atas, karena kita akan melakukan custom view pagination, maka kita akan publish dulu view dari pagination Laravel.

Silahkan teman-teman jalankan perintah berikut ini.

lua
php artisan vendor:publish --tag=laravel-pagination

Jika perintah di atas berhasil dijalankan, maka kita akan mendapatkan beberapa view untuk pagination dari Laravel, yang berada di dalam folder berikut ini.

bash
resources/views/vendor/pagination/*

Langkah 6 - Custom Pagination Laravel

Sekarang kita akan lakukan custom pagination bawaan dari Laravel agar sesuai dengan yang kita inginkan dan namanya adalah simple-default.

Silahkan teman-teman buka file resources/views/vendor/pagination/simple-default.blade.php, kemudian ubah semua kode-nya menjadi seperti berikut ini.

scss
@if ($paginator->hasPages()) <div class="d-flex justify-content-between mt-2"> {{-- Tombol Previous --}} @if ($paginator->onFirstPage()) <button class="btn btn-orange-2 rounded shadow-sm border-0" disabled> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left mb-1" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8" /> </svg> Previous </button> @else <a href="{{ $paginator->previousPageUrl() }}" class="btn btn-orange-2 rounded shadow-sm border-0" wire:navigate> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left mb-1" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8" /> </svg> Previous </a> @endif {{-- Tombol Next --}} @if ($paginator->hasMorePages()) <a href="{{ $paginator->nextPageUrl() }}" class="btn btn-orange-2 rounded shadow-sm border-0" wire:navigate> Next <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right mb-1" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8" /> </svg> </a> @else <button class="btn btn-orange-2 rounded shadow-sm border-0" disabled> Next <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right mb-1" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8" /> </svg> </button> @endif </div> @endif

Langkah 7 - Uji Coba Menampilkan Halaman My Orders

Silahkan teman-teman login dan jika berhasil maka akan diarahkan pada halaman My Orders, kurang lebih seperti berikut ini.