ifixkart-storefront/layout/HeaderActions.tsx

133 lines
5 KiB
TypeScript

'use client';
import React, { useState, useEffect } from 'react';
import Link from 'next/link';
import { Heart, ShoppingCart, Menu, Search, X, GitCompare } from 'lucide-react';
import { LiveSearch } from '../components/store/LiveSearch';
import { useCartStore } from '@/store/cartStore';
import { motion, AnimatePresence } from 'framer-motion';
import { AccountMenu } from '@/components/AccountMenu';
export const HeaderActions: React.FC = () => {
const [mobileSearchOpen, setMobileSearchOpen] = useState(false);
const setCartDrawerOpen = useCartStore((state) => state.setCartDrawerOpen);
const cartItems = useCartStore((state) => state.cart) || [];
const cartCount = cartItems.reduce(
(acc, item) => acc + (item.quantity || 1),
0
);
const wishlistCount = useCartStore((state) => state.wishlist.length);
const compareCount = useCartStore((state) => (state.compareList || []).length);
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') setMobileSearchOpen(false);
};
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, []);
const triggerMobileDrawer = () => {
window.dispatchEvent(new Event('openMobileDrawer'));
};
return (
<>
<div className="flex items-center gap-2 md:gap-5 flex-shrink-0">
<button
onClick={() => setMobileSearchOpen(!mobileSearchOpen)}
className="lg:hidden p-2 text-gray-650 hover:text-primary transition-colors hover:bg-gray-50 rounded-lg cursor-pointer"
aria-label="Toggle Search"
>
<Search size={22} className="stroke-[2.5]" />
</button>
<button
onClick={triggerMobileDrawer}
className="lg:hidden p-2 text-gray-650 hover:text-primary transition-colors hover:bg-gray-50 rounded-lg cursor-pointer"
aria-label="Open Menu"
>
<Menu size={24} className="stroke-[2.5]" />
</button>
<Link
href="/compare"
className="relative p-2 text-gray-650 hover:text-primary transition-colors hover:bg-gray-50 rounded-lg group focus:outline-none"
aria-label="Compare products"
>
<GitCompare
size={22}
className="group-hover:scale-105 transition-transform"
/>
{compareCount > 0 && (
<span className="absolute top-0 right-0 w-5 h-5 bg-[#0073EC] text-white text-[10px] font-bold rounded-full flex items-center justify-center border-2 border-white shadow-xs">
{compareCount}
</span>
)}
</Link>
<Link
href="/wishlist"
className="relative p-2 text-gray-650 hover:text-primary transition-colors hover:bg-gray-50 rounded-lg group focus:outline-none"
aria-label="Open Wishlist"
>
<Heart
size={24}
className="group-hover:scale-105 transition-transform"
/>
{wishlistCount > 0 && (
<span className="absolute top-0 right-0 w-5 h-5 bg-[#0073EC] text-white text-[10px] font-bold rounded-full flex items-center justify-center border-2 border-white shadow-xs">
{wishlistCount}
</span>
)}
</Link>
<AccountMenu />
<button
type="button"
onClick={() => setCartDrawerOpen(true)}
className="flex items-center gap-2.5 p-2 text-gray-650 hover:text-primary transition-colors hover:bg-gray-50 rounded-lg group relative cursor-pointer"
>
<div className="relative">
<ShoppingCart
size={24}
className="group-hover:scale-105 transition-transform"
/>
{cartCount > 0 && (
<span className="absolute -top-1.5 -right-1.5 w-5 h-5 bg-[#0073EC] text-white text-[10px] font-bold rounded-full flex items-center justify-center border-2 border-white shadow-xs">
{cartCount}
</span>
)}
</div>
<div className="text-left hidden md:block text-[11.5px] leading-tight font-medium">
<span className="text-gray-400 block font-normal">My Cart</span>
</div>
</button>
</div>
<AnimatePresence>
{mobileSearchOpen && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
className="lg:hidden border-t border-gray-100 px-4 pt-3 pb-2 bg-white w-full absolute left-0 right-0 top-full z-[120] shadow-md"
>
<div className="flex gap-2 items-center relative z-55">
<LiveSearch />
<button
onClick={() => setMobileSearchOpen(false)}
className="p-2 text-gray-400 hover:text-gray-650 cursor-pointer"
aria-label="Close Search"
>
<X size={20} />
</button>
</div>
</motion.div>
)}
</AnimatePresence>
</>
);
};