import React, { useState, useMemo } from 'react';
import {
Leaf,
ShoppingBag,
Menu,
X,
ArrowRight,
Mail,
Share2,
Globe,
Sprout,
Sun,
Droplets,
ShieldCheck,
Plus,
Minus,
Trash2,
CheckCircle2,
Search,
Filter
} from 'lucide-react';
// --- Types ---
interface CartItem extends Product {
quantity: number;
}
interface Product {
id: string;
name: string;
price: number;
image: string;
category: string;
}
interface ToastMessage {
id: string;
text: string;
type: 'success' | 'error' | 'info';
}
// --- Mock Data ---
const PRODUCTS: Product[] = [
{ id: '1', name: 'Heirloom Tomato Mix', price: 12.00, category: 'Vegetables', image: 'https://images.unsplash.com/photo-1592841200221-a6898f307baa?auto=format&fit=crop&q=80&w=800' },
{ id: '2', name: 'Wildflower Meadow', price: 15.00, category: 'Flowers', image: 'https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?auto=format&fit=crop&q=80&w=800' },
{ id: '3', name: 'Kitchen Herb Kit', price: 18.00, category: 'Herbs', image: 'https://images.unsplash.com/photo-1515586641520-23043046030e?auto=format&fit=crop&q=80&w=800' },
{ id: '4', name: 'Rainbow Carrots', price: 10.00, category: 'Vegetables', image: 'https://images.unsplash.com/photo-1598170845058-329d9a6da5da37?auto=format&fit=crop&q=80&w=800' },
{ id: '5', name: 'Lavender Fields', price: 14.00, category: 'Flowers', image: 'https://images.unsplash.com/photo-1495908333425-24d4ca6a2c7a?auto=format&fit=crop&q=80&w=800' },
{ id: '6', name: 'Basil & Mint Duo', price: 12.00, category: 'Herbs', image: 'https://images.unsplash.com/photo-1618375508804-79203046030e?auto=format&fit=crop&q=80&w=800' },
];
const CATEGORIES = ['All', 'Vegetables', 'Flowers', 'Herbs'];
// --- Components ---
const Toast = ({ message, onRemove }: { message: ToastMessage, onRemove: (id: string) => void }) => {
const colors = {
success: 'bg-heritage-green text-heritage-cream',
error: 'bg-red-500 text-white',
info: 'bg-heritage-clay text-heritage-cream'
};
return (
<div className={`fixed bottom-8 right-8 z-[100] flex items-center gap-3 px-6 py-4 rounded-xl shadow-2xl animate-in slide-in-from-right duration-300 ${colors[message.type]}`}>
{message.type === 'success' && <CheckCircle2 className="w-5 h-5" />}
<span className="font-bold">{message.text}</span>
<button onClick={() => onRemove(message.id)} className="ml-2 hover:opacity-70 transition-opacity">
<X className="w-4 h-4" />
</button>
</div>
);
};
const Navbar = ({ cartCount, onOpenCart, searchQuery, setSearchQuery }: {
cartCount: number,
onOpenCart: () => void,
searchQuery: string,
setSearchQuery: (q: string) => void
}) => {
const [isOpen, setIsOpen] = React.useState(false);
return (
<nav className="bg-heritage-stone/80 backdrop-blur-md sticky top-0 z-50 border-b border-heritage-green/10">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-20 items-center">
<div className="flex items-center gap-2">
<Leaf className="text-heritage-green w-8 h-8" />
<span className="text-2xl font-bold tracking-tight text-heritage-green font-serif">SeedVault</span>
</div>
<div className="hidden md:flex items-center space-x-6">
<div className="relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-heritage-green/40" />
<input
type="text"
placeholder="Search seeds..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10 pr-4 py-2 bg-heritage-cream/50 border border-heritage-green/10 rounded-full text-sm focus:outline-none focus:ring-2 focus:ring-heritage-green/20 w-48 lg:w-64 transition-all"
/>
</div>
<div className="flex items-center space-x-4">
<a href="#" className="text-heritage-green/80 hover:text-heritage-green font-medium transition-colors">Shop</a>
<a href="#" className="text-heritage-green/80 hover:text-heritage-green font-medium transition-colors">Guides</a>
<button
onClick={onOpenCart}
className="relative p-2 text-heritage-green hover:bg-heritage-green/5 rounded-full transition-colors"
>
<ShoppingBag className="w-6 h-6" />
{cartCount > 0 && (
<span className="absolute top-0 right-0 bg-heritage-clay text-heritage-cream text-[10px] font-bold w-5 h-5 flex items-center justify-center rounded-full border-2 border-heritage-stone">
{cartCount}
</span>
)}
</button>
</div>
</div>
<div className="md:hidden flex items-center gap-4">
<button onClick={onOpenCart} className="relative text-heritage-green p-2">
<ShoppingBag className="w-6 h-6" />
{cartCount > 0 && (
<span className="absolute top-0 right-0 bg-heritage-clay text-heritage-cream text-[10px] font-bold w-5 h-5 flex items-center justify-center rounded-full border-2 border-heritage-stone">
{cartCount}
</span>
)}
</button>
<button onClick={() => setIsOpen(!isOpen)} className="text-heritage-green p-2">
{isOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
</button>
</div>
</div>
</div>
{/* Mobile Menu */}
{isOpen && (
<div className="md:hidden bg-heritage-stone border-b border-heritage-green/10 animate-in slide-in-from-top duration-300">
<div className="px-4 pt-2 pb-6 space-y-4">
<div className="relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-heritage-green/40" />
<input
type="text"
placeholder="Search seeds..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full pl-10 pr-4 py-3 bg-heritage-cream/50 border border-heritage-green/10 rounded-lg text-sm focus:outline-none"
/>
</div>
<div className="flex flex-col space-y-2">
<a href="#" className="px-3 py-2 text-lg font-medium text-heritage-green">Shop All</a>
<a href="#" className="px-3 py-2 text-lg font-medium text-heritage-green">Vegetables</a>
<a href="#" className="px-3 py-2 text-lg font-medium text-heritage-green">Flowers</a>
<a href="#" className="px-3 py-2 text-lg font-medium text-heritage-green">Growing Guides</a>
</div>
</div>
</div>
)}
</nav>
);
};
const CartDrawer = ({
isOpen,
onClose,
cart,
onUpdateQuantity,
onRemove,
onClear,
onCheckout
}: {
isOpen: boolean,
onClose: () => void,
cart: CartItem[],
onUpdateQuantity: (id: string, delta: number) => void,
onRemove: (id: string) => void,
onClear: () => void,
onCheckout: () => void
}) => {
const total = useMemo(() => cart.reduce((sum, item) => sum + (item.price * item.quantity), 0), [cart]);
return (
<>
{isOpen && <div className="fixed inset-0 bg-black/40 backdrop-blur-sm z-[60]" onClick={onClose} />}
<div className={`fixed top-0 right-0 h-full w-full max-w-md bg-white z-[70] shadow-2xl transform transition-transform duration-300 ease-in-out ${isOpen ? 'translate-x-0' : 'translate-x-full'}`}>
<div className="flex flex-col h-full">
<div className="p-6 border-b border-heritage-green/10 flex justify-between items-center">
<h2 className="text-2xl font-bold text-heritage-green font-serif">Your Cart</h2>
<button onClick={onClose} className="p-2 text-heritage-green hover:bg-heritage-green/5 rounded-full transition-colors">
<X className="w-6 h-6" />
</button>
</div>
<div className="flex-1 overflow-y-auto p-6">
{cart.length === 0 ? (
<div className="h-full flex flex-col items-center justify-center text-center">
<ShoppingBag className="w-16 h-16 text-heritage-green/20 mb-4" />
<p className="text-heritage-green/60 text-lg">Your cart is empty</p>
<button onClick={onClose} className="mt-6 text-heritage-green font-bold hover:underline">Start Shopping</button>
</div>
) : (
<div className="space-y-6">
{cart.map((item) => (
<div key={item.id} className="flex gap-4">
<img src={item.image} alt={item.name} className="w-20 h-20 object-cover rounded-lg" />
<div className="flex-1">
<h3 className="font-bold text-heritage-green">{item.name}</h3>
<p className="text-heritage-clay text-sm">${item.price.toFixed(2)}</p>
<div className="flex items-center justify-between mt-2">
<div className="flex items-center border border-heritage-green/10 rounded-lg">
<button onClick={() => onUpdateQuantity(item.id, -1)} className="p-1 text-heritage-green hover:bg-heritage-green/5"><Minus className="w-4 h-4" /></button>
<span className="px-3 text-sm font-medium text-heritage-green">{item.quantity}</span>
<button onClick={() => onUpdateQuantity(item.id, 1)} className="p-1 text-heritage-green hover:bg-heritage-green/5"><Plus className="w-4 h-4" /></button>
</div>
<button onClick={() => onRemove(item.id)} className="text-heritage-clay hover:text-red-500 transition-colors"><Trash2 className="w-4 h-4" /></button>
</div>
</div>
</div>
))}
</div>
)}
</div>
{cart.length > 0 && (
<div className="p-6 border-t border-heritage-green/10 bg-heritage-cream/30">
<div className="flex justify-between items-center mb-4">
<span className="text-heritage-green/60 font-medium">Subtotal</span>
<span className="text-2xl font-bold text-heritage-green">${total.toFixed(2)}</span>
</div>
<div className="grid grid-cols-2 gap-4">
<button onClick={() => { onClear(); onClose(); }} className="py-3 px-4 border border-heritage-green/20 text-heritage-green font-bold rounded-lg hover:bg-heritage-green/5 transition-all">Clear Cart</button>
<button onClick={onCheckout} className="py-3 px-4 bg-heritage-green text-heritage-cream font-bold rounded-lg hover:bg-heritage-green/90 transition-all shadow-lg">Checkout</button>
</div>
</div>
)}
</div>
</div>
</>
);
};
const Hero = () => (
<section className="relative overflow-hidden bg-heritage-green py-24 lg:py-32">
<div className="absolute inset-0 opacity-20">
<img src="https://images.unsplash.com/photo-1466692476868-aef1dfb1e735?auto=format&fit=crop&q=80&w=2070" alt="Background" className="w-full h-full object-cover" />
</div>
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<span className="inline-block px-4 py-1.5 mb-6 text-sm font-semibold tracking-wider text-heritage-cream uppercase bg-heritage-clay/30 rounded-full">Preserving Biodiversity</span>
<h1 className="text-5xl md:text-7xl font-bold text-heritage-cream mb-8 leading-tight">Heirloom Quality <br /><span className="italic font-serif">for the Future.</span></h1>
<p className="text-xl text-heritage-cream/80 max-w-2xl mx-auto mb-10 leading-relaxed">Discover a curated collection of non-GMO, heirloom seeds hand-selected for resilience, taste, and biodiversity.</p>
<div className="flex flex-col sm:flex-row justify-center gap-4">
<button className="px-8 py-4 bg-heritage-cream text-heritage-green font-bold rounded-lg hover:bg-white transition-all flex items-center justify-center gap-2 shadow-lg">Shop All Seeds <ArrowRight className="w-5 h-5" /></button>
<button className="px-8 py-4 bg-transparent border-2 border-heritage-cream text-heritage-cream font-bold rounded-lg hover:bg-heritage-cream/10 transition-all">Our Story</button>
</div>
</div>
</section>
);
const ProductCard = ({ product, onAddToCart }: { product: Product, onAddToCart: (p: Product) => void }) => (
<div className="group bg-white rounded-2xl overflow-hidden shadow-sm hover:shadow-xl transition-all duration-300 border border-heritage-green/5">
<div className="relative aspect-[4/5] overflow-hidden">
<img src={product.image} alt={product.name} className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110" />
<div className="absolute top-4 left-4">
<span className="px-3 py-1 bg-white/90 backdrop-blur text-heritage-green text-xs font-bold rounded-full uppercase tracking-wider">{product.category}</span>
</div>
</div>
<div className="p-6">
<h3 className="text-xl font-bold text-heritage-green mb-1">{product.name}</h3>
<p className="text-heritage-clay font-semibold text-lg">${product.price.toFixed(2)}</p>
<button onClick={() => onAddToCart(product)} className="mt-4 w-full py-3 bg-heritage-green text-heritage-cream font-bold rounded-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center gap-2">
<ShoppingBag className="w-5 h-5" /> Add to Cart
</button>
</div>
</div>
);
const Features = () => (
<section className="py-24 bg-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-12">
{[
{ icon: <Sprout className="w-8 h-8" />, title: "Non-GMO", desc: "Pure, unadulterated genetics for your garden." },
{ icon: <Sun className="w-8 h-8" />, title: "Resilient", desc: "Varieties selected for climate adaptability." },
{ icon: <Droplets className="w-8 h-8" />, title: "Water Efficient", desc: "Optimized for sustainable water usage." },
{ icon: <ShieldCheck className="w-8 h-8" />, title: "Tested", desc: "Every batch is verified for germination." },
].map((feature, i) => (
<div key={i} className="text-center">
<div className="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-heritage-cream text-heritage-green mb-6">{feature.icon}</div>
<h3 className="text-xl font-bold text-heritage-green mb-3">{feature.title}</h3>
<p className="text-heritage-green/60 leading-relaxed">{feature.desc}</p>
</div>
))}
</div>
</div>
</section>
);
const Newsletter = () => (
<section className="py-24 bg-heritage-green relative overflow-hidden">
<div className="absolute top-0 left-0 w-full h-full opacity-10 pointer-events-none">
<div className="absolute top-[-10%] left-[-10%] w-[40%] h-[40%] rounded-full bg-heritage-cream blur-[120px]" />
<div className="absolute bottom-[-10%] right-[-10%] w-[40%] h-[40%] rounded-full bg-heritage-cream blur-[120px]" />
</div>
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
<Mail className="w-12 h-12 text-heritage-cream mx-auto mb-6 opacity-50" />
<h2 className="text-4xl font-bold text-heritage-cream mb-4">Join the Seed Club</h2>
<p className="text-heritage-cream/70 text-lg mb-10">Get seasonal planting alerts, exclusive heirloom releases, and expert growing guides delivered to your inbox.</p>
<form className="flex flex-col sm:flex-row gap-4 max-w-lg mx-auto" onSubmit={(e) => e.preventDefault()}>
<input type="email" placeholder="Enter your email" className="flex-1 px-6 py-4 rounded-lg bg-white/10 border border-white/20 text-heritage-cream placeholder:text-white/40 focus:outline-none focus:ring-2 focus:ring-heritage-cream/50" />
<button className="px-8 py-4 bg-heritage-cream text-heritage-green font-bold rounded-lg hover:bg-white transition-all">Subscribe</button>
</form>
</div>
</section>
);
const Footer = () => (
<footer className="bg-heritage-stone py-16 border-t border-heritage-green/10">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 md:grid-cols-4 gap-12 mb-12">
<div className="col-span-1 md:col-span-1">
<div className="flex items-center gap-2 mb-6">
<Leaf className="text-heritage-green w-6 h-6" />
<span className="text-xl font-bold text-heritage-green font-serif">SeedVault</span >
</div>
<p className="text-heritage-green/60 leading-relaxed">Empowering food sovereignty through heirloom biodiversity and sustainable practices.</p>
</div>
<div>
<h4 className="text-heritage-green font-bold mb-6 uppercase tracking-wider text-sm">Shop</h4>
<ul className="space-y-4 text-heritage-green/70">
<li><a href="#" className="hover:text-heritage-green transition-colors">All Seeds</a></li>
<li><a href="#" className="hover:text-heritage-green transition-colors">Vegetables</a></li>
<li><a href="#" className="hover:text-heritage-green transition-colors">Flowers</a></li>
<li><a href="#" className="hover:text-heritage-green transition-colors">Herbs</a></li>
</ul>
</div>
<div>
<h4 className="text-heritage-green font-bold mb-6 uppercase tracking-wider text-sm">Support</h4>
<ul className="space-y-4 text-heritage-green/70">
<li><a href="#" className="hover:text-heritage-green transition-colors">Growing Guides</a></li>
<li><a href="#" className="hover:text-heritage-green transition-colors">Shipping Policy</a></li>
<li><a href="#" className="hover:text-heritage-green transition-colors">Contact Us</a></li>
</ul>
</div>
<div>
<h4 className="text-heritage-green font-bold mb-6 uppercase tracking-wider text-sm">Follow Us</h4>
<div className="flex space-x-4">
<a href="#" className="p-2 bg-heritage-green/5 rounded-full text-heritage-green hover:bg-heritage-green hover:text-heritage-cream transition-all"><Share2 className="w-5 h-5" /></a>
<a href="#" className="p-2 bg-heritage-green/5 rounded-full text-heritage-green hover:bg-heritage-green hover:text-heritage-cream transition-all"><Globe className="w-5 h-5" /></a>
<a href="#" className="p-2 bg-heritage-green/5 rounded-full text-heritage-green hover:bg-heritage-green hover:text-heritage-cream transition-all"><Mail className="w-5 h-5" /></a>
</div>
</div>
</div>
<div className="pt-8 border-t border-heritage-green/10 text-center text-heritage-green/40 text-sm">
<p>© 2026 SeedVault. All rights reserved. Built for food sovereignty.</p>
</div>
</div>
</footer>
);
const App = () => {
const [cart, setCart] = useState<CartItem[]>([]);
const [isCartOpen, setIsCartOpen] = useState(false);
const [isCheckoutSuccess, setIsCheckoutSuccess] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
const [selectedCategory, setSelectedCategory] = useState('All');
const [toasts, setToasts] = useState<ToastMessage[]>([]);
const addToast = (text: string, type: 'success' | 'error' | 'info' = 'success') => {
const id = Math.random().toString(36).substring(2, 9);
setToasts(prev => [...prev, { id, text, type }]);
setTimeout(() => removeToast(id), 3000);
};
const removeToast = (id: string) => {
setToasts(prev => prev.filter(t => t.id !== id));
};
const addToCart = (product: Product) => {
setCart(prev => {
const existing = prev.find(item => item.id === product.id);
if (existing) {
return prev.map(item => item.id === product.id ? { ...item, quantity: item.quantity + 1 } : item);
}
return [...prev, { ...product, quantity: 1 }];
});
addToast(`Added ${product.name} to cart!`);
};
const updateQuantity = (id: string, delta: number) => {
setCart(prev => prev.map(item => {
if (item.id === id) {
const newQty = Math.max(1, item.quantity + delta);
return { ...item, quantity: newQty };
}
return item;
}));
};
const removeFromCart = (id: string) => {
const item = cart.find(i => i.id === id);
if (item) addToast(`Removed ${item.name} from cart`, 'info');
setCart(prev => prev.filter(item => item.id !== id));
};
const clearCart = () => {
if (cart.length > 0) addToast('Cart cleared', 'info');
setCart([]);
};
const handleCheckout = () => {
setIsCheckoutSuccess(true);
setCart([]);
addToast('Order placed successfully!', 'success');
setTimeout(() => setIsCheckoutSuccess(false), 3000);
};
const filteredProducts = useMemo(() => {
return PRODUCTS.filter(p => {
const matchesSearch = p.name.toLowerCase().includes(searchQuery.toLowerCase());
const matchesCategory = selectedCategory === 'All' || p.category === selectedCategory;
return matchesSearch && matchesCategory;
});
}, [searchQuery, selectedCategory]);
return (
<div className="min-h-screen selection:bg-heritage-clay/30 selection:text-heritage-clay">
<Navbar
cartCount={cart.reduce((sum, item) => sum + item.quantity, 0)}
onOpenCart={() => setIsCartOpen(true)}
searchQuery={searchQuery}
setSearchQuery={setSearchQuery}
/>
<main>
<Hero />
<Features />
<section className="py-24 bg-heritage-cream">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex flex-col md:flex-row md:items-center justify-between mb-12 gap-6">
<div>
<h2 className="text-4xl font-bold text-heritage-green mb-4">Our Collection</h2>
<p className="text-heritage-green/60 text-lg">Find the perfect seeds for your garden.</p>
</div>
<div className="flex items-center gap-2 overflow-x-auto pb-2 md:pb-0">
<Filter className="w-5 h-5 text-heritage-green/40 mr-2" />
{CATEGORIES.map(cat => (
<button
key={cat}
onClick={() => setSelectedCategory(cat)}
className={`px-4 py-2 rounded-full text-sm font-medium transition-all whitespace-nowrap ${
selectedCategory === cat
? 'bg-heritage-green text-heritage-cream shadow-md'
: 'bg-white text-heritage-green/70 hover:bg-heritage-green/5'
}`}
>
{cat}
</button>
))}
</div>
</div>
{filteredProducts.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
{filteredProducts.map(product => (
<ProductCard key={product.id} product={product} onAddToCart={addToCart} />
))}
</div>
) : (
<div className="py-20 text-center">
<Search className="w-16 h-16 text-heritage-green/10 mx-auto mb-4" />
<p className="text-heritage-green/60 text-xl">No seeds found matching your search.</p>
</div>
)}
</div>
</section>
<Newsletter />
</main>
<Footer />
<CartDrawer
isOpen={isCartOpen}
onClose={() => setIsCartOpen(false)}
cart={cart}
onUpdateQuantity={updateQuantity}
onRemove={removeFromCart}
onClear={clearCart}
onCheckout={handleCheckout}
/>
{toasts.map(toast => (
<Toast key={toast.id} message={toast} onRemove={removeToast} />
))}
{isCheckoutSuccess && (
<div className="fixed inset-0 z-[110] flex items-center justify-center bg-heritage-green/20 backdrop-blur-sm">
<div className="bg-white p-8 rounded-2xl shadow-2xl text-center max-w-sm animate-in zoom-in duration-300">
<CheckCircle2 className="w-16 h-16 text-heritage-green mx-auto mb-4" />
<h2 className="text-2xl font-bold text-heritage-green mb-2">Thank You!</h2>
<p className="text-heritage-clay mb-6">Your order has been placed. We'll send a confirmation email shortly.</p>
<button onClick={() => setIsCheckoutSuccess(false)} className="w-full py-3 bg-heritage-green text-heritage-cream font-bold rounded-lg">Continue Shopping</button>
</div>
</div>
)}
</div>
);
};
export default App;