11'use client' ;
22
33import * as React from 'react' ;
4+ import dynamic from 'next/dynamic' ;
45import {
56 AppBar ,
67 Box ,
@@ -30,8 +31,8 @@ import {
3031 gbfsMetricsNavItems ,
3132} from '../constants/Navigation' ;
3233import type NavigationItem from '../interface/Navigation' ;
33- import { usePathname , useRouter , useSearchParams } from 'next/navigation' ;
34- import LogoutConfirmModal from './LogoutConfirmModal ' ;
34+ import { usePathname , useRouter } from 'next/navigation' ;
35+ import Image from 'next/image ' ;
3536import { BikeScooterOutlined , OpenInNew } from '@mui/icons-material' ;
3637import { useRemoteConfig } from '../context/RemoteConfigProvider' ;
3738import { NestedMenuItem } from 'mui-nested-menu' ;
@@ -40,7 +41,6 @@ import DepartureBoardIcon from '@mui/icons-material/DepartureBoard';
4041import { fontFamily } from '../Theme' ;
4142import { defaultRemoteConfigValues } from '../interface/RemoteConfig' ;
4243import { animatedButtonStyling } from './Header.style' ;
43- import DrawerContent from './HeaderMobileDrawer' ;
4444import ThemeToggle from './ThemeToggle' ;
4545import { useTranslations , useLocale } from 'next-intl' ;
4646import { useSelector } from 'react-redux' ;
@@ -49,16 +49,36 @@ import {
4949 selectUserEmail ,
5050} from '../store/profile-selectors' ;
5151
52+ // Lazy load components not needed for initial render
53+ const LogoutConfirmModal = dynamic ( ( ) => import ( './LogoutConfirmModal' ) , {
54+ ssr : false ,
55+ } ) ;
56+ const DrawerContent = dynamic ( ( ) => import ( './HeaderMobileDrawer' ) , {
57+ ssr : false ,
58+ } ) ;
59+
60+ // Hook to safely access search params only on client
61+ function useClientSearchParams ( ) {
62+ const [ searchParams , setSearchParams ] = React . useState < URLSearchParams | null > ( null ) ;
63+
64+ React . useEffect ( ( ) => {
65+ if ( typeof window !== 'undefined' ) {
66+ setSearchParams ( new URLSearchParams ( window . location . search ) ) ;
67+ }
68+ } , [ ] ) ;
69+
70+ return searchParams ;
71+ }
72+
5273export default function DrawerAppBar ( ) : React . ReactElement {
53- const searchParams = useSearchParams ( ) ;
74+ const clientSearchParams = useClientSearchParams ( ) ;
5475 const hasTransitFeedsRedirectParam =
55- searchParams . get ( 'utm_source' ) === 'transitfeeds' ;
76+ clientSearchParams ?. get ( 'utm_source' ) === 'transitfeeds' ;
77+
5678 const theme = useTheme ( ) ;
5779 const pathname = usePathname ( ) ;
5880 const [ mobileOpen , setMobileOpen ] = React . useState ( false ) ;
59- const [ hasTransitFeedsRedirect , setHasTransitFeedsRedirect ] = React . useState (
60- hasTransitFeedsRedirectParam ,
61- ) ;
81+ const [ hasTransitFeedsRedirect , setHasTransitFeedsRedirect ] = React . useState ( false ) ;
6282 const [ openDialog , setOpenDialog ] = React . useState ( false ) ;
6383 const [ activeTab , setActiveTab ] = React . useState ( '' ) ;
6484 const [ navigationItems , setNavigationItems ] = React . useState <
@@ -68,6 +88,12 @@ export default function DrawerAppBar(): React.ReactElement {
6888 const { config } = useRemoteConfig ( ) ;
6989 const t = useTranslations ( 'common' ) ;
7090
91+ React . useEffect ( ( ) => {
92+ if ( hasTransitFeedsRedirectParam ) {
93+ setHasTransitFeedsRedirect ( true ) ;
94+ }
95+ } , [ hasTransitFeedsRedirectParam ] ) ;
96+
7197 React . useEffect ( ( ) => {
7298 setActiveTab ( pathname ?? '' ) ;
7399 } , [ pathname ] ) ;
@@ -99,8 +125,7 @@ export default function DrawerAppBar(): React.ReactElement {
99125 handleMenuClose ( ) ;
100126 } ;
101127
102- const container =
103- window !== undefined ? ( ) => window . document . body : undefined ;
128+ const container = typeof window !== 'undefined' ? ( ) => window . document . body : undefined ;
104129
105130 const [ anchorEl , setAnchorEl ] = React . useState < null | HTMLElement > ( null ) ;
106131
@@ -159,22 +184,14 @@ export default function DrawerAppBar(): React.ReactElement {
159184 } }
160185 className = 'btn-link'
161186 >
162- < picture style = { { display : 'flex' } } >
163- < source
164- media = '(min-width: 50px)'
165- srcSet = '/assets/MOBILTYDATA_logo_purple_M.webp'
166- width = '50'
167- height = '50'
168- />
169- < source
170- src = '/assets/MOBILTYDATA_logo_purple_M.png'
171- type = 'image/png'
172- />
173- < img
174- alt = 'MobilityData logo'
175- src = '/assets/MOBILTYDATA_logo_purple_M.png'
176- />
177- </ picture >
187+ < Image
188+ src = '/assets/MOBILTYDATA_logo_purple_M.webp'
189+ alt = 'MobilityData logo'
190+ width = { 50 }
191+ height = { 50 }
192+ priority
193+ fetchPriority = 'high'
194+ />
178195 < Typography
179196 variant = 'h5'
180197 component = 'h1'
@@ -429,9 +446,9 @@ export default function DrawerAppBar(): React.ReactElement {
429446 severity = 'warning'
430447 onClose = { ( ) => {
431448 setHasTransitFeedsRedirect ( false ) ;
432- if ( hasTransitFeedsRedirectParam ) {
449+ if ( hasTransitFeedsRedirectParam && clientSearchParams ) {
433450 // Remove utm_source from URL
434- const newSearchParams = new URLSearchParams ( searchParams ) ;
451+ const newSearchParams = new URLSearchParams ( clientSearchParams ) ;
435452 newSearchParams . delete ( 'utm_source' ) ;
436453 const newPath = `${ pathname } ?${ newSearchParams . toString ( ) } ` ;
437454 router . replace ( newPath ) ;
0 commit comments