mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 04:08:11 +00:00
215 lines
8.5 KiB
TypeScript
215 lines
8.5 KiB
TypeScript
"use client";
|
|
|
|
import { Menu, X, Moon, Sun, HelpCircle, KeyRound, LogOut, ChevronDown } from "lucide-react";
|
|
import Link from "next/link";
|
|
import Image from "next/image";
|
|
import { useEffect, useState } from "react";
|
|
import { useAuthStore } from "@/lib/auth-store";
|
|
import ChangePasswordModal from "@/components/ChangePasswordModal";
|
|
|
|
export default function AppHeader() {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const [isDark, setIsDark] = useState(false);
|
|
const [showUserMenu, setShowUserMenu] = useState(false);
|
|
const [showChangePassword, setShowChangePassword] = useState(false);
|
|
const { user, isAuthenticated, initialize, logout } = useAuthStore();
|
|
|
|
useEffect(() => {
|
|
const isDarkMode = document.documentElement.classList.contains("dark");
|
|
setIsDark(isDarkMode);
|
|
initialize();
|
|
}, [initialize]);
|
|
|
|
const toggleTheme = () => {
|
|
const html = document.documentElement;
|
|
const isDarkMode = html.classList.contains("dark");
|
|
if (isDarkMode) {
|
|
html.classList.remove("dark");
|
|
setIsDark(false);
|
|
localStorage.setItem("theme", "light");
|
|
} else {
|
|
html.classList.add("dark");
|
|
setIsDark(true);
|
|
localStorage.setItem("theme", "dark");
|
|
}
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
<header className="sticky top-0 z-[60] bg-[rgb(20_113_76)] dark:bg-gray-900 border-b border-[rgb(16_89_60)] dark:border-gray-800 shadow-sm">
|
|
<div className="container mx-auto px-4">
|
|
<div className="max-w-6xl mx-auto">
|
|
<div className="flex items-center justify-between h-16">
|
|
{/* Logo */}
|
|
<Link
|
|
href="/"
|
|
className="flex items-center hover:opacity-80 transition-opacity"
|
|
>
|
|
<Image
|
|
src="/edr-logo.png"
|
|
alt="Ethio-Djibouti Railway"
|
|
width={140}
|
|
height={48}
|
|
className="h-14 w-auto"
|
|
priority
|
|
/>
|
|
</Link>
|
|
|
|
{/* Desktop Menu */}
|
|
<div className="hidden md:flex items-center gap-8">
|
|
<Link
|
|
href="/booking/lookup"
|
|
className="text-sm font-medium text-gray-100 hover:text-white transition-colors"
|
|
>
|
|
My Booking
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Right Actions */}
|
|
<div className="flex items-center gap-2">
|
|
{/* Help Link */}
|
|
<Link
|
|
href="/help"
|
|
className="hidden sm:flex items-center justify-center p-2 text-gray-100 hover:bg-white hover:bg-opacity-10 rounded-lg transition-colors"
|
|
title="Help & FAQ"
|
|
>
|
|
<HelpCircle className="w-5 h-5" />
|
|
</Link>
|
|
|
|
{/* Theme Toggler */}
|
|
<button
|
|
onClick={toggleTheme}
|
|
className="p-2 text-gray-100 hover:bg-white hover:bg-opacity-10 rounded-lg transition-colors"
|
|
title={isDark ? "Light mode" : "Dark mode"}
|
|
>
|
|
{isDark ? (
|
|
<Sun className="w-5 h-5" />
|
|
) : (
|
|
<Moon className="w-5 h-5" />
|
|
)}
|
|
</button>
|
|
|
|
{/* Auth */}
|
|
{isAuthenticated && user ? (
|
|
<div className="relative">
|
|
<button
|
|
onClick={() => setShowUserMenu(!showUserMenu)}
|
|
className="flex items-center gap-2 p-1.5 hover:bg-white hover:bg-opacity-10 rounded-lg transition-colors"
|
|
>
|
|
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-white text-[rgb(20_113_76)] font-semibold text-sm">
|
|
{user.fullName?.toUpperCase().charAt(0) || 'U'}
|
|
</div>
|
|
<ChevronDown className="hidden sm:block w-4 h-4 text-gray-100" />
|
|
</button>
|
|
|
|
{showUserMenu && (
|
|
<div className="absolute right-0 top-full mt-2 w-56 z-50 rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 shadow-xl">
|
|
<div className="p-3 border-b border-gray-200 dark:border-gray-700">
|
|
<p className="text-sm font-medium text-gray-900 dark:text-gray-100 truncate">{user.fullName}</p>
|
|
<p className="text-xs text-gray-500 dark:text-gray-400 truncate">{user.email}</p>
|
|
</div>
|
|
<div className="p-2">
|
|
<button
|
|
onClick={() => {
|
|
setShowUserMenu(false);
|
|
setShowChangePassword(true);
|
|
}}
|
|
className="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
|
|
>
|
|
<KeyRound className="h-4 w-4" />
|
|
Change Password
|
|
</button>
|
|
<button
|
|
onClick={() => {
|
|
setShowUserMenu(false);
|
|
logout();
|
|
}}
|
|
className="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-[rgb(20_113_76)] dark:text-emerald-400 hover:bg-green-50 dark:hover:bg-green-900/20 transition-colors"
|
|
>
|
|
<LogOut className="h-4 w-4" />
|
|
Sign out
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
) : (
|
|
<div className="hidden md:flex items-center gap-2">
|
|
<Link
|
|
href="/login"
|
|
className="px-3 py-1.5 text-sm font-medium text-gray-100 hover:bg-white hover:bg-opacity-10 rounded-lg transition-colors"
|
|
>
|
|
Sign in
|
|
</Link>
|
|
<Link
|
|
href="/register"
|
|
className="px-3 py-1.5 text-sm font-medium bg-white text-[rgb(20_113_76)] hover:bg-gray-100 rounded-lg transition-colors"
|
|
>
|
|
Register
|
|
</Link>
|
|
</div>
|
|
)}
|
|
|
|
{/* Mobile Menu Button */}
|
|
<button
|
|
onClick={() => setIsOpen(!isOpen)}
|
|
className="md:hidden p-2 text-gray-100 hover:bg-white hover:bg-opacity-10 rounded-lg"
|
|
>
|
|
{isOpen ? (
|
|
<X className="w-5 h-5" />
|
|
) : (
|
|
<Menu className="w-5 h-5" />
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Mobile Menu */}
|
|
{isOpen && (
|
|
<div className="md:hidden border-t border-white border-opacity-20 dark:border-gray-700 py-4 space-y-2 animate-in slide-in-from-top-2 duration-200">
|
|
<Link
|
|
href="/booking/lookup"
|
|
className="block px-4 py-2 text-gray-100 dark:text-gray-300 hover:bg-white hover:bg-opacity-10 dark:hover:bg-gray-800 rounded-lg transition-colors"
|
|
onClick={() => setIsOpen(false)}
|
|
>
|
|
My Booking
|
|
</Link>
|
|
<Link
|
|
href="/help"
|
|
className="block px-4 py-2 text-gray-100 dark:text-gray-300 hover:bg-white hover:bg-opacity-10 dark:hover:bg-gray-800 rounded-lg transition-colors"
|
|
onClick={() => setIsOpen(false)}
|
|
>
|
|
Help
|
|
</Link>
|
|
{!isAuthenticated && (
|
|
<>
|
|
<Link
|
|
href="/login"
|
|
className="block px-4 py-2 text-gray-100 dark:text-gray-300 hover:bg-white hover:bg-opacity-10 dark:hover:bg-gray-800 rounded-lg transition-colors"
|
|
onClick={() => setIsOpen(false)}
|
|
>
|
|
Sign in
|
|
</Link>
|
|
<Link
|
|
href="/register"
|
|
className="block px-4 py-2 text-gray-100 dark:text-gray-300 hover:bg-white hover:bg-opacity-10 dark:hover:bg-gray-800 rounded-lg transition-colors"
|
|
onClick={() => setIsOpen(false)}
|
|
>
|
|
Register
|
|
</Link>
|
|
</>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<ChangePasswordModal
|
|
isOpen={showChangePassword}
|
|
onClose={() => setShowChangePassword(false)}
|
|
/>
|
|
</header>
|
|
);
|
|
}
|