Update app/product/[id]/page.tsx
This commit is contained in:
parent
765b65de32
commit
510dbc1d9c
|
|
@ -0,0 +1,261 @@
|
|||
"use client";
|
||||
import { Container } from "@/components/container";
|
||||
import { Footer } from "@/components/footer";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { BlurImage } from "@/components/blur-image";
|
||||
import { Badge } from "@/components/badge";
|
||||
import { useState } from "react";
|
||||
import { ProductCard } from "@/components/product-card";
|
||||
|
||||
// Mock product data - in real app, this would come from API/database
|
||||
const productData = {
|
||||
id: "1",
|
||||
name: "Modern Velvet Sofa",
|
||||
price: 899,
|
||||
originalPrice: 1299,
|
||||
category: "Living Room",
|
||||
description: "Elevate your living space with our luxurious Modern Velvet Sofa. Featuring plush velvet upholstery, deep cushioning, and a sturdy hardwood frame, this sofa combines comfort with contemporary style. Perfect for relaxing after a long day or entertaining guests.",
|
||||
features: [
|
||||
"Premium velvet upholstery",
|
||||
"Solid hardwood frame",
|
||||
"High-density foam cushions",
|
||||
"Removable cushion covers",
|
||||
"Weight capacity: 800 lbs",
|
||||
"Assembly required (30 minutes)",
|
||||
],
|
||||
dimensions: {
|
||||
width: "84 inches",
|
||||
depth: "36 inches",
|
||||
height: "33 inches",
|
||||
seatHeight: "18 inches",
|
||||
},
|
||||
colors: ["Navy Blue", "Emerald Green", "Charcoal Gray", "Blush Pink"],
|
||||
images: [
|
||||
"https://images.unsplash.com/photo-1555041469-a586c61ea9bc?w=800&q=80",
|
||||
"https://images.unsplash.com/photo-1540574163026-643ea20ade25?w=800&q=80",
|
||||
"https://images.unsplash.com/photo-1567538096630-e0c55bd6374c?w=800&q=80",
|
||||
],
|
||||
inStock: true,
|
||||
rating: 4.8,
|
||||
reviews: 127,
|
||||
};
|
||||
|
||||
const relatedProducts = [
|
||||
{
|
||||
id: "5",
|
||||
name: "Minimalist Coffee Table",
|
||||
price: 299,
|
||||
image: "https://images.unsplash.com/photo-1532372320572-cda25653a26d?w=600&q=80",
|
||||
category: "Living Room",
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
name: "Leather Recliner",
|
||||
price: 799,
|
||||
originalPrice: 999,
|
||||
image: "https://images.unsplash.com/photo-1567538096630-e0c55bd6374c?w=600&q=80",
|
||||
category: "Living Room",
|
||||
isSale: true,
|
||||
},
|
||||
{
|
||||
id: "12",
|
||||
name: "Accent Armchair",
|
||||
price: 399,
|
||||
image: "https://images.unsplash.com/photo-1586023492125-27b2c045efd7?w=600&q=80",
|
||||
category: "Living Room",
|
||||
},
|
||||
];
|
||||
|
||||
export default function ProductDetailPage() {
|
||||
const [selectedImage, setSelectedImage] = useState(0);
|
||||
const [selectedColor, setSelectedColor] = useState(productData.colors[0]);
|
||||
const [quantity, setQuantity] = useState(1);
|
||||
|
||||
const discount = productData.originalPrice
|
||||
? Math.round(((productData.originalPrice - productData.price) / productData.originalPrice) * 100)
|
||||
: 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className="py-12">
|
||||
<Container>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 mb-20">
|
||||
{/* Product Images */}
|
||||
<div>
|
||||
<div className="relative h-[500px] rounded-2xl overflow-hidden mb-4">
|
||||
<BlurImage
|
||||
src={productData.images[selectedImage]}
|
||||
alt={productData.name}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
{discount > 0 && (
|
||||
<div className="absolute top-4 right-4">
|
||||
<Badge variant="destructive">-{discount}%</Badge>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
{productData.images.map((image, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => setSelectedImage(index)}
|
||||
className={`relative h-32 rounded-lg overflow-hidden border-2 transition-all ${
|
||||
selectedImage === index
|
||||
? "border-neutral-900 dark:border-neutral-100"
|
||||
: "border-transparent hover:border-neutral-300"
|
||||
}`}
|
||||
>
|
||||
<BlurImage
|
||||
src={image}
|
||||
alt={`${productData.name} view ${index + 1}`}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Product Info */}
|
||||
<div>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400 uppercase tracking-wide mb-2">
|
||||
{productData.category}
|
||||
</p>
|
||||
<h1 className="text-4xl font-bold mb-4">{productData.name}</h1>
|
||||
|
||||
<div className="flex items-center gap-4 mb-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-3xl font-bold">${productData.price}</span>
|
||||
{productData.originalPrice && (
|
||||
<span className="text-xl text-neutral-500 line-through">
|
||||
${productData.originalPrice}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-yellow-500">★</span>
|
||||
<span className="font-semibold">{productData.rating}</span>
|
||||
<span className="text-neutral-500">({productData.reviews} reviews)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-neutral-600 dark:text-neutral-400 mb-6">
|
||||
{productData.description}
|
||||
</p>
|
||||
|
||||
{/* Color Selection */}
|
||||
<div className="mb-6">
|
||||
<p className="font-semibold mb-3">Color: {selectedColor}</p>
|
||||
<div className="flex gap-2">
|
||||
{productData.colors.map((color) => (
|
||||
<button
|
||||
key={color}
|
||||
onClick={() => setSelectedColor(color)}
|
||||
className={`px-4 py-2 rounded-lg border-2 transition-all ${
|
||||
selectedColor === color
|
||||
? "border-neutral-900 dark:border-neutral-100 bg-neutral-100 dark:bg-neutral-800"
|
||||
: "border-neutral-200 dark:border-neutral-700 hover:border-neutral-400"
|
||||
}`}
|
||||
>
|
||||
{color}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Quantity */}
|
||||
<div className="mb-6">
|
||||
<p className="font-semibold mb-3">Quantity</p>
|
||||
<div className="flex items-center gap-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setQuantity(Math.max(1, quantity - 1))}
|
||||
>
|
||||
-
|
||||
</Button>
|
||||
<span className="text-xl font-semibold w-12 text-center">{quantity}</span>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setQuantity(quantity + 1)}
|
||||
>
|
||||
+
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Add to Cart */}
|
||||
<div className="flex gap-4 mb-8">
|
||||
<Button size="lg" className="flex-1">
|
||||
Add to Cart - ${productData.price * quantity}
|
||||
</Button>
|
||||
<Button size="lg" variant="outline">
|
||||
♡
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Stock Status */}
|
||||
{productData.inStock ? (
|
||||
<p className="text-green-600 dark:text-green-400 mb-6">
|
||||
✓ In Stock - Ships within 2-3 business days
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-red-600 dark:text-red-400 mb-6">
|
||||
Out of Stock - Notify me when available
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Features */}
|
||||
<div className="border-t pt-6">
|
||||
<h3 className="font-semibold text-lg mb-4">Key Features</h3>
|
||||
<ul className="space-y-2">
|
||||
{productData.features.map((feature, index) => (
|
||||
<li key={index} className="flex items-start gap-2">
|
||||
<span className="text-green-600 dark:text-green-400 mt-1">✓</span>
|
||||
<span className="text-neutral-600 dark:text-neutral-400">{feature}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Dimensions */}
|
||||
<div className="border-t mt-6 pt-6">
|
||||
<h3 className="font-semibold text-lg mb-4">Dimensions</h3>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<p className="text-sm text-neutral-500">Width</p>
|
||||
<p className="font-semibold">{productData.dimensions.width}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-neutral-500">Depth</p>
|
||||
<p className="font-semibold">{productData.dimensions.depth}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-neutral-500">Height</p>
|
||||
<p className="font-semibold">{productData.dimensions.height}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-neutral-500">Seat Height</p>
|
||||
<p className="font-semibold">{productData.dimensions.seatHeight}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Related Products */}
|
||||
<div>
|
||||
<h2 className="text-3xl font-bold mb-8">You May Also Like</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{relatedProducts.map((product) => (
|
||||
<ProductCard key={product.id} {...product} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue