NitinBot002's picture
Initial commit with all project files
f4854a1
import { useState, useEffect } from 'react';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { motion, AnimatePresence } from 'framer-motion';
import { HiMenu, HiX, HiChevronDown, HiHeart, HiUserCircle } from 'react-icons/hi';
import { useAuth } from '../../contexts/AuthContext';
import { NAV_LINKS, FOUNDATION_INFO } from '../../utils/constants';
import './Header.css';
export default function Header() {
const [isScrolled, setIsScrolled] = useState(false);
const [mobileOpen, setMobileOpen] = useState(false);
const [dropdownOpen, setDropdownOpen] = useState(null);
const { currentUser, userProfile, logout } = useAuth();
const location = useLocation();
const navigate = useNavigate();
useEffect(() => {
const handleScroll = () => setIsScrolled(window.scrollY > 20);
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// Close mobile menu on route change
useEffect(() => {
setMobileOpen(false);
setDropdownOpen(null);
}, [location]);
const handleLogout = async () => {
try {
await logout();
navigate('/');
} catch (error) {
console.error('Logout error:', error);
}
};
const isActive = (path) => location.pathname === path;
return (
<header className={`header ${isScrolled ? 'header--scrolled' : ''}`}>
<div className="header__container container">
{/* Logo */}
<Link to="/" className="header__logo">
<img src="/logo.png" alt={FOUNDATION_INFO.name} className="header__logo-img" />
<div className="header__logo-text">
<span className="header__logo-name">Social Share</span>
<span className="header__logo-sub">& Care Foundation</span>
</div>
</Link>
{/* Desktop Navigation */}
<nav className="header__nav">
{NAV_LINKS.map((link) => (
<div
key={link.path}
className="header__nav-item"
onMouseEnter={() => link.children && setDropdownOpen(link.path)}
onMouseLeave={() => setDropdownOpen(null)}
>
<Link
to={link.path}
className={`header__nav-link ${isActive(link.path) ? 'header__nav-link--active' : ''}`}
>
{link.label}
{link.children && <HiChevronDown className="header__chevron" />}
</Link>
{/* Dropdown */}
<AnimatePresence>
{link.children && dropdownOpen === link.path && (
<motion.div
className="header__dropdown"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
transition={{ duration: 0.2 }}
>
{link.children.map((child) => (
<Link
key={child.path}
to={child.path}
className="header__dropdown-link"
>
{child.label}
</Link>
))}
</motion.div>
)}
</AnimatePresence>
</div>
))}
</nav>
{/* Right Actions */}
<div className="header__actions">
<Link to="/donate" className="btn btn--primary btn--sm header__donate-btn">
<HiHeart /> Donate
</Link>
{currentUser ? (
<div
className="header__user"
onMouseEnter={() => setDropdownOpen('user')}
onMouseLeave={() => setDropdownOpen(null)}
>
<button className="header__user-btn">
{userProfile?.profileImage ? (
<img src={userProfile.profileImage} alt="" className="header__avatar" referrerPolicy="no-referrer" />
) : (
<HiUserCircle size={40} />
)}
</button>
<AnimatePresence>
{dropdownOpen === 'user' && (
<motion.div
className="header__dropdown header__dropdown--right"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
>
<div className="header__dropdown-user">
<strong>{userProfile?.displayName}</strong>
<span>{userProfile?.email}</span>
</div>
<Link to="/dashboard" className="header__dropdown-link">Dashboard</Link>
<Link to="/dashboard/profile" className="header__dropdown-link">Profile</Link>
<Link to="/donations/history" className="header__dropdown-link">My Donations</Link>
<button onClick={handleLogout} className="header__dropdown-link header__dropdown-link--danger">
Sign Out
</button>
</motion.div>
)}
</AnimatePresence>
</div>
) : (
<Link to="/login" className="btn btn--outline btn--sm">
Sign In
</Link>
)}
{/* Mobile Toggle */}
<button
className="header__mobile-toggle"
onClick={() => setMobileOpen(!mobileOpen)}
aria-label="Toggle menu"
>
{mobileOpen ? <HiX size={24} /> : <HiMenu size={24} />}
</button>
</div>
</div>
{/* Mobile Menu */}
<AnimatePresence>
{mobileOpen && (
<motion.div
className="header__mobile"
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3 }}
>
<nav className="header__mobile-nav">
{NAV_LINKS.map((link) => (
<div key={link.path}>
<Link
to={link.path}
className={`header__mobile-link ${isActive(link.path) ? 'header__mobile-link--active' : ''}`}
>
{link.label}
</Link>
{link.children && (
<div className="header__mobile-sub">
{link.children.map((child) => (
<Link key={child.path} to={child.path} className="header__mobile-sub-link">
{child.label}
</Link>
))}
</div>
)}
</div>
))}
{!currentUser && (
<Link to="/login" className="btn btn--primary" style={{ marginTop: '1rem' }}>
Sign In
</Link>
)}
{currentUser && (
<>
<Link to="/dashboard" className="header__mobile-link">Dashboard</Link>
<Link to="/donations/history" className="header__mobile-link">My Donations</Link>
<button onClick={handleLogout} className="header__mobile-link" style={{ color: '#EF4444' }}>
Sign Out
</button>
</>
)}
</nav>
</motion.div>
)}
</AnimatePresence>
</header>
);
}