Merge version_1 into main #7
@@ -3,10 +3,9 @@
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleCentered from "@/components/navbar/NavbarStyleCentered/NavbarStyleCentered";
|
||||
import FooterCard from "@/components/sections/footer/FooterCard";
|
||||
import { Instagram, Twitter, Youtube, Heart, Share2, ShoppingCart } from "lucide-react";
|
||||
import { Instagram, Twitter, Youtube, ShoppingCart, Heart } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import { useParams } from "next/navigation";
|
||||
|
||||
const TikTok = (props: React.SVGProps<SVGSVGElement>) => (
|
||||
<svg
|
||||
@@ -21,54 +20,28 @@ const TikTok = (props: React.SVGProps<SVGSVGElement>) => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
const products: Record<
|
||||
string,
|
||||
{
|
||||
id: string;
|
||||
name: string;
|
||||
price: number;
|
||||
imageSrc: string;
|
||||
imageAlt: string;
|
||||
description: string;
|
||||
sizes: string[];
|
||||
colors: string[];
|
||||
specs: { label: string; value: string }[];
|
||||
}
|
||||
> = {
|
||||
const products: Record<string, any> = {
|
||||
"1": {
|
||||
id: "1", name: "Classic Black Hoodie", price: 89.99,
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/medium-shot-man-posing-with-hoodie-indoors_23-2149359859.jpg", imageAlt: "Classic black oversized hoodie", description:
|
||||
"Premium comfort meets timeless style with our Classic Black Hoodie. Crafted from 100% organic cotton, this essential piece features a relaxed fit perfect for everyday wear. The durable construction ensures it'll be a staple in your wardrobe for years to come.", sizes: ["XS", "S", "M", "L", "XL", "XXL"],
|
||||
colors: ["Black", "Gray", "Navy"],
|
||||
specs: [
|
||||
{ label: "Material", value: "100% Organic Cotton" },
|
||||
{ label: "Weight", value: "280g" },
|
||||
{ label: "Care", value: "Machine wash cold" },
|
||||
{ label: "Fit", value: "Relaxed" },
|
||||
],
|
||||
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"],
|
||||
colors: ["Black", "Charcoal", "Navy"],
|
||||
rating: 4.8,
|
||||
reviews: 124,
|
||||
},
|
||||
"2": {
|
||||
id: "2", name: "Vintage Denim Jacket", price: 129.99,
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/fashionable-woman-wearing-denim-jacket_23-2148859621.jpg", imageAlt: "Vintage style denim jacket", description:
|
||||
"Elevate your streetwear game with our Vintage Denim Jacket. Featuring authentic distressing and premium indigo denim, this jacket adds instant character to any outfit. Perfect for layering or wearing standalone.", sizes: ["XS", "S", "M", "L", "XL"],
|
||||
colors: ["Indigo", "Light Blue", "Black"],
|
||||
specs: [
|
||||
{ label: "Material", value: "100% Cotton Denim" },
|
||||
{ label: "Weight", value: "650g" },
|
||||
{ label: "Care", value: "Wash separately" },
|
||||
{ label: "Fit", value: "Classic" },
|
||||
],
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
export default function ProductPage() {
|
||||
const params = useParams();
|
||||
const productId = params.id as string;
|
||||
const product = products[productId];
|
||||
|
||||
const [selectedSize, setSelectedSize] = useState(product?.sizes[2] || "");
|
||||
const [selectedColor, setSelectedColor] = useState(product?.colors[0] || "");
|
||||
export default function ProductPage({ params }: { params: { id: string } }) {
|
||||
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 [isFavorited, setIsFavorited] = useState(false);
|
||||
|
||||
const navItems = [
|
||||
@@ -86,48 +59,6 @@ export default function ProductPage() {
|
||||
{ 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-4xl font-bold text-foreground mb-4">Product Not Found</h1>
|
||||
<Link href="/shop" className="text-accent hover:text-background-accent">
|
||||
Return 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"
|
||||
@@ -149,39 +80,51 @@ export default function ProductPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="product" data-section="product" className="min-h-screen px-4 py-20">
|
||||
<div id="product-detail" data-section="product-detail" 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">
|
||||
<div className="flex items-center justify-center bg-card/30 rounded-soft overflow-hidden">
|
||||
<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">
|
||||
<img
|
||||
src={product.imageSrc}
|
||||
alt={product.imageAlt}
|
||||
className="w-full h-full object-cover"
|
||||
className="w-full h-full object-cover rounded-soft"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col justify-center">
|
||||
<h1 className="text-5xl font-light text-foreground mb-4">{product.name}</h1>
|
||||
<p className="text-3xl font-bold text-background-accent mb-6">
|
||||
${product.price.toFixed(2)}
|
||||
</p>
|
||||
<p className="text-foreground/70 text-lg mb-8">{product.description}</p>
|
||||
{/* 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>
|
||||
<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>
|
||||
|
||||
<div className="mb-8">
|
||||
<label className="block text-foreground font-semibold mb-3">Size</label>
|
||||
<div className="flex gap-3 flex-wrap">
|
||||
{product.sizes.map((size) => (
|
||||
<p className="text-foreground/80 leading-relaxed">{product.description}</p>
|
||||
|
||||
{/* 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) => (
|
||||
<button
|
||||
key={size}
|
||||
onClick={() => setSelectedSize(size)}
|
||||
className={`px-4 py-2 rounded-soft border-2 transition-colors ${
|
||||
className={`px-4 py-2 rounded-soft font-semibold transition-colors ${
|
||||
selectedSize === size
|
||||
? "bg-background-accent text-primary-cta-text border-background-accent"
|
||||
: "border-accent/30 text-foreground hover:border-accent"
|
||||
? "bg-background-accent text-primary-cta-text"
|
||||
: "bg-card border border-accent/20 text-foreground hover:border-background-accent"
|
||||
}`}
|
||||
>
|
||||
{size}
|
||||
@@ -190,17 +133,18 @@ export default function ProductPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-8">
|
||||
<label className="block text-foreground font-semibold mb-3">Color</label>
|
||||
<div className="flex gap-3 flex-wrap">
|
||||
{product.colors.map((color) => (
|
||||
{/* 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) => (
|
||||
<button
|
||||
key={color}
|
||||
onClick={() => setSelectedColor(color)}
|
||||
className={`px-4 py-2 rounded-soft border-2 transition-colors ${
|
||||
className={`px-4 py-2 rounded-soft font-semibold transition-colors ${
|
||||
selectedColor === color
|
||||
? "bg-background-accent text-primary-cta-text border-background-accent"
|
||||
: "border-accent/30 text-foreground hover:border-accent"
|
||||
? "bg-background-accent text-primary-cta-text"
|
||||
: "bg-card border border-accent/20 text-foreground hover:border-background-accent"
|
||||
}`}
|
||||
>
|
||||
{color}
|
||||
@@ -209,55 +153,49 @@ export default function ProductPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-8">
|
||||
<label className="block text-foreground font-semibold mb-3">Quantity</label>
|
||||
<div className="flex items-center gap-4 w-fit bg-accent/10 rounded-soft p-2">
|
||||
{/* 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-3 py-1 hover:bg-accent/20 rounded transition-colors"
|
||||
className="px-4 py-2 bg-card border border-accent/20 rounded-soft hover:border-background-accent transition-colors"
|
||||
>
|
||||
−
|
||||
</button>
|
||||
<span className="w-8 text-center font-semibold text-foreground">{quantity}</span>
|
||||
<span className="text-lg font-semibold text-foreground w-8 text-center">{quantity}</span>
|
||||
<button
|
||||
onClick={() => setQuantity(quantity + 1)}
|
||||
className="px-3 py-1 hover:bg-accent/20 rounded transition-colors"
|
||||
className="px-4 py-2 bg-card border border-accent/20 rounded-soft hover:border-background-accent transition-colors"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4 mb-8">
|
||||
<button className="flex-1 px-8 py-4 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">
|
||||
{/* 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} />
|
||||
Add to Cart
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsFavorited(!isFavorited)}
|
||||
className={`px-6 py-4 rounded-soft border-2 transition-colors ${
|
||||
className={`px-6 py-3 rounded-soft border transition-colors ${
|
||||
isFavorited
|
||||
? "bg-accent/20 border-accent text-background-accent"
|
||||
: "border-accent/30 text-foreground hover:border-accent"
|
||||
? "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>
|
||||
<button className="px-6 py-4 rounded-soft border-2 border-accent/30 text-foreground hover:border-accent transition-colors">
|
||||
<Share2 size={20} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="bg-card/30 border border-accent/20 rounded-soft p-6">
|
||||
<h3 className="text-lg font-semibold text-foreground mb-4">Product Details</h3>
|
||||
<div className="space-y-3">
|
||||
{product.specs.map((spec, idx) => (
|
||||
<div key={idx} className="flex justify-between text-foreground/70">
|
||||
<span>{spec.label}:</span>
|
||||
<span className="font-semibold text-foreground">{spec.value}</span>
|
||||
</div>
|
||||
))}
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user