Spaces:
Sleeping
Sleeping
| import { useState, useEffect } from 'react'; | |
| import { | |
| BookOpen, | |
| Home, | |
| User, | |
| LogOut, | |
| Mic, | |
| Users, | |
| Calendar, | |
| Menu, | |
| } from 'lucide-react'; | |
| import { Button } from './ui/button'; | |
| import { useAuth } from '../lib/authContext'; | |
| import { useLanguage } from '../lib/languageContext'; | |
| import { translations } from '../lib/translations'; | |
| import { LanguageSwitcher } from './LanguageSwitcher'; | |
| import { | |
| DropdownMenu, | |
| DropdownMenuContent, | |
| DropdownMenuItem, | |
| DropdownMenuLabel, | |
| DropdownMenuSeparator, | |
| DropdownMenuTrigger, | |
| } from './ui/dropdown-menu'; | |
| import { Link, useLocation, useNavigate } from 'react-router-dom'; | |
| import { useQueryClient } from '@tanstack/react-query'; | |
| export function Navbar() { | |
| const { user, signOut } = useAuth(); | |
| const { language } = useLanguage(); | |
| const t = translations[language].navbar; | |
| const location = useLocation(); | |
| const navigate = useNavigate(); | |
| const queryClient = useQueryClient(); | |
| const [mobileOpen, setMobileOpen] = useState(false); | |
| const [isMobile, setIsMobile] = useState(false); | |
| useEffect(() => { | |
| const check = () => setIsMobile(window.innerWidth < 950); | |
| check(); | |
| window.addEventListener('resize', check); | |
| return () => window.removeEventListener('resize', check); | |
| }, []); | |
| if (!user) return null; | |
| const isActive = (path) => location.pathname.startsWith(path); | |
| const getNavItems = () => { | |
| switch (user.role) { | |
| case 'student': | |
| return [ | |
| { path: '/student/dashboard', label: t.dashboard, icon: Home }, | |
| { path: '/student/practice', label: t.aiPractice, icon: Mic }, | |
| { path: '/student/find-sheikh', label: t.findSheikh, icon: Users }, | |
| { path: '/student/sessions', label: t.mySessions, icon: Calendar }, | |
| ]; | |
| case 'sheikh': | |
| return [ | |
| { path: '/sheikh/dashboard', label: t.dashboard, icon: Home }, | |
| { path: '/sheikh/sessions', label: t.sessions, icon: Calendar }, | |
| { path: '/sheikh/students', label: t.students, icon: Users }, | |
| ]; | |
| case 'admin': | |
| return [ | |
| { path: '/admin/dashboard', label: t.dashboard, icon: Home }, | |
| { path: '/admin/sheikh-approval', label: t.sheikhApproval, icon: Users }, | |
| { path: '/admin/users', label: t.allUsers, icon: Users }, | |
| ]; | |
| default: | |
| return []; | |
| } | |
| }; | |
| const navItems = getNavItems(); | |
| return ( | |
| <nav className="border-b bg-white sticky top-0 z-50"> | |
| <div className="container mx-auto px-4"> | |
| <div className="flex h-16 items-center justify-between gap-4"> | |
| {/* Left: Hamburger (mobile) + Logo */} | |
| <div className="flex items-center gap-2"> | |
| {/* Hamburger - mobile only */} | |
| {isMobile && ( | |
| <DropdownMenu open={mobileOpen} onOpenChange={setMobileOpen}> | |
| <DropdownMenuTrigger asChild> | |
| <Button variant="ghost" size="icon"> | |
| <Menu className="h-5 w-5" /> | |
| </Button> | |
| </DropdownMenuTrigger> | |
| <DropdownMenuContent align="start" className="w-52"> | |
| <DropdownMenuLabel>القائمة</DropdownMenuLabel> | |
| <DropdownMenuSeparator /> | |
| {navItems.map((item) => { | |
| const Icon = item.icon; | |
| return ( | |
| <DropdownMenuItem | |
| key={item.path} | |
| asChild | |
| className={isActive(item.path) ? 'bg-accent' : ''} | |
| > | |
| <Link | |
| to={item.path} | |
| className="flex items-center gap-2 w-full cursor-pointer" | |
| onClick={() => setMobileOpen(false)} | |
| > | |
| <Icon className="h-4 w-4" /> | |
| {item.label} | |
| </Link> | |
| </DropdownMenuItem> | |
| ); | |
| })} | |
| </DropdownMenuContent> | |
| </DropdownMenu> | |
| )} | |
| {/* Logo */} | |
| <Link to="/" className="flex items-center gap-2"> | |
| <BookOpen className="h-6 w-6 text-emerald-600" /> | |
| <span className="font-semibold hidden sm:inline">{t.platformName}</span> | |
| </Link> | |
| {/* Desktop Nav Links */} | |
| {!isMobile && ( | |
| <div className="flex items-center gap-1 ml-4"> | |
| {navItems.map((item) => { | |
| const Icon = item.icon; | |
| return ( | |
| <Button | |
| key={item.path} | |
| asChild | |
| variant={isActive(item.path) ? 'default' : 'ghost'} | |
| className="gap-2" | |
| > | |
| <Link to={item.path}> | |
| <Icon className="h-4 w-4" /> | |
| {item.label} | |
| </Link> | |
| </Button> | |
| ); | |
| })} | |
| </div> | |
| )} | |
| </div> | |
| {/* Right: Language + User menu */} | |
| <div className="flex items-center gap-2"> | |
| <LanguageSwitcher /> | |
| <DropdownMenu> | |
| <DropdownMenuTrigger asChild> | |
| <Button variant="ghost" className="gap-2"> | |
| <User className="h-4 w-4" /> | |
| <span className="hidden md:inline max-w-[120px] truncate"> | |
| {user.name} | |
| </span> | |
| </Button> | |
| </DropdownMenuTrigger> | |
| <DropdownMenuContent align="end"> | |
| <DropdownMenuLabel>{t.myAccount}</DropdownMenuLabel> | |
| <DropdownMenuSeparator /> | |
| <DropdownMenuItem onClick={() => navigate('/profile')}> | |
| <User className="mr-2 h-4 w-4" /> | |
| {t.profile} | |
| </DropdownMenuItem> | |
| <DropdownMenuSeparator /> | |
| <DropdownMenuItem | |
| onClick={() => { | |
| signOut(); | |
| queryClient.clear(); | |
| navigate('/'); | |
| }} | |
| > | |
| <LogOut className="mr-2 h-4 w-4" /> | |
| {t.signOut} | |
| </DropdownMenuItem> | |
| </DropdownMenuContent> | |
| </DropdownMenu> | |
| </div> | |
| </div> | |
| </div> | |
| </nav> | |
| ); | |
| } |