Seed: ecommerce template (24 files)
This commit is contained in:
@@ -0,0 +1,318 @@
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import {
|
||||
Truck, RotateCcw, ShieldCheck, Star, ArrowRight, Heart,
|
||||
ChevronRight, Mail, Sparkles, Check
|
||||
} from "lucide-react";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import { useSaasMutation } from "@/hooks/use-tygarun";
|
||||
|
||||
const featuredProducts = [
|
||||
{ id: 1, name: "Classic Leather Jacket", price: 189, originalPrice: 249, rating: 5, sale: true, gradient: "from-rose-100 to-stone-200", image: "" },
|
||||
{ id: 2, name: "Silk Evening Dress", price: 245, originalPrice: null, rating: 5, sale: false, gradient: "from-amber-100 to-orange-200", image: "" },
|
||||
{ id: 3, name: "Cashmere Knit Sweater", price: 128, originalPrice: null, rating: 4, sale: false, gradient: "from-stone-100 to-stone-300", image: "" },
|
||||
{ id: 4, name: "Linen Wide-Leg Trousers", price: 95, originalPrice: 135, rating: 4, sale: true, gradient: "from-rose-50 to-amber-100", image: "" },
|
||||
{ id: 5, name: "Italian Leather Handbag", price: 320, originalPrice: null, rating: 5, sale: false, gradient: "from-stone-200 to-rose-100", image: "" },
|
||||
{ id: 6, name: "Merino Wool Blazer", price: 165, originalPrice: null, rating: 4, sale: false, gradient: "from-amber-50 to-stone-200", image: "" },
|
||||
];
|
||||
|
||||
const categories = [
|
||||
{ name: "Women", gradient: "from-stone-700 to-stone-900", count: 124 },
|
||||
{ name: "Men", gradient: "from-rose-700 to-rose-900", count: 86 },
|
||||
{ name: "Accessories", gradient: "from-amber-700 to-amber-900", count: 53 },
|
||||
{ name: "Footwear", gradient: "from-stone-600 to-rose-800", count: 97 },
|
||||
];
|
||||
|
||||
export default function IndexPage() {
|
||||
const [email, setEmail] = useState("");
|
||||
const [subscribed, setSubscribed] = useState(false);
|
||||
const { mutate: subscribeNewsletter, loading: subscribing } = useSaasMutation("email", "/send/newsletter-confirm");
|
||||
|
||||
const handleSubscribe = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!email) return;
|
||||
try {
|
||||
await subscribeNewsletter({ email });
|
||||
setSubscribed(true);
|
||||
toast.success("Subscribed!");
|
||||
} catch {
|
||||
toast.error("Could not subscribe. Please try again.");
|
||||
}
|
||||
};
|
||||
|
||||
const renderStars = (count: number) =>
|
||||
Array.from({ length: 5 }, (_, i) => (
|
||||
<Star key={i} className={`h-3.5 w-3.5 \${i < count ? "fill-amber-400 text-amber-400" : "text-stone-300"}`} />
|
||||
));
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white text-stone-900 antialiased">
|
||||
<Header />
|
||||
|
||||
{/* ── HERO ── */}
|
||||
<section className="relative overflow-hidden bg-gradient-to-br from-rose-50 via-white to-amber-50 pt-28 pb-20 sm:pt-36 sm:pb-28">
|
||||
{/* Floating gradient blurs */}
|
||||
<div className="absolute top-10 left-1/4 h-72 w-72 rounded-full bg-rose-300 opacity-20 blur-[100px]" />
|
||||
<div className="absolute bottom-10 right-1/4 h-64 w-64 rounded-full bg-amber-300 opacity-20 blur-[100px]" />
|
||||
<div className="absolute top-1/2 left-10 h-56 w-56 rounded-full bg-violet-300 opacity-20 blur-[100px]" />
|
||||
<div className="absolute bottom-1/3 right-10 h-48 w-48 rounded-full bg-sky-300 opacity-20 blur-[100px]" />
|
||||
{/* Dot grid pattern overlay */}
|
||||
<div className="absolute inset-0" style={{ backgroundImage: "radial-gradient(circle, rgba(255,255,255,0.5) 1px, transparent 1px)", backgroundSize: "32px 32px" }} />
|
||||
<div className="mx-auto max-w-7xl px-6 grid lg:grid-cols-2 gap-12 items-center relative">
|
||||
<div className="text-center lg:text-left">
|
||||
<Badge className="mb-6 bg-rose-100 text-rose-700 hover:bg-rose-100 border-0 px-4 py-1.5 text-sm font-medium animate-fade-in">
|
||||
<Sparkles className="mr-1.5 h-3.5 w-3.5" /> Summer Sale:Up to 40% Off
|
||||
</Badge>
|
||||
<h1 className="mx-auto lg:mx-0 max-w-4xl text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl">
|
||||
<span className="block animate-fade-up">Elevate Your Everyday Style</span>
|
||||
</h1>
|
||||
<p className="mx-auto lg:mx-0 mt-6 max-w-2xl text-lg text-stone-500 animate-fade-up [animation-delay:100ms]">
|
||||
Discover curated collections of premium fashion, accessories, and lifestyle essentials crafted for the modern individual.
|
||||
</p>
|
||||
<div className="mt-10 flex flex-col sm:flex-row items-center lg:justify-start justify-center gap-4 animate-fade-up [animation-delay:200ms]">
|
||||
<Button asChild size="lg" className="bg-stone-900 hover:bg-stone-800 text-white px-8 rounded-full active:scale-[0.98] transition-all">
|
||||
<Link to="/products">Shop Collection <ArrowRight className="ml-2 h-4 w-4" /></Link>
|
||||
</Button>
|
||||
<Button asChild variant="outline" size="lg" className="rounded-full border-stone-300 active:scale-[0.98] transition-all">
|
||||
<Link to="/products">New Arrivals</Link>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-12 flex flex-wrap lg:justify-start justify-center gap-8 text-sm text-stone-500 animate-fade-in [animation-delay:400ms]">
|
||||
<span className="flex items-center gap-2"><Truck className="h-4 w-4 text-rose-500" /> Free Shipping Over $100</span>
|
||||
<span className="flex items-center gap-2"><RotateCcw className="h-4 w-4 text-rose-500" /> 30-Day Returns</span>
|
||||
<span className="flex items-center gap-2"><ShieldCheck className="h-4 w-4 text-rose-500" /> Secure Checkout</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* Featured product card floating on right */}
|
||||
<div className="hidden lg:flex justify-center animate-fade-up [animation-delay:300ms]">
|
||||
<Card className="w-72 overflow-hidden border-0 shadow-2xl hover:shadow-3xl transition-shadow duration-500 rotate-2 hover:rotate-0">
|
||||
<div className="aspect-[3/4] bg-gradient-to-br from-rose-100 to-amber-100 relative overflow-hidden">
|
||||
<div className="absolute inset-0" style={{ backgroundImage: "radial-gradient(circle, rgba(0,0,0,0.06) 1px, transparent 1px)", backgroundSize: "16px 16px" }} />
|
||||
<div className="absolute top-1/4 -left-8 h-24 w-24 rounded-full bg-white/30 blur-2xl" />
|
||||
<div className="absolute bottom-1/4 -right-8 h-20 w-20 rounded-full bg-white/20 blur-2xl" />
|
||||
<div className="absolute inset-0 flex items-center justify-center text-stone-400 text-sm">Featured</div>
|
||||
<Badge className="absolute top-3 left-3 bg-rose-500 text-white border-0">Trending</Badge>
|
||||
</div>
|
||||
<CardContent className="p-4">
|
||||
<h3 className="font-semibold text-stone-900">{featuredProducts[0].name}</h3>
|
||||
<p className="text-lg font-bold mt-1 text-stone-900">\${featuredProducts[0].price}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FEATURED PRODUCTS ── */}
|
||||
<section className="py-24 bg-white">
|
||||
<div className="mx-auto max-w-7xl px-6">
|
||||
<div className="flex items-end justify-between mb-10">
|
||||
<div>
|
||||
<h2 className="text-3xl font-bold tracking-tight animate-fade-up">Featured Collection</h2>
|
||||
<p className="mt-2 text-stone-500 animate-fade-up [animation-delay:100ms]">Handpicked pieces for the season</p>
|
||||
</div>
|
||||
<Link to="/products" className="hidden sm:flex items-center text-sm font-medium text-rose-600 hover:text-rose-700">
|
||||
View All <ChevronRight className="ml-1 h-4 w-4" />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-6 stagger">
|
||||
{featuredProducts.map((product, i) => (
|
||||
<Link to="/product" key={product.id} className="group">
|
||||
<Card className="overflow-hidden border-0 shadow-sm hover:shadow-xl hover:-translate-y-1 transition-all duration-300">
|
||||
<div className={`relative aspect-[3/4] bg-gradient-to-br \${product.gradient} animate-scale-in overflow-hidden`}>
|
||||
<div className="absolute inset-0 transition-transform duration-300 group-hover:scale-110 group-hover:brightness-110" style={{ backgroundImage: "radial-gradient(circle, rgba(0,0,0,0.06) 1px, transparent 1px)", backgroundSize: "16px 16px" }} />
|
||||
<div className="absolute top-1/4 -left-8 h-24 w-24 rounded-full bg-white/30 blur-2xl" />
|
||||
<div className="absolute bottom-1/4 -right-8 h-20 w-20 rounded-full bg-white/20 blur-2xl" />
|
||||
<div className="absolute inset-0 flex items-center justify-center text-stone-400 text-sm transition-transform duration-300 group-hover:scale-110 group-hover:brightness-110">
|
||||
Product Image
|
||||
</div>
|
||||
{product.sale && (
|
||||
<Badge className="absolute top-3 left-3 bg-rose-500 text-white border-0">Sale</Badge>
|
||||
)}
|
||||
<button className="absolute top-3 right-3 h-8 w-8 rounded-full bg-white/80 backdrop-blur-sm flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity hover:bg-white hover:scale-125 active:scale-90 transition-transform">
|
||||
<Heart className="h-4 w-4 text-stone-600" />
|
||||
</button>
|
||||
<div className="absolute bottom-0 left-0 right-0 translate-y-full group-hover:translate-y-0 transition-transform duration-300 p-3"><Button className="w-full" size="sm">Quick Add</Button></div>
|
||||
</div>
|
||||
<CardContent className="p-4">
|
||||
<h3 className="font-medium text-sm text-stone-900 group-hover:text-rose-600 transition-colors">{product.name}</h3>
|
||||
<div className="flex gap-1 mt-1 opacity-0 group-hover:opacity-100 transition-opacity"><span className="w-3 h-3 rounded-full bg-stone-900" /><span className="w-3 h-3 rounded-full bg-rose-400" /><span className="w-3 h-3 rounded-full bg-amber-200" /></div>
|
||||
<div className="flex items-center gap-1 mt-1">{renderStars(product.rating)}</div>
|
||||
<div className="mt-2 flex items-center gap-2">
|
||||
<span className="font-semibold text-stone-900">\${product.price}</span>
|
||||
{product.originalPrice && (
|
||||
<span className="text-sm text-stone-400 line-through">\${product.originalPrice}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1 mt-1"><div className="flex">{[...Array(5)].map((_, j) => <Star key={j} className="h-3 w-3 fill-amber-400 text-amber-400" />)}</div><span className="text-xs text-muted-foreground">(128)</span></div>
|
||||
{i < 2 && <span className="text-xs text-amber-600 font-medium">Only 3 left</span>}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-8 text-center sm:hidden">
|
||||
<Button asChild variant="outline" className="rounded-full">
|
||||
<Link to="/products">View All Products</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── CATEGORIES ── */}
|
||||
<section className="py-24 bg-stone-50">
|
||||
<div className="mx-auto max-w-7xl px-6">
|
||||
<h2 className="text-3xl font-bold tracking-tight text-center mb-12 animate-fade-up">Shop by Category</h2>
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 stagger">
|
||||
{categories.map((cat) => (
|
||||
<Link to="/products" key={cat.name} className="group relative overflow-hidden rounded-2xl aspect-[4/5] hover:-translate-y-1 hover:shadow-xl transition-all duration-300">
|
||||
<div className={`absolute inset-0 bg-gradient-to-br \${cat.gradient}`} />
|
||||
<div className="absolute inset-0 bg-black/20 group-hover:bg-black/40 transition-colors" />
|
||||
<div className="relative h-full flex flex-col justify-end p-6 text-white">
|
||||
<h3 className="text-xl font-bold">{cat.name}</h3>
|
||||
<p className="text-sm text-white/70 mt-1">{cat.count} items</p>
|
||||
<span className="mt-3 text-sm font-medium flex items-center gap-1 group-hover:gap-2 transition-all">
|
||||
Shop Now <ArrowRight className="h-4 w-4" />
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── TRUST BAR ── */}
|
||||
<section className="py-24 bg-white border-y border-stone-100">
|
||||
<div className="mx-auto max-w-7xl px-6 grid grid-cols-2 md:grid-cols-4 gap-8 text-center stagger">
|
||||
{[
|
||||
{ icon: Truck, title: "Free Shipping", desc: "On orders over $100" },
|
||||
{ icon: RotateCcw, title: "Easy Returns", desc: "30-day return policy" },
|
||||
{ icon: ShieldCheck, title: "Secure Payment", desc: "SSL encrypted checkout" },
|
||||
{ icon: Sparkles, title: "Premium Quality", desc: "Handpicked materials" },
|
||||
].map((item) => (
|
||||
<div key={item.title} className="flex flex-col items-center gap-3 animate-fade-in">
|
||||
<div className="h-12 w-12 rounded-full bg-rose-50 flex items-center justify-center">
|
||||
<item.icon className="h-5 w-5 text-rose-600" />
|
||||
</div>
|
||||
<h3 className="font-semibold text-sm">{item.title}</h3>
|
||||
<p className="text-xs text-stone-500">{item.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── THE COLLECTION LOOKBOOK ── */}
|
||||
<section className="py-24">
|
||||
<div className="mx-auto max-w-7xl px-6">
|
||||
<h2 className="text-3xl font-bold tracking-tight mb-12 animate-fade-up">The Collection</h2>
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div className="col-span-2 row-span-2 relative group overflow-hidden rounded-2xl">
|
||||
<div className="aspect-square bg-gradient-to-br from-stone-800 to-rose-900 transition-transform duration-700 group-hover:scale-105" />
|
||||
<div className="absolute inset-0 bg-black/20 group-hover:bg-black/40 transition-colors flex items-end p-8">
|
||||
<div>
|
||||
<Badge className="bg-white/20 backdrop-blur text-white border-0 mb-2">New Season</Badge>
|
||||
<h3 className="text-2xl font-bold text-white">Spring Essentials</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative group overflow-hidden rounded-2xl">
|
||||
<div className="aspect-square bg-gradient-to-br from-amber-600 to-amber-800 transition-transform duration-700 group-hover:scale-105" />
|
||||
<div className="absolute inset-0 bg-black/20 group-hover:bg-black/40 transition-colors flex items-end p-6">
|
||||
<div>
|
||||
<Badge className="bg-white/20 backdrop-blur text-white border-0 mb-2">Trending</Badge>
|
||||
<h3 className="text-lg font-bold text-white">Accessories</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative group overflow-hidden rounded-2xl">
|
||||
<div className="aspect-square bg-gradient-to-br from-rose-600 to-stone-700 transition-transform duration-700 group-hover:scale-105" />
|
||||
<div className="absolute inset-0 bg-black/20 group-hover:bg-black/40 transition-colors flex items-end p-6">
|
||||
<div>
|
||||
<Badge className="bg-white/20 backdrop-blur text-white border-0 mb-2">Popular</Badge>
|
||||
<h3 className="text-lg font-bold text-white">Best Sellers</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative group overflow-hidden rounded-2xl">
|
||||
<div className="aspect-square bg-gradient-to-br from-violet-700 to-stone-900 transition-transform duration-700 group-hover:scale-105" />
|
||||
<div className="absolute inset-0 bg-black/20 group-hover:bg-black/40 transition-colors flex items-end p-6">
|
||||
<div>
|
||||
<Badge className="bg-white/20 backdrop-blur text-white border-0 mb-2">Exclusive</Badge>
|
||||
<h3 className="text-lg font-bold text-white">Limited Edition</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── BRAND STORY ── */}
|
||||
<section className="py-24 bg-muted/30">
|
||||
<div className="mx-auto max-w-4xl px-6 text-center">
|
||||
<p className="text-sm uppercase tracking-widest text-muted-foreground mb-4 animate-fade-up">Our Story</p>
|
||||
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight mb-6 animate-fade-up">Crafted with Care Since 2020</h2>
|
||||
<p className="text-lg text-muted-foreground leading-relaxed mb-8">Every piece in our collection is thoughtfully designed and ethically sourced. We believe in quality over quantity, creating timeless pieces that tell a story.</p>
|
||||
<Button variant="outline" className="rounded-full">Learn More <ArrowRight className="ml-2 h-4 w-4" /></Button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── NEWSLETTER ── */}
|
||||
<section className="py-24 bg-gradient-to-br from-stone-900 to-stone-800 text-white">
|
||||
<div className="mx-auto max-w-2xl px-6 text-center">
|
||||
<Mail className="mx-auto h-10 w-10 text-rose-400 mb-6" />
|
||||
<h2 className="text-3xl font-bold animate-fade-up">Stay in the Loop</h2>
|
||||
<p className="mt-3 text-stone-300 animate-fade-up [animation-delay:100ms]">Get early access to new arrivals, exclusive deals, and styling tips.</p>
|
||||
{subscribed ? (
|
||||
<div className="mt-8 animate-fade-in">
|
||||
<div className="inline-flex items-center gap-2 bg-green-500/20 text-green-300 rounded-full px-6 py-3 text-sm font-medium">
|
||||
<Check className="h-4 w-4" /> You're subscribed! Check your inbox.
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<form onSubmit={handleSubscribe} className="mt-8 flex flex-col sm:flex-row gap-3 max-w-md mx-auto">
|
||||
<Input
|
||||
type="email"
|
||||
required
|
||||
placeholder="Enter your email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
className="bg-white/10 border-white/20 text-white placeholder:text-stone-400 rounded-full"
|
||||
/>
|
||||
<Button type="submit" disabled={subscribing} className="bg-rose-500 hover:bg-rose-600 text-white rounded-full px-6 whitespace-nowrap active:scale-[0.98] transition-all">
|
||||
Subscribe
|
||||
</Button>
|
||||
</form>
|
||||
)}
|
||||
<p className="mt-4 text-xs text-stone-400">Join 15,000+ subscribers. No spam, unsubscribe anytime.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── INSTAGRAM GALLERY ── */}
|
||||
<section className="py-24 bg-white">
|
||||
<div className="mx-auto max-w-7xl px-6 text-center">
|
||||
<h2 className="text-3xl font-bold tracking-tight mb-2 animate-fade-up">Follow @StyleHaus</h2>
|
||||
<p className="text-stone-500 mb-10">Tag us in your looks for a chance to be featured</p>
|
||||
<div className="grid grid-cols-3 md:grid-cols-6 gap-2">
|
||||
{["from-rose-100 to-rose-200", "from-stone-100 to-stone-200", "from-amber-100 to-amber-200",
|
||||
"from-rose-200 to-stone-100", "from-stone-200 to-amber-100", "from-amber-200 to-rose-100"
|
||||
].map((grad, i) => (
|
||||
<div key={i} className={`aspect-square rounded-lg bg-gradient-to-br \${grad} group cursor-pointer relative overflow-hidden`}>
|
||||
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/30 transition-colors flex items-center justify-center">
|
||||
<Heart className="h-6 w-6 text-white opacity-0 group-hover:opacity-100 transition-opacity" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user