Berikut adalah contoh implementasi Product Detail di frontend beserta desain nya. Selain itu, kita juga akan mengedit halaman home (frontend) agar produk dapat di-klik untuk menuju halaman detail produk.

1. Routing & Controller untuk Product Detail

Tambahkan route di routes/web.php untuk halaman detail produk. Kita akan identifikasi produk menggunakan slug:

use App\Http\Controllers\FrontendController;

Route::get('products/{slug}', [FrontendController::class, 'show'])->name('products.show');

Di FrontendController.php, tambahkan method show:

public function show($slug)
{
    $product = Product::with('images', 'category')->where('slug', $slug)->firstOrFail();

    return Inertia::render('Frontend/ProductDetail', [
        'product' => $product
    ]);
}

2. Edit Halaman Home (Frontend/Homepage.vue)

Ubah bagian card product pada homepage agar klik nama produk (atau gambar) membawa user ke halaman detail produk. Gunakan Inertia <Link>:

<!-- PRODUCT GRID -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-6">
    <div
        v-for="product in products.data"
        :key="product.id"
        class="bg-white p-4 rounded shadow hover:shadow-md transition-shadow"
    >
        <Link :href="route('products.show', product.slug)" class="block relative pb-1/1 overflow-hidden rounded">
        <img
            v-if="product.images && product.images.length > 0"
            :src="`/storage/${product.images[0].image}`"
            alt="Product Image"
            class="w-full h-full object-cover rounded"
        />
        <div v-else class="absolute h-full w-full flex items-center justify-center text-gray-400">
            No Image
        </div>
        </Link>
        <Link :href="route('products.show', product.slug)">
        <h2 class="mt-2 font-semibold text-sm text-gray-800 line-clamp-2 hover:text-blue-600 transition-colors">{{ product.name }}</h2>
        </Link>
        <p class="text-xs text-gray-500">{{ product.category ? product.category.name : 'No Category' }}</p>
        <p class="text-red-600 font-bold mt-1 text-sm">Rp {{ product.price }}</p>
    </div>
</div>

3. Membuat ProductDetail.vue

Buat file resources/js/Pages/Frontend/ProductDetail.vue:

<template>
    <div class="min-h-screen flex flex-col bg-gray-50">
      <!-- NAVBAR -->
      <header class="bg-white shadow z-10">
        <div class="max-w-7xl mx-auto px-4 py-4 flex items-center justify-between">
          <div class="text-2xl font-bold text-gray-800">MyShop</div>
          <nav class="flex items-center space-x-6">
            <Link href="/" class="text-gray-700 hover:text-gray-900 font-medium px-3 py-2 transition-colors">Home</Link>
            <Link href="/categories" class="text-gray-700 hover:text-gray-900 font-medium px-3 py-2 transition-colors">Categories</Link>
            <Link href="/about" class="text-gray-700 hover:text-gray-900 font-medium px-3 py-2 transition-colors">About</Link>
          </nav>
        </div>
      </header>
  
      <!-- MAIN CONTENT -->
      <main class="flex-1 py-10">
        <div class="max-w-6xl mx-auto px-4">
          <!-- Back Link -->
          <div class="mb-4">
            <Link href="/" class="text-sm text-blue-600 hover:text-blue-800">&larr; Back to Home</Link>
          </div>
  
          <div class="md:flex md:space-x-10">
            <!-- Image Gallery -->
            <div class="md:w-1/2 mb-8 md:mb-0">
              <!-- Main Image -->
              <div class="relative w-full h-96 bg-white rounded-lg shadow-lg">
                <img
                  v-if="selectedImage || product.images.length > 0"
                  :src="`/storage/${selectedImage || product.images[0].image}`"
                  alt="Product Image"
                  class="absolute inset-0 w-full h-full object-cover rounded-lg"
                />
                <div v-else class="absolute inset-0 w-full h-full flex items-center justify-center text-gray-400">
                  No Image Available
                </div>
              </div>
  
              <!-- Thumbnails -->
              <div class="flex space-x-2 mt-4 overflow-x-auto pb-2">
                <div
                  v-for="(img, index) in product.images"
                  :key="index"
                  @click="selectedImage = img.image"
                  class="w-16 h-16 relative border rounded-lg overflow-hidden cursor-pointer hover:opacity-80 transition"
                >
                  <img :src="`/storage/${img.image}`" class="absolute w-full h-full object-cover" />
                </div>
              </div>
            </div>
  
            <!-- Product Info -->
            <div class="md:w-1/2">
              <h1 class="text-3xl font-bold text-gray-800 mb-3">{{ product.name }}</h1>
              <p class="text-sm text-gray-500 mb-1">Category: {{ product.category ? product.category.name : 'No Category' }}</p>
              <p class="text-xl text-red-600 font-bold mb-6">Rp {{ product.price }}</p>
              <p class="text-gray-700 leading-relaxed mb-8">{{ product.description }}</p>
  
              <div class="flex items-center space-x-4 mb-8">
                <button class="px-6 py-3 bg-blue-600 text-white font-semibold rounded hover:bg-blue-700 transition">Add to Cart</button>
                <button class="px-6 py-3 bg-gray-200 text-gray-700 font-semibold rounded hover:bg-gray-300 transition">
                  Wishlist
                </button>
              </div>
  
              <div class="border-t pt-6 space-y-4">
                <h2 class="text-lg font-semibold text-gray-800">Product Details</h2>
                <ul class="space-y-1 text-gray-600 text-sm list-disc list-inside">
                  <li>High-quality material</li>
                  <li>Available in various sizes</li>
                  <li>30-day return policy</li>
                </ul>
              </div>
            </div>
          </div>
        </div>
      </main>
  
      <!-- FOOTER -->
      <footer class="bg-white py-4">
        <div class="max-w-7xl mx-auto px-4 text-center text-gray-600 text-sm">
          &copy; 2024 MyShop. All rights reserved.
        </div>
      </footer>
    </div>
  </template>
  
  <script>
  import { ref } from 'vue';
  import { Link } from '@inertiajs/inertia-vue3';
  
  export default {
    props: {
      product: Object
    },
    components: { Link },
    setup(props) {
      const selectedImage = ref(null); // Set initial image if no thumbnail clicked
      return { selectedImage };
    },
  };
  </script>
  
  <style scoped>
  /* Ensuring that the image maintains its aspect ratio */
  .relative {
    position: relative;
  }
  .object-cover {
    object-fit: cover;
  }
  </style>
  

4. Lakukan Testing

Buka homepage (http://localhost:8000). Kemudian klik gambar, atau nama productnya yang akan mengarah ke halaman detail Product.

Jika berhasil, akan seperti berikut:
product detail

Selamat mencoba!!! Jika ada error, silahkan tinggalkan kolom komentar