Merge version_1 into main #8
@@ -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, ShoppingCart, Heart } from "lucide-react";
|
||||
import { Instagram, Twitter, Youtube } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
|
||||
@@ -20,29 +20,29 @@ const TikTok = (props: React.SVGProps<SVGSVGElement>) => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
const products: Record<string, any> = {
|
||||
"1": {
|
||||
const products = [
|
||||
{
|
||||
id: "1", name: "Classic Black Hoodie", price: 89.99,
|
||||
description: "Experience the epitome of urban comfort with our Classic Black Hoodie. Crafted from premium heavyweight cotton blend, this essential piece offers a perfect balance of style and warmth. The oversized silhouette provides that coveted streetwear aesthetic, while premium stitching ensures durability. Whether you're hitting the streets or relaxing at home, this hoodie becomes an instant wardrobe staple.", imageSrc: "http://img.b2bpic.net/free-photo/medium-shot-man-posing-with-hoodie-indoors_23-2149359859.jpg", imageAlt: "Classic black oversized hoodie", sizes: ["XS", "S", "M", "L", "XL", "2XL"],
|
||||
description: "Premium oversized hoodie crafted from 100% organic cotton. Perfect for layering or wearing solo. Features reinforced seams and a comfortable fit that works with any style.", image: "http://img.b2bpic.net/free-photo/medium-shot-man-posing-with-hoodie-indoors_23-2149359859.jpg", sizes: ["XS", "S", "M", "L", "XL", "XXL"],
|
||||
colors: ["Black", "Charcoal", "Navy"],
|
||||
rating: 4.8,
|
||||
reviews: 124,
|
||||
},
|
||||
"2": {
|
||||
{
|
||||
id: "2", name: "Vintage Denim Jacket", price: 129.99,
|
||||
description: "Step back in time with our Vintage Denim Jacket, an iconic piece that never goes out of style. This carefully distressed jacket combines classic denim craftsmanship with modern streetwear edge. Perfect for layering, it adds instant cool factor to any outfit. The slightly faded wash and strategic rips create that perfect worn-in vintage feel that can only come from quality construction and timeless design.", imageSrc: "http://img.b2bpic.net/free-photo/fashionable-woman-wearing-denim-jacket_23-2148859621.jpg", imageAlt: "Vintage style denim jacket", sizes: ["XS", "S", "M", "L", "XL"],
|
||||
colors: ["Indigo", "Light Wash", "Black Denim"],
|
||||
rating: 4.9,
|
||||
reviews: 89,
|
||||
description: "Timeless denim jacket with authentic vintage wash. Perfect for any occasion. Heavy-duty construction with durable hardware and reinforced stitching.", image: "http://img.b2bpic.net/free-photo/fashionable-woman-wearing-denim-jacket_23-2148859621.jpg", sizes: ["XS", "S", "M", "L", "XL"],
|
||||
colors: ["Indigo", "Light Wash", "Medium Wash"],
|
||||
},
|
||||
};
|
||||
{
|
||||
id: "3", name: "Cargo Pants - Khaki", price: 79.99,
|
||||
description: "Versatile cargo pants with multiple pockets. Made from durable cotton blend. Perfect for everyday wear and outdoor adventures.", image: "http://img.b2bpic.net/free-photo/young-woman-wearing-trucker-hat_23-2149432334.jpg", sizes: ["28", "30", "32", "34", "36", "38"],
|
||||
colors: ["Khaki", "Olive", "Black"],
|
||||
},
|
||||
];
|
||||
|
||||
export default function ProductPage({ params }: { params: { id: string } }) {
|
||||
const product = products[params.id] || products["1"];
|
||||
const product = products.find((p) => p.id === params.id);
|
||||
const [quantity, setQuantity] = useState(1);
|
||||
const [selectedSize, setSelectedSize] = useState(product.sizes[2]);
|
||||
const [selectedColor, setSelectedColor] = useState(product.colors[0]);
|
||||
const [isFavorited, setIsFavorited] = useState(false);
|
||||
const [selectedSize, setSelectedSize] = useState(product?.sizes[0]);
|
||||
const [selectedColor, setSelectedColor] = useState(product?.colors[0]);
|
||||
|
||||
const navItems = [
|
||||
{ name: "Shop", id: "products" },
|
||||
@@ -59,6 +59,46 @@ export default function ProductPage({ params }: { params: { id: string } }) {
|
||||
{ icon: Youtube, href: "https://youtube.com/@umbra", ariaLabel: "YouTube" },
|
||||
];
|
||||
|
||||
if (!product) {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="shift-hover"
|
||||
defaultTextAnimation="reveal-blur"
|
||||
borderRadius="soft"
|
||||
contentWidth="smallMedium"
|
||||
sizing="medium"
|
||||
background="circleGradient"
|
||||
cardStyle="glass-elevated"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="normal"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleCentered
|
||||
navItems={navItems}
|
||||
button={{ text: "View Cart", href: "/cart" }}
|
||||
brandName="Umbra"
|
||||
/>
|
||||
</div>
|
||||
<div className="min-h-screen flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<h1 className="text-2xl font-semibold text-foreground mb-4">Product not found</h1>
|
||||
<Link href="/shop" className="text-accent hover:text-background-accent">
|
||||
Back to Shop
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterCard
|
||||
logoText="Umbra"
|
||||
copyrightText="© 2025 | Umbra Streetwear. All rights reserved."
|
||||
socialLinks={socialLinks}
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="shift-hover"
|
||||
@@ -80,122 +120,103 @@ 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 md:grid-cols-2 gap-12">
|
||||
{/* Product Image */}
|
||||
<div className="flex items-center justify-center bg-card/50 rounded-soft p-8 min-h-96">
|
||||
<div className="flex items-center justify-center bg-card/50 border border-accent/20 rounded-soft p-8">
|
||||
<img
|
||||
src={product.imageSrc}
|
||||
alt={product.imageAlt}
|
||||
className="w-full h-full object-cover rounded-soft"
|
||||
src={product.image}
|
||||
alt={product.name}
|
||||
className="w-full h-auto rounded-soft object-cover"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Product Info */}
|
||||
<div className="flex flex-col justify-start space-y-6">
|
||||
<div>
|
||||
<h1 className="text-4xl font-semibold text-foreground mb-2">{product.name}</h1>
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<div className="flex text-background-accent">
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<span key={i}>★</span>
|
||||
<div className="flex flex-col justify-center">
|
||||
<h1 className="text-4xl font-light text-foreground mb-4">{product.name}</h1>
|
||||
<p className="text-3xl font-semibold text-background-accent mb-6">
|
||||
${product.price.toFixed(2)}
|
||||
</p>
|
||||
<p className="text-foreground/70 mb-8 leading-relaxed">{product.description}</p>
|
||||
|
||||
<div className="space-y-6 mb-8">
|
||||
<div>
|
||||
<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={`px-4 py-2 rounded-soft border transition-colors ${
|
||||
selectedSize === size
|
||||
? "bg-background-accent text-primary-cta-text border-background-accent"
|
||||
: "border-accent/30 text-foreground hover:border-accent"
|
||||
}`}
|
||||
>
|
||||
{size}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<span className="text-foreground/70">{product.rating} ({product.reviews} reviews)</span>
|
||||
</div>
|
||||
<p className="text-2xl font-bold text-background-accent">${product.price.toFixed(2)}</p>
|
||||
</div>
|
||||
|
||||
<p className="text-foreground/80 leading-relaxed">{product.description}</p>
|
||||
<div>
|
||||
<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 rounded-soft border transition-colors ${
|
||||
selectedColor === color
|
||||
? "bg-background-accent text-primary-cta-text border-background-accent"
|
||||
: "border-accent/30 text-foreground hover:border-accent"
|
||||
}`}
|
||||
>
|
||||
{color}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Size Selection */}
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-3">Size</label>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{product.sizes.map((size: string) => (
|
||||
<div>
|
||||
<label className="block text-foreground font-semibold mb-3">Quantity</label>
|
||||
<div className="flex items-center gap-3 w-fit bg-accent/10 rounded-soft p-2">
|
||||
<button
|
||||
key={size}
|
||||
onClick={() => setSelectedSize(size)}
|
||||
className={`px-4 py-2 rounded-soft font-semibold transition-colors ${
|
||||
selectedSize === size
|
||||
? "bg-background-accent text-primary-cta-text"
|
||||
: "bg-card border border-accent/20 text-foreground hover:border-background-accent"
|
||||
}`}
|
||||
onClick={() => setQuantity(Math.max(1, quantity - 1))}
|
||||
className="px-3 py-1 hover:bg-accent/20 rounded transition-colors"
|
||||
>
|
||||
{size}
|
||||
−
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Color Selection */}
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-3">Color</label>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{product.colors.map((color: string) => (
|
||||
<span className="w-8 text-center font-semibold text-foreground">{quantity}</span>
|
||||
<button
|
||||
key={color}
|
||||
onClick={() => setSelectedColor(color)}
|
||||
className={`px-4 py-2 rounded-soft font-semibold transition-colors ${
|
||||
selectedColor === color
|
||||
? "bg-background-accent text-primary-cta-text"
|
||||
: "bg-card border border-accent/20 text-foreground hover:border-background-accent"
|
||||
}`}
|
||||
onClick={() => setQuantity(quantity + 1)}
|
||||
className="px-3 py-1 hover:bg-accent/20 rounded transition-colors"
|
||||
>
|
||||
{color}
|
||||
+
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Quantity Selection */}
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-3">Quantity</label>
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={() => setQuantity(Math.max(1, quantity - 1))}
|
||||
className="px-4 py-2 bg-card border border-accent/20 rounded-soft hover:border-background-accent transition-colors"
|
||||
>
|
||||
−
|
||||
</button>
|
||||
<span className="text-lg font-semibold text-foreground w-8 text-center">{quantity}</span>
|
||||
<button
|
||||
onClick={() => setQuantity(quantity + 1)}
|
||||
className="px-4 py-2 bg-card border border-accent/20 rounded-soft hover:border-background-accent transition-colors"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Add to Cart & Favorite */}
|
||||
<div className="flex gap-4 pt-4">
|
||||
<button className="flex-1 px-6 py-3 bg-background-accent text-primary-cta-text font-semibold rounded-soft hover:bg-primary-cta transition-colors flex items-center justify-center gap-2">
|
||||
<ShoppingCart size={20} />
|
||||
<div className="flex gap-4">
|
||||
<button className="flex-1 px-8 py-3 bg-background-accent text-primary-cta-text font-semibold rounded-soft hover:bg-primary-cta hover:text-primary-cta-text transition-colors">
|
||||
Add to Cart
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsFavorited(!isFavorited)}
|
||||
className={`px-6 py-3 rounded-soft border transition-colors ${
|
||||
isFavorited
|
||||
? "bg-background-accent/20 border-background-accent text-background-accent"
|
||||
: "border-accent/20 text-foreground hover:border-background-accent"
|
||||
}`}
|
||||
>
|
||||
<Heart size={20} fill={isFavorited ? "currentColor" : "none"} />
|
||||
<button className="flex-1 px-8 py-3 border border-accent/50 text-foreground font-semibold rounded-soft hover:bg-accent/10 transition-colors">
|
||||
Save for Later
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Product Details */}
|
||||
<div className="pt-6 border-t border-accent/20 space-y-3">
|
||||
<p className="text-sm text-foreground/70">✓ Free shipping on orders over $150</p>
|
||||
<p className="text-sm text-foreground/70">✓ 30-day return policy</p>
|
||||
<p className="text-sm text-foreground/70">✓ Secure checkout with multiple payment options</p>
|
||||
<div className="mt-8 pt-8 border-t border-accent/20">
|
||||
<p className="text-foreground/70 text-sm">
|
||||
<span className="font-semibold text-foreground">Free Shipping:</span> On orders over $150
|
||||
</p>
|
||||
<p className="text-foreground/70 text-sm mt-2">
|
||||
<span className="font-semibold text-foreground">Easy Returns:</span> 30-day money-back guarantee
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user