262 lines
9.7 KiB
TypeScript
262 lines
9.7 KiB
TypeScript
"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 />
|
|
</>
|
|
);
|
|
}
|