dressed_for_succes_store/frontend/components/header.tsx

205 lines
7.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import { useState, useEffect } from "react"
import Link from "next/link"
import Image from "next/image"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Search, ShoppingBag, User, Heart, Menu, X } from "lucide-react"
import { usePathname } from "next/navigation"
import { motion, AnimatePresence } from "framer-motion"
export default function Header() {
const [isScrolled, setIsScrolled] = useState(false)
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
const [isSearchOpen, setIsSearchOpen] = useState(false)
const pathname = usePathname()
// Отслеживание скролла для изменения стиля хедера
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50)
}
window.addEventListener("scroll", handleScroll)
return () => window.removeEventListener("scroll", handleScroll)
}, [])
// Закрытие мобильного меню при изменении маршрута
useEffect(() => {
setIsMobileMenuOpen(false)
setIsSearchOpen(false)
}, [pathname])
// Навигационные ссылки
const navLinks = [
{ name: "ГЛАВНАЯ", href: "/" },
{ name: "КАТАЛОГ", href: "/catalog" },
{ name: "КОЛЛЕКЦИИ", href: "/collections" },
{ name: "О НАС", href: "/about" },
{ name: "КОНТАКТЫ", href: "/contact" },
]
return (
<header
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-500 ${
isScrolled
? "bg-tertiary/95 backdrop-blur-md shadow-sm py-2"
: "bg-white/80 backdrop-blur-sm py-4"
}`}
>
<div className="container mx-auto px-4">
<div className="flex items-center justify-between">
{/* Логотип */}
<Link href="/" className="relative z-10">
<div className="flex items-center">
<div className="relative h-12 w-12 mr-2">
<Image
src="/logo.svg"
alt="Dressed For Success"
fill
className="object-contain"
priority
/>
</div>
<span className="font-serif text-primary text-xl tracking-wider hidden md:block">
DRESSED FOR SUCCESS
</span>
</div>
</Link>
{/* Десктопная навигация */}
<nav className="hidden md:flex items-center space-x-8">
{navLinks.map((link) => (
<Link
key={link.href}
href={link.href}
className={`text-sm font-medium tracking-wide transition-colors hover:text-secondary ${
pathname === link.href
? "text-primary border-b border-primary pb-1"
: "text-primary/80"
}`}
>
{link.name}
</Link>
))}
</nav>
{/* Иконки действий */}
<div className="flex items-center space-x-2">
<Button
variant="ghost"
size="icon"
className="text-primary hover:text-secondary hover:bg-tertiary/50"
onClick={() => setIsSearchOpen(!isSearchOpen)}
>
<Search className="h-5 w-5" />
<span className="sr-only">Поиск</span>
</Button>
<Link href="/wishlist">
<Button
variant="ghost"
size="icon"
className="text-primary hover:text-secondary hover:bg-tertiary/50"
>
<Heart className="h-5 w-5" />
<span className="sr-only">Избранное</span>
</Button>
</Link>
<Link href="/account">
<Button
variant="ghost"
size="icon"
className="text-primary hover:text-secondary hover:bg-tertiary/50"
>
<User className="h-5 w-5" />
<span className="sr-only">Аккаунт</span>
</Button>
</Link>
<Link href="/cart">
<Button
variant="ghost"
size="icon"
className="text-primary hover:text-secondary hover:bg-tertiary/50 relative"
>
<ShoppingBag className="h-5 w-5" />
<span className="absolute -top-1 -right-1 bg-secondary text-white text-xs rounded-full h-4 w-4 flex items-center justify-center">
0
</span>
<span className="sr-only">Корзина</span>
</Button>
</Link>
{/* Кнопка мобильного меню */}
<Button
variant="ghost"
size="icon"
className="md:hidden text-primary hover:text-secondary hover:bg-tertiary/50"
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
>
{isMobileMenuOpen ? (
<X className="h-5 w-5" />
) : (
<Menu className="h-5 w-5" />
)}
<span className="sr-only">Меню</span>
</Button>
</div>
</div>
{/* Строка поиска */}
<AnimatePresence>
{isSearchOpen && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
className="py-4"
>
<div className="relative">
<Input
type="search"
placeholder="Поиск по каталогу..."
className="w-full border-primary/20 focus:border-primary bg-white/90 pl-10"
autoFocus
/>
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-primary/60" />
</div>
</motion.div>
)}
</AnimatePresence>
{/* Мобильное меню */}
<AnimatePresence>
{isMobileMenuOpen && (
<motion.div
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
className="absolute top-full left-0 right-0 bg-tertiary/95 backdrop-blur-md shadow-lg py-6 px-4 z-50"
>
<nav className="flex flex-col space-y-4">
{navLinks.map((link) => (
<Link
key={link.href}
href={link.href}
className={`text-sm font-medium tracking-wide transition-colors ${
pathname === link.href
? "text-secondary font-semibold"
: "text-primary"
}`}
>
{link.name}
</Link>
))}
</nav>
</motion.div>
)}
</AnimatePresence>
</div>
</header>
)
}