Files
edr-platform/apps/edr-passenger-web/backoffice/src/components/layout/Header.tsx
2026-07-18 00:34:12 +03:00

153 lines
7.6 KiB
TypeScript

'use client';
import { Bell, LogOut, Moon, Sun, ChevronDown, HelpCircle, KeyRound, ScanLine } from 'lucide-react';
import { useAuthStore } from '@/lib/auth-store';
import { useTheme } from '@/lib/theme-store';
import { useState } from 'react';
import Link from 'next/link';
import ChangePasswordModal from '@/components/layout/ChangePasswordModal';
export default function Header() {
const { user, logout } = useAuthStore();
const { isDark, toggleTheme } = useTheme();
const [showUserMenu, setShowUserMenu] = useState(false);
const [showNotifications, setShowNotifications] = useState(false);
const [showChangePassword, setShowChangePassword] = useState(false);
return (
<header className="flex h-16 items-center justify-between border-b border-gray-200 dark:border-slate-700 bg-white dark:bg-slate-900 px-6 shadow-sm">
<div className="flex flex-1 items-center gap-4">
<h2 className="text-xl font-semibold text-[rgb(20,113,76)] dark:text-[rgb(20,113,76)]"></h2>
<Link
href="/boarding"
className="ml-auto rounded-lg p-2 hover:bg-gray-100 dark:hover:bg-slate-800 transition-colors"
title="Boarding / Gate Scan"
>
<ScanLine className="h-5 w-5 text-[rgb(20,113,76)] dark:text-slate-400" />
</Link>
</div>
<div className="flex items-center gap-3">
{/* Help Documentation */}
<Link
href="/docs"
className="rounded-lg p-2 hover:bg-gray-100 dark:hover:bg-slate-800 transition-colors"
title="View Documentation"
target="_blank"
>
<HelpCircle className="h-5 w-5 text-[rgb(20,113,76)] dark:text-slate-400" />
</Link>
{/* Notifications */}
<div className="relative">
<button
onClick={() => setShowNotifications(!showNotifications)}
className="relative rounded-lg p-2 hover:bg-gray-100 dark:hover:bg-slate-800 transition-colors"
>
<Bell className="h-5 w-5 text-[rgb(20,113,76)] dark:text-slate-400" />
<span className="absolute right-1 top-1 h-2 w-2 rounded-full bg-[rgb(20,113,76)]"></span>
</button>
{showNotifications && (
<div className="fixed inset-x-2 top-20 z-50 rounded-lg border border-gray-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-xl sm:absolute sm:inset-x-auto sm:right-0 sm:top-full sm:mt-2 sm:w-80 md:w-96">
<div className="p-4 border-b border-gray-200 dark:border-slate-700">
<h3 className="font-semibold text-foreground">Notifications</h3>
</div>
<div className="max-h-96 overflow-y-auto">
<Link href="/notifications" className="block p-4 hover:bg-gray-50 dark:hover:bg-slate-800 transition-colors border-b border-gray-200 dark:border-slate-700">
<p className="text-sm font-medium text-foreground">New booking received</p>
<p className="text-xs text-muted-foreground mt-1">Booking #BK-2024-001 created</p>
<p className="text-xs text-muted-foreground mt-1">2 minutes ago</p>
</Link>
<Link href="/notifications" className="block p-4 hover:bg-gray-50 dark:hover:bg-slate-800 transition-colors border-b border-gray-200 dark:border-slate-700">
<p className="text-sm font-medium text-foreground">Payment confirmed</p>
<p className="text-xs text-muted-foreground mt-1">Payment of 1,250 ETB received</p>
<p className="text-xs text-muted-foreground mt-1">15 minutes ago</p>
</Link>
<Link href="/notifications" className="block p-4 hover:bg-gray-50 dark:hover:bg-slate-800 transition-colors">
<p className="text-sm font-medium text-foreground">System update</p>
<p className="text-xs text-muted-foreground mt-1">New features available</p>
<p className="text-xs text-muted-foreground mt-1">1 hour ago</p>
</Link>
</div>
<div className="p-3 border-t border-gray-200 dark:border-slate-700">
<Link href="/notifications" className="text-sm text-primary hover:underline">
View all notifications
</Link>
</div>
</div>
)}
</div>
{/* Theme Toggle */}
<button
onClick={toggleTheme}
className="rounded-lg p-2 hover:bg-gray-100 dark:hover:bg-slate-800 transition-colors"
title={isDark ? 'Switch to Light Mode' : 'Switch to Dark Mode'}
>
{isDark ? <Sun className="h-5 w-5 text-[rgb(20,113,76)] dark:text-slate-400" /> : <Moon className="h-5 w-5 text-[rgb(20,113,76)] dark:text-slate-400" />}
</button>
{/* User Menu */}
<div className="relative">
<button
onClick={() => setShowUserMenu(!showUserMenu)}
className="flex items-center gap-3 rounded-lg p-2 hover:bg-gray-100 dark:hover:bg-slate-800 transition-colors"
>
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-[rgb(20,113,76)] text-white font-semibold text-sm shadow-md">
{user?.fullName?.toUpperCase().charAt(0) || 'A'}
</div>
<div className="text-left hidden md:block">
<p className="text-sm font-medium text-foreground">{user?.fullName || 'Full Name'}</p>
<p className="text-xs text-muted-foreground">{user?.role || 'User Role'}</p>
</div>
<ChevronDown className="h-4 w-4 text-[rgb(20,113,76)] dark:text-slate-400" />
</button>
{showUserMenu && (
<div className="fixed inset-x-2 top-20 z-50 rounded-lg border border-gray-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-xl sm:absolute sm:inset-x-auto sm:right-0 sm:top-full sm:mt-2 sm:w-56">
<div className="p-3 border-b border-gray-200 dark:border-slate-700">
<p className="text-sm font-medium text-foreground">{user?.fullName || 'Full Name'}</p>
<p className="text-xs text-muted-foreground">{user?.email || 'user@email.com'}</p>
</div>
<div className="p-2">
<Link
href="/settings"
className="flex items-center gap-2 rounded-lg px-3 py-2 text-sm text-foreground hover:bg-gray-100 dark:hover:bg-slate-800 transition-colors"
>
Settings
</Link>
<button
onClick={() => {
setShowUserMenu(false);
setShowChangePassword(true);
}}
className="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-foreground hover:bg-gray-100 dark:hover:bg-slate-800 transition-colors"
>
<KeyRound className="h-4 w-4" />
Change Password
</button>
<button
onClick={() => {
logout();
window.location.href = '/login';
}}
className="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-[rgb(20,113,76)] dark:text-green-400 hover:bg-green-50 dark:hover:bg-green-900/20 transition-colors"
>
<LogOut className="h-4 w-4" />
Logout
</button>
</div>
</div>
)}
</div>
</div>
<ChangePasswordModal
isOpen={showChangePassword}
onClose={() => setShowChangePassword(false)}
/>
</header>
);
}