Initial: ecommerce template via tAI
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
|
||||
import { Menu, Search, ShoppingBag, User, Heart, Separator as SeparatorIcon } from "lucide-react";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { ThemeToggle } from "@/components/ThemeToggle";
|
||||
import { useCart } from "@/lib/cart-context";
|
||||
|
||||
const cartPreviewItems = [
|
||||
{ name: "Classic Leather Jacket", price: 189, qty: 1 },
|
||||
{ name: "Silk Scarf", price: 65, qty: 1 },
|
||||
{ name: "Organic Cotton Tee", price: 45, qty: 2 },
|
||||
];
|
||||
|
||||
const navLinks = [
|
||||
{ label: "Home", to: "/" },
|
||||
{ label: "Shop", to: "/products" },
|
||||
{ label: "New Arrivals", to: "/products" },
|
||||
{ label: "Sale", to: "/products" },
|
||||
];
|
||||
|
||||
export default function Header() {
|
||||
const [mobileOpen, setMobileOpen] = useState(false);
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
const { itemCount } = useCart();
|
||||
|
||||
useEffect(() => {
|
||||
const onScroll = () => setScrolled(window.scrollY > 20);
|
||||
window.addEventListener("scroll", onScroll);
|
||||
return () => window.removeEventListener("scroll", onScroll);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<header className={\`fixed top-0 inset-x-0 z-50 transition-all duration-300 \${
|
||||
scrolled ? "backdrop-blur-xl bg-white/80 dark:bg-slate-900/80 border-white/20 border-b border-stone-100 shadow-sm" : "bg-white/80 backdrop-blur-sm"
|
||||
}\`}>
|
||||
{/* Top Banner */}
|
||||
<div className="bg-stone-900 text-white text-center text-xs py-1.5">
|
||||
Free shipping on orders over $100 | Use code STYLE20 for 20% off
|
||||
</div>
|
||||
|
||||
<div className="mx-auto max-w-7xl flex items-center justify-between px-6 py-3">
|
||||
{/* Logo */}
|
||||
<Link to="/" className="text-xl font-bold tracking-tight text-stone-900">
|
||||
StyleHaus
|
||||
</Link>
|
||||
|
||||
{/* Desktop Nav */}
|
||||
<nav className="hidden md:flex items-center gap-8">
|
||||
{navLinks.map((l) => (
|
||||
<Link key={l.to + l.label} to={l.to} className="text-sm text-stone-600 hover:text-stone-900 transition-colors font-medium">
|
||||
{l.label}
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Right Icons */}
|
||||
<div className="flex items-center gap-1">
|
||||
<Button asChild variant="ghost" size="icon" className="hidden sm:flex h-9 w-9">
|
||||
<Link to="/search"><Search className="h-4 w-4" /></Link>
|
||||
</Button>
|
||||
<Button asChild variant="ghost" size="icon" className="hidden sm:flex h-9 w-9">
|
||||
<Link to="/account?tab=wishlist"><Heart className="h-4 w-4" /></Link>
|
||||
</Button>
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button variant={itemCount > 0 ? "default" : "ghost"} size="icon" className={\`relative h-9 w-9 transition-all \${itemCount > 0 ? "bg-stone-900 hover:bg-stone-800 text-white" : ""}\`}>
|
||||
<ShoppingBag className="h-4 w-4" />
|
||||
{itemCount > 0 && (
|
||||
<span className="absolute -top-1 -right-1 h-5 w-5 rounded-full bg-rose-500 text-[10px] font-bold text-white flex items-center justify-center ring-2 ring-white animate-fade-in">
|
||||
{itemCount}
|
||||
</span>
|
||||
)}
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="right" className="w-80 bg-white flex flex-col">
|
||||
<h2 className="text-lg font-bold mb-4">Your Cart</h2>
|
||||
<div className="flex-1 overflow-y-auto space-y-4">
|
||||
{cartPreviewItems.map((item, i) => (
|
||||
<div key={i} className="flex items-center justify-between text-sm">
|
||||
<div>
|
||||
<p className="font-medium">{item.name}</p>
|
||||
<p className="text-stone-500 text-xs">Qty: {item.qty}</p>
|
||||
</div>
|
||||
<span className="font-semibold">\${(item.price * item.qty).toFixed(2)}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Separator className="my-4" />
|
||||
<div className="flex justify-between text-sm font-bold mb-4">
|
||||
<span>Subtotal</span>
|
||||
<span>\${cartPreviewItems.reduce((s, i) => s + i.price * i.qty, 0).toFixed(2)}</span>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Button asChild variant="outline" className="w-full rounded-full">
|
||||
<Link to="/cart">View Cart</Link>
|
||||
</Button>
|
||||
<Button asChild className="w-full rounded-full bg-stone-900 hover:bg-stone-800">
|
||||
<Link to="/checkout">Checkout</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
<Button asChild variant="ghost" size="icon" className="hidden sm:flex h-9 w-9">
|
||||
<Link to="/account"><User className="h-4 w-4" /></Link>
|
||||
</Button>
|
||||
<ThemeToggle />
|
||||
|
||||
{/* Mobile Menu */}
|
||||
<Sheet open={mobileOpen} onOpenChange={setMobileOpen}>
|
||||
<SheetTrigger asChild className="md:hidden">
|
||||
<Button variant="ghost" size="icon" className="h-9 w-9"><Menu className="h-5 w-5" /></Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="right" className="w-72 bg-white">
|
||||
<nav className="mt-8 flex flex-col gap-1">
|
||||
{navLinks.map((l) => (
|
||||
<Link
|
||||
key={l.to + l.label}
|
||||
to={l.to}
|
||||
className="px-4 py-3 text-base font-medium hover:bg-stone-50 rounded-lg transition-colors"
|
||||
onClick={() => setMobileOpen(false)}
|
||||
>
|
||||
{l.label}
|
||||
</Link>
|
||||
))}
|
||||
<div className="border-t border-stone-100 mt-4 pt-4 space-y-1">
|
||||
<Link to="/search" className="flex items-center gap-3 px-4 py-3 text-sm text-stone-600 hover:bg-stone-50 rounded-lg" onClick={() => setMobileOpen(false)}>
|
||||
<Search className="h-4 w-4" /> Search
|
||||
</Link>
|
||||
<Link to="/account" className="flex items-center gap-3 px-4 py-3 text-sm text-stone-600 hover:bg-stone-50 rounded-lg" onClick={() => setMobileOpen(false)}>
|
||||
<User className="h-4 w-4" /> Account
|
||||
</Link>
|
||||
<Link to="/account?tab=wishlist" className="flex items-center gap-3 px-4 py-3 text-sm text-stone-600 hover:bg-stone-50 rounded-lg" onClick={() => setMobileOpen(false)}>
|
||||
<Heart className="h-4 w-4" /> Wishlist
|
||||
</Link>
|
||||
<div className="px-4 pt-2"><ThemeToggle /></div>
|
||||
</div>
|
||||
</nav>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user