205 lines
7.2 KiB
TypeScript
205 lines
7.2 KiB
TypeScript
"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>
|
||
)
|
||
}
|