fcsc_ipi_frontend/ipi-survey-platform/src/components/admin/AdminHeader.jsx
2025-10-29 15:39:30 +05:30

158 lines
7.0 KiB
JavaScript

import React from 'react';
import { NavLink, useNavigate } from 'react-router-dom';
import Logo from '../../assets/images/fcsclogo.svg';
import DashboardIconActive from '../../assets/images/cuida_dashboard-outline.svg';
import DashboardIconInactive from '../../assets/images/cuida_dashboard-outline-inactive.svg';
import CheckCircleActive from '../../assets/images/checkcircle-active.svg';
import ConfigActive from '../../assets/images/configrationicon-active.svg';
import ConfigInactive from '../../assets/images/configrationicon-inactive.svg';
import UserActive from '../../assets/images/user-active.svg';
import UserInactive from '../../assets/images/user-inactive.svg';
import ManageSubmissionInactive from '../../assets/images/managesubmission - inactive.svg';
import BellIconAsset from '../../assets/images/bell.svg';
const NavItem = ({ label, to, iconActive, iconInactive, end = false }) => (
<NavLink
to={to}
end={end}
className={({ isActive }) =>
`inline-flex items-center gap-2 pb-1 border-b-2 text-[14px] leading-5 ` +
(isActive ? 'text-[#92722A] font-medium border-[#92722A]' : 'text-[#232528] border-transparent hover:text-gray-900')
}
>
{({ isActive }) => (
<>
{iconActive && iconInactive ? (
<img src={isActive ? iconActive : iconInactive} alt={label} className="h-[18px] w-[18px]" />
) : (
<span className={`inline-block h-[18px] w-[18px] rounded ${isActive ? 'bg-[#92722A]' : 'bg-[#C9CDD1]'}`} />
)}
<span>{label}</span>
</>
)}
</NavLink>
);
const AdminHeader = () => {
const [open, setOpen] = React.useState(false);
const [profileOpen, setProfileOpen] = React.useState(false);
const [userName, setUserName] = React.useState('User');
const [userEmail, setUserEmail] = React.useState('user@example.com');
const navigate = useNavigate();
React.useEffect(() => {
try {
const stored = sessionStorage.getItem('user_profile');
if (stored) {
const parsed = JSON.parse(stored);
if (parsed?.name || parsed?.username) {
setUserName(parsed.name || parsed.username);
}
if (parsed?.email) {
setUserEmail(parsed.email);
}
}
} catch {
// ignore corrupt storage
}
}, []);
const handleLogout = () => {
try {
sessionStorage.removeItem('auth_token');
sessionStorage.removeItem('user_profile');
sessionStorage.removeItem('user_role');
sessionStorage.removeItem('establishment_id');
} catch {
// ignore storage errors
}
setProfileOpen(false);
navigate('/login');
};
return (
<header className="bg-white border-b border-[#E5E7EB] shadow-[0_6px_18px_rgba(15,23,42,0.04)]">
<div className="max-w-[1280px] mx-auto px-4">
<div className="flex items-center h-20 gap-6 ">
<img src={Logo} alt="FCSC" className="w-[140px] h-[44px] " />
<nav className="flex-1 flex justify-end items-center gap-6 xl:gap-8 text-[14px] leading-5 ml-auto ">
<NavItem to="/admin/dashboard" end label="Dashboard" iconActive={DashboardIconActive} iconInactive={DashboardIconInactive} />
<NavItem to="/admin/validations" label="Manage Submissions" iconActive={CheckCircleActive} iconInactive={ManageSubmissionInactive} />
<NavItem to="/admin/configuration" label="Configuration" iconActive={ConfigActive} iconInactive={ConfigInactive} />
<NavItem to="/admin/users" label="Users" iconActive={UserActive} iconInactive={UserInactive} />
</nav>
<div className="hidden lg:flex items-center gap-3 ml-auto">
<button
type="button"
aria-label="Notifications"
className="inline-flex h-9 w-9 items-center justify-center rounded-full border border-transparent hover:border-[#E5E7EB]"
>
<img src={BellIconAsset} alt="Notifications" className="h-[18px] w-[18px]" />
</button>
<div className="relative">
<button
type="button"
onClick={() => setProfileOpen((value) => !value)}
className="h-9 w-9 rounded-full bg-[#F2F2F2] grid place-items-center text-[13px] font-medium text-[#232528]"
aria-haspopup="menu"
aria-expanded={profileOpen}
>
{userName?.slice(0, 1)?.toUpperCase() || 'U'}
</button>
{profileOpen && (
<div className="absolute right-0 mt-3 w-64 rounded-[12px] border border-[#E5E7EB] bg-white shadow-[0_20px_30px_rgba(15,23,42,0.12)] z-50 text-center">
<div className="px-4 py-3 border-b border-[#F1F5F9]">
<p className="text-sm font-semibold text-[#232528] truncate" title={userName}>{userName}</p>
<p className="text-xs text-[#6B7280] truncate" title={userEmail}>{userEmail}</p>
</div>
<button
type="button"
className="w-full px-4 py-2.5 text-center text-sm text-[#232528] hover:bg-[#F2ECCF]"
onClick={() => {
setProfileOpen(false);
navigate('/reset-password');
}}
>
Change Password
</button>
<button
type="button"
className="w-full px-4 py-2.5 text-center text-sm text-[#B52520] hover:bg-[#FEE2E2]"
onClick={handleLogout}
>
Logout
</button>
</div>
)}
</div>
</div>
<div className="ml-auto lg:hidden">
<button
type="button"
aria-label="Open Menu"
className="inline-flex items-center justify-center h-10 w-10 rounded-full border border-[#E5E7EB]"
onClick={() => setOpen((v) => !v)}
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
</div>
{open && (
<div className="lg:hidden pb-6 border-t border-[#E5E7EB]">
<nav className="flex flex-col gap-3 pt-4 text-[14px] leading-5">
<NavItem to="/admin/dashboard" end label="Dashboard" iconActive={DashboardIconActive} iconInactive={DashboardIconInactive} />
<NavItem to="/admin/validations" label="Manage Submissions" iconActive={CheckCircleActive} iconInactive={ManageSubmissionInactive} />
<NavItem to="/admin/configuration" label="Configuration" iconActive={ConfigActive} iconInactive={ConfigInactive} />
<NavItem to="/admin/users" label="Users" iconActive={UserActive} iconInactive={UserInactive} />
</nav>
</div>
)}
</div>
</header>
);
};
export default AdminHeader;