Merge version_1 into main #10
@@ -3,7 +3,7 @@
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleCentered from "@/components/navbar/NavbarStyleCentered/NavbarStyleCentered";
|
||||
import FooterCard from "@/components/sections/footer/FooterCard";
|
||||
import { Instagram, Twitter, Youtube } from "lucide-react";
|
||||
import { Instagram, Twitter, Youtube, ShoppingCart, Heart, Share2 } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
|
||||
@@ -20,28 +20,7 @@ const TikTok = (props: React.SVGProps<SVGSVGElement>) => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
const products: Record<string, any> = {
|
||||
"1": {
|
||||
id: "1", name: "Classic Black Hoodie", price: "$89.99", originalPrice: "$119.99", description: "Our signature black hoodie - a timeless essential for any streetwear collection. Premium 100% cotton blend with soft interior lining. Features a kangaroo pocket, drawstring with metal tips, and embroidered Umbra logo on the chest.", images: [
|
||||
"http://img.b2bpic.net/free-photo/medium-shot-man-posing-with-hoodie-indoors_23-2149359859.jpg", "http://img.b2bpic.net/free-photo/medium-shot-man-posing-with-hoodie-indoors_23-2149359859.jpg"],
|
||||
sizes: ["XS", "S", "M", "L", "XL", "2XL"],
|
||||
colors: ["Black", "Charcoal", "Navy"],
|
||||
rating: 4.8,
|
||||
reviews: 342,
|
||||
inStock: true,
|
||||
},
|
||||
"2": {
|
||||
id: "2", name: "Vintage Denim Jacket", price: "$129.99", description: "Classic denim jacket with a vintage washed finish. Perfect layering piece for any outfit. Features button closure, flap pockets, and adjustable waist tabs.", images: [
|
||||
"http://img.b2bpic.net/free-photo/fashionable-woman-wearing-denim-jacket_23-2148859621.jpg"],
|
||||
sizes: ["XS", "S", "M", "L", "XL", "2XL"],
|
||||
colors: ["Indigo", "Light Wash", "Dark Wash"],
|
||||
rating: 4.6,
|
||||
reviews: 218,
|
||||
inStock: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default function ProductPage({ params }: { params: { id: string } }) {
|
||||
export default function ProductPage() {
|
||||
const navItems = [
|
||||
{ name: "Shop", id: "products" },
|
||||
{ name: "Collections", id: "collections" },
|
||||
@@ -50,11 +29,10 @@ export default function ProductPage({ params }: { params: { id: string } }) {
|
||||
{ name: "Contact", id: "contact" },
|
||||
];
|
||||
|
||||
const product = products[params.id] || products["1"];
|
||||
const [quantity, setQuantity] = useState(1);
|
||||
const [selectedSize, setSelectedSize] = useState(product.sizes[2]);
|
||||
const [selectedColor, setSelectedColor] = useState(product.colors[0]);
|
||||
const [selectedImage, setSelectedImage] = useState(0);
|
||||
const [selectedSize, setSelectedSize] = useState("M");
|
||||
const [selectedColor, setSelectedColor] = useState("Black");
|
||||
const [isFavorite, setIsFavorite] = useState(false);
|
||||
|
||||
const socialLinks = [
|
||||
{ icon: Instagram, href: "https://instagram.com/umbra", ariaLabel: "Instagram" },
|
||||
@@ -63,6 +41,15 @@ export default function ProductPage({ params }: { params: { id: string } }) {
|
||||
{ icon: Youtube, href: "https://youtube.com/@umbra", ariaLabel: "YouTube" },
|
||||
];
|
||||
|
||||
const product = {
|
||||
id: "1", name: "Classic Black Hoodie", price: 89.99,
|
||||
description: "Our signature Classic Black Hoodie combines premium comfort with timeless style. Crafted from high-quality cotton blend fabric, this oversized hoodie features a spacious kangaroo pocket, adjustable drawstrings, and reinforced seams for durability. Perfect for layering or wearing solo, it's the essential streetwear piece for any wardrobe.", image: "http://img.b2bpic.net/free-photo/medium-shot-man-posing-with-hoodie-indoors_23-2149359859.jpg", rating: 4.8,
|
||||
reviewCount: 247,
|
||||
inStock: true,
|
||||
sizes: ["XS", "S", "M", "L", "XL", "XXL"],
|
||||
colors: ["Black", "Gray", "Navy", "White"],
|
||||
material: "80% Cotton, 20% Polyester", care: "Machine wash cold with similar colors. Tumble dry low."};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="shift-hover"
|
||||
@@ -84,98 +71,53 @@ export default function ProductPage({ params }: { params: { id: string } }) {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="product-detail" data-section="product-detail" className="mx-auto px-4 md:px-6 py-20">
|
||||
<div id="product" data-section="product" className="mx-auto px-4 md:px-6 py-20">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<Link href="/shop" className="text-accent hover:text-background-accent mb-8 inline-block">
|
||||
← Back to Shop
|
||||
</Link>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12">
|
||||
{/* Product Images */}
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="w-full aspect-square bg-card rounded-soft overflow-hidden">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 mb-16">
|
||||
{/* Product Image */}
|
||||
<div>
|
||||
<div className="bg-card rounded-soft overflow-hidden h-96 md:h-full">
|
||||
<img
|
||||
src={product.images[selectedImage]}
|
||||
src={product.image}
|
||||
alt={product.name}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
{product.images.map((img: string, idx: number) => (
|
||||
<button
|
||||
key={idx}
|
||||
onClick={() => setSelectedImage(idx)}
|
||||
className={`w-20 h-20 rounded-soft overflow-hidden border-2 transition-colors ${
|
||||
selectedImage === idx
|
||||
? "border-background-accent"
|
||||
: "border-accent/20 hover:border-accent/50"
|
||||
}`}
|
||||
>
|
||||
<img src={img} alt={`${product.name} ${idx}`} className="w-full h-full object-cover" />
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Product Details */}
|
||||
<div>
|
||||
<h1 className="text-4xl font-light text-foreground mb-2">{product.name}</h1>
|
||||
<div className="flex flex-col">
|
||||
<h1 className="text-4xl font-semibold text-foreground mb-4">{product.name}</h1>
|
||||
|
||||
<div className="flex items-center gap-4 mb-6">
|
||||
<div className="flex items-center gap-1">
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className={i < Math.floor(product.rating) ? "text-background-accent" : "text-accent/30"}
|
||||
>
|
||||
★
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<span className="text-sm text-foreground/70">({product.reviews} reviews)</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-baseline gap-4 mb-6">
|
||||
<span className="text-3xl font-bold text-background-accent">{product.price}</span>
|
||||
{product.originalPrice && (
|
||||
<span className="text-lg text-foreground/50 line-through">{product.originalPrice}</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<p className="text-foreground/70 mb-8">{product.description}</p>
|
||||
|
||||
{/* Color Selection */}
|
||||
<div className="mb-8">
|
||||
<label className="block text-sm font-semibold text-foreground mb-3">Color</label>
|
||||
<div className="flex gap-3">
|
||||
{product.colors.map((color: string) => (
|
||||
<button
|
||||
key={color}
|
||||
onClick={() => setSelectedColor(color)}
|
||||
className={`px-4 py-2 rounded-soft border-2 transition-colors ${
|
||||
selectedColor === color
|
||||
? "border-background-accent bg-background-accent/10"
|
||||
: "border-accent/20 hover:border-accent/50"
|
||||
}`}
|
||||
>
|
||||
{color}
|
||||
</button>
|
||||
))}
|
||||
<div className="flex items-center">
|
||||
<span className="text-xl font-semibold text-background-accent">{product.rating}</span>
|
||||
<span className="text-foreground/50 ml-2">({product.reviewCount} reviews)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-3xl font-bold text-background-accent mb-6">
|
||||
${product.price.toFixed(2)}
|
||||
</div>
|
||||
|
||||
<p className="text-foreground/70 mb-8 leading-relaxed">{product.description}</p>
|
||||
|
||||
{/* Size Selection */}
|
||||
<div className="mb-8">
|
||||
<label className="block text-sm font-semibold text-foreground mb-3">Size</label>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
{product.sizes.map((size: string) => (
|
||||
<label className="block text-foreground font-semibold mb-3">Size</label>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{product.sizes.map((size) => (
|
||||
<button
|
||||
key={size}
|
||||
onClick={() => setSelectedSize(size)}
|
||||
className={`py-2 rounded-soft border-2 transition-colors ${
|
||||
className={`px-4 py-2 border rounded-soft transition-all ${
|
||||
selectedSize === size
|
||||
? "border-background-accent bg-background-accent/10"
|
||||
: "border-accent/20 hover:border-accent/50"
|
||||
? "bg-background-accent text-primary-cta-text border-background-accent"
|
||||
: "border-accent/30 text-foreground hover:border-accent"
|
||||
}`}
|
||||
>
|
||||
{size}
|
||||
@@ -184,17 +126,37 @@ export default function ProductPage({ params }: { params: { id: string } }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Color Selection */}
|
||||
<div className="mb-8">
|
||||
<label className="block text-foreground font-semibold mb-3">Color</label>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{product.colors.map((color) => (
|
||||
<button
|
||||
key={color}
|
||||
onClick={() => setSelectedColor(color)}
|
||||
className={`px-4 py-2 border rounded-soft transition-all ${
|
||||
selectedColor === color
|
||||
? "bg-background-accent text-primary-cta-text border-background-accent"
|
||||
: "border-accent/30 text-foreground hover:border-accent"
|
||||
}`}
|
||||
>
|
||||
{color}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Quantity */}
|
||||
<div className="mb-8">
|
||||
<label className="block text-sm font-semibold text-foreground mb-3">Quantity</label>
|
||||
<div className="flex items-center gap-4 w-fit bg-accent/10 rounded-soft p-2">
|
||||
<label className="block text-foreground font-semibold mb-3">Quantity</label>
|
||||
<div className="flex items-center gap-4 bg-accent/10 rounded-soft p-2 w-fit">
|
||||
<button
|
||||
onClick={() => setQuantity(Math.max(1, quantity - 1))}
|
||||
className="px-3 py-1 hover:bg-accent/20 rounded transition-colors"
|
||||
>
|
||||
−
|
||||
</button>
|
||||
<span className="w-8 text-center font-semibold">{quantity}</span>
|
||||
<span className="text-foreground font-semibold w-8 text-center">{quantity}</span>
|
||||
<button
|
||||
onClick={() => setQuantity(quantity + 1)}
|
||||
className="px-3 py-1 hover:bg-accent/20 rounded transition-colors"
|
||||
@@ -204,23 +166,57 @@ export default function ProductPage({ params }: { params: { id: string } }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Add to Cart Button */}
|
||||
<button className="w-full px-6 py-4 bg-background-accent text-primary-cta-text font-semibold rounded-soft hover:bg-primary-cta hover:text-primary-cta-text transition-colors mb-4">
|
||||
Add to Cart
|
||||
</button>
|
||||
{/* Action Buttons */}
|
||||
<div className="flex flex-col gap-3 mb-8">
|
||||
<button className="w-full px-6 py-3 bg-background-accent text-primary-cta-text font-semibold rounded-soft hover:bg-primary-cta hover:text-primary-cta-text transition-colors flex items-center justify-center gap-2">
|
||||
<ShoppingCart size={20} />
|
||||
Add to Cart
|
||||
</button>
|
||||
<div className="flex gap-3">
|
||||
<button
|
||||
onClick={() => setIsFavorite(!isFavorite)}
|
||||
className={`flex-1 px-6 py-3 border rounded-soft font-semibold transition-all ${
|
||||
isFavorite
|
||||
? "bg-background-accent/20 border-background-accent text-background-accent"
|
||||
: "border-accent/30 text-foreground hover:border-accent"
|
||||
}`}
|
||||
>
|
||||
<Heart size={20} className="inline mr-2" />
|
||||
Favorite
|
||||
</button>
|
||||
<button className="flex-1 px-6 py-3 border border-accent/30 text-foreground font-semibold rounded-soft hover:border-accent transition-colors flex items-center justify-center gap-2">
|
||||
<Share2 size={20} />
|
||||
Share
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button className="w-full px-6 py-3 border border-accent/50 text-foreground font-semibold rounded-soft hover:bg-accent/10 transition-colors">
|
||||
Save for Later
|
||||
</button>
|
||||
|
||||
{/* Stock Status */}
|
||||
{product.inStock ? (
|
||||
<p className="text-sm text-background-accent font-semibold mt-4">✓ In Stock - Ships within 24 hours</p>
|
||||
<p className="text-background-accent font-semibold">✓ In Stock - Ships within 24 hours</p>
|
||||
) : (
|
||||
<p className="text-sm text-foreground/50 mt-4">Out of Stock - Notify me when available</p>
|
||||
<p className="text-red-500 font-semibold">Out of Stock</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Product Info */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-16 bg-card/50 border border-accent/20 rounded-soft p-8">
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-foreground mb-4">Material & Care</h3>
|
||||
<p className="text-foreground/70 mb-4">
|
||||
<span className="font-semibold">Material:</span> {product.material}
|
||||
</p>
|
||||
<p className="text-foreground/70">
|
||||
<span className="font-semibold">Care:</span> {product.care}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-foreground mb-4">Shipping & Returns</h3>
|
||||
<p className="text-foreground/70 mb-2">• Free shipping on orders over $150</p>
|
||||
<p className="text-foreground/70 mb-2">• 30-day returns with free return shipping</p>
|
||||
<p className="text-foreground/70">• Easy exchanges within 30 days</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user