hotschpotsh/Pottery-website/pages/ProductDetail.tsx

117 lines
5.7 KiB
TypeScript

import React from 'react';
import { useParams, Link } from 'react-router-dom';
import { motion } from 'framer-motion';
import { useStore } from '../src/context/StoreContext';
const ProductDetail: React.FC = () => {
const { slug } = useParams<{ slug: string }>();
const { products, addToCart } = useStore();
const product = products.find(item => item.slug === slug);
if (!product) {
return (
<div className="min-h-screen pt-32 flex flex-col items-center justify-center text-text-main dark:text-white">
<h2 className="text-4xl font-display mb-4">Product Not Found</h2>
<Link to="/collections" className="underline hover:text-stone-500">Return to Shop</Link>
</div>
);
}
return (
<div className="bg-white dark:bg-stone-950 min-h-screen pt-32 pb-24">
<div className="max-w-[1920px] mx-auto px-6 md:px-12">
{/* Breadcrumb */}
<div className="mb-12 text-sm uppercase tracking-widest text-stone-500">
<Link to="/collections" className="hover:text-text-main dark:hover:text-white transition-colors">Shop</Link>
<span className="mx-2">/</span>
<span className="text-text-main dark:text-white">{product.title}</span>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 xl:gap-24">
{/* Images Column */}
<div className="space-y-4">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="aspect-[4/5] w-full overflow-hidden bg-stone-100 rounded-sm"
>
<img
src={product.image}
alt={product.title}
className="w-full h-full object-cover"
/>
</motion.div>
{/* Additional images grid */}
<div className="grid grid-cols-2 gap-4">
{product.images?.slice(1).map((img, idx) => (
<motion.div
key={idx}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1 * (idx + 1) }}
className="aspect-square w-full overflow-hidden bg-stone-100 rounded-sm"
>
<img src={img} alt={`${product.title} detail ${idx + 1}`} className="w-full h-full object-cover" />
</motion.div>
))}
</div>
</div>
{/* Info Column */}
<div className="lg:sticky lg:top-32 h-fit">
<motion.h1
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
className="font-display text-5xl md:text-7xl font-light text-text-main dark:text-white mb-6"
>
{product.title}
</motion.h1>
<motion.p
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.1 }}
className="text-2xl font-light text-stone-600 dark:text-stone-300 mb-8"
>
${product.price}
</motion.p>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.2 }}
className="prose prose-stone dark:prose-invert max-w-none mb-12 font-light leading-relaxed text-lg"
>
<p>{product.description}</p>
<ul>
{product.details && product.details.map((detail, i) => (
<li key={i}>{detail}</li>
))}
<li>Made in Corpus Christi, TX</li>
</ul>
</motion.div>
<motion.button
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
onClick={() => addToCart(product)}
type="button"
className="w-full bg-text-main dark:bg-white text-white dark:text-text-main py-4 uppercase tracking-[0.2em] hover:bg-stone-800 dark:hover:bg-stone-200 transition-colors"
>
Add to Cart
</motion.button>
<div className="mt-12 pt-12 border-t border-stone-200 dark:border-stone-800 text-sm text-stone-500 font-light space-y-2">
<p>Free shipping on orders over $150</p>
<p>Ships within 3-5 business days</p>
</div>
</div>
</div>
</div>
</div>
);
};
export default ProductDetail;