Setelah sebelumnya, kita membuat halaman order untuk administrator, kali ini kita akan membuat halaman order untuk user, jadi nanti user bisa melihat detail order dan status order setelah dia login dan melakukan order.
Langkah 1. Edit file FrontendController
Sebelumnya kita sudah buat Controller dengan nama FrontendController, kita bisa menggunakan controller tersebut dengan menambah function khusus untuk order. Edit file FrontendController dan tambahkan function Order dan OrderDetail berikut:
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use App\Models\Category;
use Illuminate\Http\Request;
use Inertia\Inertia;
use App\Models\Order;
class FrontendController extends Controller
{
public function index(Request $request)
{
// Ambil parameter search & filter kategori
$search = $request->input('search');
$categoryId = $request->input('category_id');
$query = Product::with('images', 'category');
if ($search) {
$query->where('name', 'like', '%' . $search . '%');
}
if ($categoryId) {
$query->where('category_id', $categoryId);
}
$products = $query->latest()->paginate(12)->withQueryString();
$categories = Category::all(['id','name']);
return Inertia::render('Frontend/Homepage', [
'products' => $products,
'categories' => $categories,
'filters' => [
'search' => $search,
'category_id' => $categoryId,
]
]);
}
public function show($slug)
{
$product = Product::with('images', 'category')->where('slug', $slug)->firstOrFail();
return Inertia::render('Frontend/ProductDetail', [
'product' => $product
]);
}
public function cart()
{
return Inertia::render('Frontend/Cart');
}
public function order(){
$orders = Order::where('user_id', auth()->id())
->with('items.product')
->latest()
->paginate(10);
return Inertia::render('Frontend/Order', [
'orders' => $orders,
]);
}
public function OrderDetail(Order $order){
// Pastikan user hanya bisa melihat pesanan miliknya
if ($order->user_id !== auth()->id()) {
abort(403, 'Unauthorized action.');
}
$order->load('items.product', 'user');
return Inertia::render('Frontend/OrderDetail', [
'order' => $order,
]);
}
}
Langkah 2. Menambahkan Frontend Vue
Buat file resources/js/Pages/Frontend/Order.vue
:
<template>
<div class="min-h-screen bg-gray-100">
<!-- Header -->
<header class="bg-white shadow">
<div class="container mx-auto px-6 py-4">
<h1 class="text-2xl font-bold text-gray-800">User Dashboard</h1>
</div>
</header>
<!-- Main Content -->
<div class="container mx-auto px-6 py-8 grid grid-cols-1 md:grid-cols-4 gap-6">
<!-- Profile Sidebar -->
<aside class="bg-white p-6 shadow rounded-md md:col-span-1">
<div class="flex items-center space-x-4">
<img
src="https://placehold.co/600x400/png"
alt="User Profile"
class="w-16 h-16 rounded-full border border-gray-300"
/>
<div>
<h2 class="text-lg font-semibold">{{ $page.props.auth.user.name }}</h2>
<p class="text-gray-500">{{ $page.props.auth.user.email }}</p>
</div>
</div>
<ul class="mt-6 space-y-4">
<li>
<Link href="/user/orders" class="text-blue-500 hover:underline">My Orders</Link>
</li>
<li>
<Link href="/user/settings" class="text-blue-500 hover:underline">Settings</Link>
</li>
</ul>
</aside>
<!-- Orders List -->
<main class="bg-white p-6 shadow rounded-md md:col-span-3">
<h2 class="text-xl font-bold mb-4">My Orders</h2>
<!-- Orders Table -->
<div class="overflow-x-auto">
<table class="w-full border-collapse border border-gray-200">
<thead>
<tr class="bg-gray-100">
<th class="border px-4 py-2 text-left">Order ID</th>
<th class="border px-4 py-2 text-left">Date</th>
<th class="border px-4 py-2 text-left">Total</th>
<th class="border px-4 py-2 text-left">Status</th>
<th class="border px-4 py-2 text-center">Action</th>
</tr>
</thead>
<tbody>
<tr v-for="order in orders.data" :key="order.id">
<td class="border px-4 py-2">{{ order.id }}</td>
<td class="border px-4 py-2">{{ new Date(order.created_at).toLocaleDateString() }}</td>
<td class="border px-4 py-2">{{ formatCurrency(order.total_price) }}</td>
<td class="border px-4 py-2">
<span
:class="{
'bg-green-100 text-green-700': order.status === 'completed',
'bg-yellow-100 text-yellow-700': order.status === 'pending',
'bg-red-100 text-red-700': order.status === 'canceled'
}"
class="px-2 py-1 text-xs font-semibold rounded-full"
>
{{ order.status }}
</span>
</td>
<td class="border px-4 py-2 text-center">
<Link
:href="route('user.orders.show', order.id)"
class="text-blue-500 hover:underline"
>
View
</Link>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Pagination -->
<Pagination :links="orders.links" />
</main>
</div>
</div>
</template>
<script>
import { Link } from '@inertiajs/vue3';
import Pagination from '@/Components/Pagination.vue';
export default {
props: {
orders: {
type: Object,
required: true,
},
},
components: {
Link,
Pagination,
},
methods: {
formatCurrency(amount) {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'IDR',
}).format(amount);
},
},
};
</script>
<style scoped>
body {
font-family: 'Inter', sans-serif;
}
</style>
Kemudian buat file Buat file resources/js/Pages/Frontend/OrderDetail.vue
:
<template>
<div class="container mx-auto py-8 px-4">
<div class="bg-white shadow-lg rounded-lg p-6">
<!-- Header Section -->
<h2 class="text-2xl font-bold mb-4">Order Details</h2>
<!-- Order Summary -->
<div class="mb-6">
<p class="text-lg"><strong>Order ID:</strong> {{ order.id }}</p>
<p class="text-lg"><strong>Order Date:</strong> {{ new Date(order.created_at).toLocaleDateString() }}</p>
<p class="text-lg"><strong>Status:</strong> <span>{{ order.status }}</span></p>
</div>
<!-- Shipping Information -->
<div class="mb-6">
<h3 class="text-xl font-bold mb-2">Shipping Information</h3>
<p><strong>Name:</strong> {{ order.user.name }}</p>
<p><strong>Email:</strong> {{ order.user.email }}</p>
</div>
<!-- Product List -->
<div>
<h3 class="text-xl font-bold mb-2">Products</h3>
<table class="w-full border-collapse border border-gray-300">
<thead>
<tr class="bg-gray-100">
<th class="border border-gray-300 p-2 text-left">Product</th>
<th class="border border-gray-300 p-2 text-left">Quantity</th>
<th class="border border-gray-300 p-2 text-left">Price</th>
<th class="border border-gray-300 p-2 text-left">Total</th>
</tr>
</thead>
<tbody>
<tr v-for="item in order.items" :key="item.id" class="hover:bg-gray-50">
<td class="border border-gray-300 p-2">{{ item.product.name }}</td>
<td class="border border-gray-300 p-2">{{ item.quantity }}</td>
<td class="border border-gray-300 p-2">{{ formatCurrency(item.price) }}</td>
<td class="border border-gray-300 p-2">{{ formatCurrency(item.price * item.quantity) }}</td>
</tr>
</tbody>
</table>
</div>
<!-- Total Price -->
<div class="mt-6 text-right">
<p class="text-xl font-bold">Total: {{ formatCurrency(order.total_price) }}</p>
</div>
</div>
</div>
</template>
<script>
import { Link } from "@inertiajs/vue3";
export default {
components: { Link },
props: {
order: Object,
},
methods: {
formatCurrency(amount) {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: "IDR",
}).format(amount);
},
},
};
</script>
<style scoped>
/* Tambahkan gaya tambahan jika diperlukan */
</style>
Langkah 3. Route
Modifikasi file web.php dengan menambahkan route untuk orders user:
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/user/orders', [FrontendController::class, 'order'])->name('user.orders.index');
Route::get('/user/orders/{order}', [FrontendController::class, 'OrderDetail'])->name('user.orders.show');
});
Langkah 4. Testing
Lakukan testing dengan mengakses URL:
http://localhost:8000/user/orders
Jika berhasil, maka akan menghasilkan output seperi berikut:
Dan jika view diklik, maka akan seperti berikut:
Selamat Mencobaaa!!! silahkan tinggalkan komentar jika ada yang perlu didiskusikan :)