@@ -5,6 +5,8 @@ import { ChevronDown } from "lucide-react";
55import { useDispatch , useSelector } from "react-redux" ;
66import { logout , syncUserFromCookie } from "../redux/slices/authSlice.js" ;
77import { getUserCookie } from "../utils/cookies.js" ;
8+ import { getAssetPath } from "../utils/assets.js" ;
9+ import ImageWithFallback from "./shared/ImageWithFallback.jsx" ;
810
911const navItems = [
1012 { to : "/" , label : "Home" } ,
@@ -60,12 +62,13 @@ function Header() {
6062 const location = useLocation ( ) ;
6163 const reduxUser = useSelector ( ( state ) => state . auth . user ) ;
6264 // Fallback to cookie if Redux user is not available (for cross-tab sync)
63- const user = reduxUser || ( typeof window !== 'undefined' ? getUserCookie ( ) : null ) ;
65+ const user =
66+ reduxUser || ( typeof window !== "undefined" ? getUserCookie ( ) : null ) ;
6467 const [ menuOpen , setMenuOpen ] = React . useState ( false ) ;
6568
6669 // Sync user from cookie on mount and when storage changes (cross-tab sync)
6770 const lastSyncedRef = React . useRef ( null ) ;
68-
71+
6972 React . useEffect ( ( ) => {
7073 // Only sync once on mount if needed - don't re-sync on every reduxUser change
7174 const cookieUser = getUserCookie ( ) ;
@@ -77,7 +80,7 @@ function Header() {
7780 lastSyncedRef . current = cookieStr ;
7881 }
7982 }
80-
83+
8184 const handleStorageChange = ( ) => {
8285 // Storage events only fire from other tabs, so safe to sync
8386 dispatch ( syncUserFromCookie ( ) ) ;
@@ -86,10 +89,10 @@ function Header() {
8689 lastSyncedRef . current = JSON . stringify ( updatedCookie ) ;
8790 }
8891 } ;
89-
92+
9093 // Listen for storage events (cross-tab sync)
91- window . addEventListener ( ' storage' , handleStorageChange ) ;
92-
94+ window . addEventListener ( " storage" , handleStorageChange ) ;
95+
9396 // Also check periodically for cookie changes (since cookies don't trigger storage events)
9497 const interval = setInterval ( ( ) => {
9598 const currentCookieUser = getUserCookie ( ) ;
@@ -106,9 +109,9 @@ function Header() {
106109 lastSyncedRef . current = null ;
107110 }
108111 } , 3000 ) ; // Check every 3 seconds
109-
112+
110113 return ( ) => {
111- window . removeEventListener ( ' storage' , handleStorageChange ) ;
114+ window . removeEventListener ( " storage" , handleStorageChange ) ;
112115 clearInterval ( interval ) ;
113116 } ;
114117 } , [ dispatch ] ) ; // Only dispatch in dependencies - sync once on mount
@@ -138,7 +141,7 @@ function Header() {
138141 className = "flex items-center gap-1.5 md:gap-2 transition-transform hover:scale-105 flex-shrink-0"
139142 >
140143 < img
141- src = "/assets/logo.png"
144+ src = { getAssetPath ( "/assets/logo.png" ) }
142145 alt = "XK Trading Floor Logo"
143146 className = "h-10 w-8 md:h-14 md:w-10 rounded object-cover"
144147 />
@@ -244,8 +247,9 @@ function Header() {
244247 aria-expanded = { menuOpen }
245248 aria-label = "User menu"
246249 >
247- < img
250+ < ImageWithFallback
248251 src = { user . avatar || "/assets/users/default-avatar.jpg" }
252+ fallback = "/assets/users/default-avatar.jpg"
249253 alt = "User avatar"
250254 className = "h-7 w-7 lg:h-8 lg:w-8 rounded-full object-cover ring-2 ring-blue-500/20 flex-shrink-0"
251255 />
@@ -268,13 +272,13 @@ function Header() {
268272 className = "absolute right-0 top-12 w-48 border border-gray-800 bg-gray-900/95 backdrop-blur-xl rounded-lg shadow-2xl overflow-hidden"
269273 role = "menu"
270274 >
271- { ( user ?. role === ' admin' || user ?. role === ' operator' ) && (
275+ { ( user ?. role === " admin" || user ?. role === " operator" ) && (
272276 < button
273277 onClick = { ( ) => {
274278 setMenuOpen ( false ) ;
275279 // Use navigate with a small delay to ensure menu closes first
276280 setTimeout ( ( ) => {
277- navigate ( ' /dashboard' ) ;
281+ navigate ( " /dashboard" ) ;
278282 } , 100 ) ;
279283 } }
280284 className = "block w-full text-left px-4 py-3 text-sm text-gray-200 hover:bg-gray-800/50 transition-colors border-b border-gray-800"
@@ -364,12 +368,12 @@ function Header() {
364368 < div className = "pt-4 mt-2 border-t border-gray-800 flex flex-col gap-2" >
365369 { user ? (
366370 < >
367- { ( user ?. role === ' admin' || user ?. role === ' operator' ) && (
371+ { ( user ?. role === " admin" || user ?. role === " operator" ) && (
368372 < button
369373 onClick = { ( ) => {
370374 setOpen ( false ) ;
371375 setTimeout ( ( ) => {
372- navigate ( ' /dashboard' ) ;
376+ navigate ( " /dashboard" ) ;
373377 } , 100 ) ;
374378 } }
375379 className = "w-full text-left px-4 py-3 text-sm text-gray-300 hover:text-white hover:bg-gray-800/50 rounded-lg transition-colors"
0 commit comments