'use client'; import Link from 'next/link'; import Image from 'next/image'; import { useState, useEffect, useRef, useCallback } from 'react'; import { usePathname } from 'next/navigation'; import { useLanguage } from '@/context/LanguageContext'; import { useAuth } from '@/context/AuthContext'; import LanguageToggle from '@/components/LanguageToggle'; import Button from '@/components/ui/Button'; import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'; function NavLink({ href, children }: { href: string; children: React.ReactNode }) { const pathname = usePathname(); const isActive = pathname === href || (href !== '/' && pathname.startsWith(href)); return ( {children} ); } function MobileNavLink({ href, children, onClick }: { href: string; children: React.ReactNode; onClick: () => void }) { const pathname = usePathname(); const isActive = pathname === href || (href !== '/' && pathname.startsWith(href)); return ( {children} ); } export default function Header() { const { t } = useLanguage(); const { user, isAdmin, logout } = useAuth(); const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const menuRef = useRef(null); const touchStartX = useRef(0); const touchCurrentX = useRef(0); const isDragging = useRef(false); // Close menu on route change const pathname = usePathname(); useEffect(() => { setMobileMenuOpen(false); }, [pathname]); // Prevent body scroll when menu is open useEffect(() => { if (mobileMenuOpen) { document.body.style.overflow = 'hidden'; } else { document.body.style.overflow = ''; } return () => { document.body.style.overflow = ''; }; }, [mobileMenuOpen]); // Handle swipe to close const handleTouchStart = useCallback((e: React.TouchEvent) => { touchStartX.current = e.touches[0].clientX; touchCurrentX.current = e.touches[0].clientX; isDragging.current = true; }, []); const handleTouchMove = useCallback((e: React.TouchEvent) => { if (!isDragging.current) return; touchCurrentX.current = e.touches[0].clientX; const deltaX = touchCurrentX.current - touchStartX.current; // Only allow dragging to the right (to close) if (deltaX > 0 && menuRef.current) { menuRef.current.style.transform = `translateX(${deltaX}px)`; } }, []); const handleTouchEnd = useCallback(() => { if (!isDragging.current) return; isDragging.current = false; const deltaX = touchCurrentX.current - touchStartX.current; const threshold = 100; // Minimum swipe distance to close if (menuRef.current) { menuRef.current.style.transform = ''; if (deltaX > threshold) { setMobileMenuOpen(false); } } }, []); const closeMenu = useCallback(() => { setMobileMenuOpen(false); }, []); const navLinks = [ { href: '/', label: t('nav.home') }, { href: '/events', label: t('nav.events') }, { href: '/community', label: t('nav.community') }, { href: '/contact', label: t('nav.contact') }, ]; return ( {/* Logo */} {/* Desktop Navigation */} {navLinks.map((link) => ( {link.label} ))} {/* Right side actions */} {user ? ( {t('nav.dashboard')} {isAdmin && ( {t('nav.admin')} )} {user.name} {t('nav.logout')} ) : ( {t('nav.login')} {t('nav.joinEvent')} )} {/* Mobile menu button (hamburger) */} setMobileMenuOpen(true)} aria-label="Open menu" > {/* Mobile Slide-in Menu */} {/* Overlay */} {/* Slide-in Panel */} {/* Menu Header */} {/* Menu Content */} {/* Navigation Links */} {navLinks.map((link) => ( {link.label} ))} {/* Divider */} {/* Language Toggle */} {/* Divider */} {/* Auth Actions */} {user ? ( <> {user.name?.charAt(0).toUpperCase()} {user.name} {t('nav.dashboard')} {isAdmin && ( {t('nav.admin')} )} { logout(); closeMenu(); }} className="w-full justify-center" > {t('nav.logout')} > ) : ( <> {t('nav.login')} {t('nav.joinEvent')} > )} {/* Swipe hint */} Swipe right to close ); }
Swipe right to close