1+ import { useState , useEffect } from "react" ;
2+ import { Link , useNavigate } from "react-router-dom" ;
13import { SidebarTrigger } from "@/components/ui/sidebar" ;
2- import { Bell , Search , User , ChevronDown } from "lucide-react" ;
3- import { useEffect , useState } from "react" ;
4+ import { Badge } from "@/components/ui/badge" ;
5+ import {
6+ DropdownMenu ,
7+ DropdownMenuContent ,
8+ DropdownMenuItem ,
9+ DropdownMenuSeparator ,
10+ DropdownMenuTrigger ,
11+ } from "@/components/ui/dropdown-menu" ;
12+ import { Bell , ChevronDown , LogOut , KeyRound , UserCircle } from "lucide-react" ;
413import { useAuthStore } from "@/store/useAuthStore" ;
514import { useNotifCountStore } from "@/store/useNotifCountStore" ;
6- import { Link , useNavigate } from "react-router-dom" ;
715
816export default function AppNavbar ( ) {
9- const [ isProfileOpen , setIsProfileOpen ] = useState ( false ) ;
1017 const { logout, name, role } = useAuthStore ( ) ;
1118 const { unreadCount, fetchUnreadCount } = useNotifCountStore ( ) ;
12-
1319 const navigate = useNavigate ( ) ;
1420
1521 const handleLogout = ( ) => {
@@ -20,60 +26,166 @@ export default function AppNavbar() {
2026 fetchUnreadCount ( ) ;
2127 } , [ fetchUnreadCount ] ) ;
2228
29+ // Get initials from name
30+ const getInitials = ( name ) => {
31+ if ( ! name ) return "U" ;
32+ return name
33+ . split ( " " )
34+ . map ( ( n ) => n [ 0 ] )
35+ . join ( "" )
36+ . toUpperCase ( )
37+ . slice ( 0 , 2 ) ;
38+ } ;
39+
40+ // Get role badge color
41+ const getRoleBadgeColor = ( role ) => {
42+ switch ( role ?. toLowerCase ( ) ) {
43+ case "hr" :
44+ return "bg-purple-100 text-purple-700 border-purple-200" ;
45+ case "manager" :
46+ return "bg-blue-100 text-blue-700 border-blue-200" ;
47+ case "staff" :
48+ return "bg-green-100 text-green-700 border-green-200" ;
49+ default :
50+ return "bg-gray-100 text-gray-700 border-gray-200" ;
51+ }
52+ } ;
53+
2354 return (
24- < header className = "flex justify-between sticky p-5 top-0 z-40 h-20 items-center gap-4 border-b bg-tersier shadow-sm" >
25- < SidebarTrigger className = "text-gray-700 hover:text-sekunder cursor-pointer" />
26- < div className = "flex items-center gap-4" >
27- < button
28- onClick = { ( ) => navigate ( "/announcement" ) }
29- className = "relative rounded-lg p-2 text-gray-600 hover:bg-gray-100 hover:text-gray-900 cursor-pointer"
30- >
31- < Bell className = "h-5 w-5" />
32- { unreadCount > 0 && (
33- < span className = "absolute -top-0.5 -right-0.5 flex h-4 w-4 items-center justify-center rounded-full bg-red-500 text-[10px] font-bold text-white" >
34- { unreadCount > 9 ? "9+" : unreadCount }
35- </ span >
36- ) }
37- </ button >
55+ < header className = "sticky top-0 z-40 border-b border-gray-200 bg-gradient-to-bl from-blue-50 via-purple-50 to-pink-50 backdrop-blur-lg shadow-sm py-3.5" >
56+ < div className = "flex h-16 items-center justify-between px-4 md:px-6" >
57+ { /* Left Section */ }
58+ < div className = "flex items-center gap-4" >
59+ < SidebarTrigger className = "text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-lg p-2 transition-all duration-200 hover:scale-105 cursor-pointer" />
60+ </ div >
3861
39- < div className = "relative" >
62+ { /* Right Section */ }
63+ < div className = "flex items-center gap-3" >
64+ { /* Notification Button */ }
4065 < button
41- onClick = { ( ) => setIsProfileOpen ( ! isProfileOpen ) }
42- className = "flex items-center gap-2 rounded-lg px-3 py-2 text-sm hover:bg-gray-100 cursor-pointer"
66+ onClick = { ( ) => navigate ( "/announcement" ) }
67+ className = "relative rounded-xl p-2.5 text-gray-600 hover:bg-gradient-to-r hover:from-blue-50 hover:to-purple-50 hover:text-blue-600 transition-all duration-200 hover:scale-105 group cursor-pointer"
4368 >
44- < div className = "h-8 w-8 rounded-full bg-teal-100 flex items-center justify-center " >
45- < User className = "h-4 w-4 text-teal-600" />
46- </ div >
47- < div className = "text-left hidden md:block" >
48- < p className = "text-sm font-medium text-gray-700" > { name } </ p >
49- < p className = "text-xs text-gray-500" > { role } </ p >
50- </ div >
51- < ChevronDown className = "h-4 w-4 text-gray-500" />
69+ < Bell className = "h-5 w-5" />
70+ { unreadCount > 0 && (
71+ < span className = "absolute -top-1 -right-1 flex h-5 w-5 items-center justify-center rounded-full bg-gradient-to-r from-red-500 to-pink-500 text-[10px] font-bold text-white shadow-lg animate-pulse" >
72+ { unreadCount > 9 ? "9+" : unreadCount }
73+ </ span >
74+ ) }
75+ { /* Tooltip */ }
76+ < span className = "absolute -bottom-8 right-0 px-2 py-1 bg-gray-900 text-white text-xs rounded-md opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap pointer-events-none" >
77+ Announcements
78+ </ span >
5279 </ button >
5380
54- { isProfileOpen && (
55- < div className = "absolute right-0 mt-2 w-48 rounded-lg border border-gray-200 bg-white shadow-lg py-1" >
56- < Link
57- to = "/profile"
58- className = "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
59- >
60- Profile
61- </ Link >
62- < Link
63- to = "/change-password"
64- className = "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
65- >
66- Change Password
67- </ Link >
68- < hr className = "my-1" />
69- < div
70- onClick = { handleLogout }
71- className = "block px-4 py-2 text-sm text-red-600 hover:bg-gray-100 cursor-pointer"
72- >
73- Logout
81+ { /* Profile Dropdown */ }
82+ < DropdownMenu >
83+ < DropdownMenuTrigger asChild >
84+ < button className = "flex items-center gap-3 rounded-xl px-3 py-2 hover:bg-gradient-to-br hover:from-blue-100 hover:to-purple-100 transition-all duration-200 group outline-none cursor-pointer" >
85+ < div className = "relative" >
86+ < div className = "h-9 w-9 rounded-full bg-gradient-to-br from-blue-500 to-purple-500 flex items-center justify-center text-white text-sm font-bold shadow-md group-hover:shadow-lg transition-shadow" >
87+ { getInitials ( name ) }
88+ </ div >
89+ < div className = "absolute -bottom-0.5 -right-0.5 h-3 w-3 rounded-full bg-green-500 border-2 border-white" > </ div >
90+ </ div >
91+ < div className = "text-left hidden lg:block" >
92+ < p className = "text-sm font-semibold text-gray-900" >
93+ { name || "User Name" }
94+ </ p >
95+ < div className = "flex items-center gap-1" >
96+ < Badge
97+ variant = "outline"
98+ className = { `text-[10px] px-1.5 py-0 h-4 ${ getRoleBadgeColor (
99+ role
100+ ) } `}
101+ >
102+ { role || "User" }
103+ </ Badge >
104+ </ div >
105+ </ div >
106+ < ChevronDown className = "h-4 w-4 text-gray-500 hidden md:block group-hover:text-blue-600 transition-colors" />
107+ </ button >
108+ </ DropdownMenuTrigger >
109+
110+ < DropdownMenuContent
111+ align = "end"
112+ className = "w-64 p-2 bg-white border border-gray-200 shadow-xl rounded-xl"
113+ >
114+ { /* User Info Header */ }
115+ < div className = "px-3 py-3 mb-2 bg-gradient-to-r from-blue-50 to-purple-50 rounded-lg" >
116+ < div className = "flex items-center gap-3" >
117+ < div className = "h-12 w-12 rounded-full bg-gradient-to-br from-blue-500 to-purple-500 flex items-center justify-center text-white text-base font-bold shadow-md" >
118+ { getInitials ( name ) }
119+ </ div >
120+ < div className = "flex-1 min-w-0" >
121+ < p className = "text-sm font-semibold text-gray-900 truncate" >
122+ { name || "User Name" }
123+ </ p >
124+ < Badge
125+ variant = "outline"
126+ className = { `text-xs mt-1 ${ getRoleBadgeColor ( role ) } ` }
127+ >
128+ { role || "User" }
129+ </ Badge >
130+ </ div >
131+ </ div >
74132 </ div >
75- </ div >
76- ) }
133+
134+ < DropdownMenuSeparator className = "my-2" />
135+
136+ { /* Menu Items */ }
137+ < DropdownMenuItem asChild >
138+ < Link
139+ to = "/profile"
140+ className = "flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-gray-700 hover:bg-gradient-to-r hover:from-blue-50 hover:to-purple-50 hover:text-blue-600 transition-all cursor-pointer"
141+ >
142+ < div className = "p-1.5 bg-blue-100 rounded-lg" >
143+ < UserCircle className = "h-4 w-4 text-blue-600" />
144+ </ div >
145+ < div >
146+ < p className = "font-medium" > Profile</ p >
147+ < p className = "text-xs text-gray-500" > View your profile</ p >
148+ </ div >
149+ </ Link >
150+ </ DropdownMenuItem >
151+
152+ < DropdownMenuItem asChild >
153+ < Link
154+ to = "/change-password"
155+ className = "flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-gray-700 hover:bg-gradient-to-r hover:from-blue-50 hover:to-purple-50 hover:text-blue-600 transition-all cursor-pointer"
156+ >
157+ < div className = "p-1.5 bg-purple-100 rounded-lg" >
158+ < KeyRound className = "h-4 w-4 text-purple-600" />
159+ </ div >
160+ < div >
161+ < p className = "font-medium" > Change Password</ p >
162+ < p className = "text-xs text-gray-500" >
163+ Update your password
164+ </ p >
165+ </ div >
166+ </ Link >
167+ </ DropdownMenuItem >
168+
169+ < DropdownMenuSeparator className = "my-2" />
170+
171+ < DropdownMenuItem asChild >
172+ < button
173+ onClick = { handleLogout }
174+ className = "w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-red-600 hover:bg-red-50 transition-all cursor-pointer"
175+ >
176+ < div className = "p-1.5 bg-red-100 rounded-lg" >
177+ < LogOut className = "h-4 w-4 text-red-600" />
178+ </ div >
179+ < div className = "text-left" >
180+ < p className = "font-medium" > Logout</ p >
181+ < p className = "text-xs text-red-500" >
182+ Sign out of your account
183+ </ p >
184+ </ div >
185+ </ button >
186+ </ DropdownMenuItem >
187+ </ DropdownMenuContent >
188+ </ DropdownMenu >
77189 </ div >
78190 </ div >
79191 </ header >
0 commit comments