@@ -2,8 +2,20 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'
22import Tabs from '@mui/material/Tabs'
33import Tab from '@mui/material/Tab'
44import Box from '@mui/material/Box'
5- import { useLocation , useNavigate } from 'react-router'
5+ import { useLocation } from 'react-router'
66import customColors from '@/customColors'
7+ import { useAppNavigation } from '@/helpers/navigation'
8+
9+ interface NamedTab {
10+ name : string
11+ path ?: string | null
12+ }
13+
14+ interface NavigationTab extends NamedTab {
15+ path : string
16+ }
17+
18+ type TabItem = string | NamedTab
719
820interface TabPanelProps {
921 children ?: React . ReactNode
@@ -13,6 +25,13 @@ interface TabPanelProps {
1325 index : number
1426}
1527
28+ const a11yProps = ( index : number ) => {
29+ return {
30+ 'id' : `simple-tab-${ index } ` ,
31+ 'aria-controls' : `simple-tabpanel-${ index } ` ,
32+ }
33+ }
34+
1635const TabPanel = React . memo ( ( props : TabPanelProps ) => {
1736 const { children, value, px, py, index, ...other } = props
1837 return (
@@ -34,22 +53,15 @@ const TabPanel = React.memo((props: TabPanelProps) => {
3453
3554TabPanel . displayName = 'TabPanel'
3655
37- const a11yProps = ( index : number ) => {
38- return {
39- 'id' : `simple-tab-${ index } ` ,
40- 'aria-controls' : `simple-tabpanel-${ index } ` ,
41- }
42- }
43-
44- interface NavigationTab {
45- name : string
46- path : string
47- }
48-
49- type TabItem = string | NavigationTab
50-
51- const isNavigationTab = ( tab : TabItem | undefined ) : tab is NavigationTab => {
52- return Boolean ( tab && typeof tab === 'object' && 'name' in tab && 'path' in tab )
56+ const isNavigationTab = ( tab : TabItem | null ) : tab is NavigationTab => {
57+ return Boolean (
58+ tab &&
59+ typeof tab === 'object' &&
60+ 'name' in tab &&
61+ 'path' in tab &&
62+ typeof tab . path === 'string' &&
63+ tab . path . trim ( ) . length > 0 ,
64+ )
5365}
5466
5567const initTabValue = ( tabNames : TabItem [ ] , pathname : string ) => {
@@ -65,31 +77,33 @@ interface GluuTabsProps {
6577
6678export default function GluuTabs ( { tabNames, tabToShow, withNavigation = false } : GluuTabsProps ) {
6779 const path = useLocation ( )
68- const navigate = useNavigate ( )
80+ const { navigateToRoute } = useAppNavigation ( )
6981
70- // Calculate initial value (only used on mount by useState)
7182 const [ value , setValue ] = useState ( ( ) =>
7283 withNavigation ? initTabValue ( tabNames , path . pathname ) : 0 ,
7384 )
7485
75- // Memoize tab label getter
76- const getTabLabel = useCallback ( ( tab : TabItem ) => ( isNavigationTab ( tab ) ? tab . name : tab ) , [ ] )
86+ const getTabLabel = useCallback ( ( tab : TabItem ) => {
87+ if ( typeof tab === 'string' ) {
88+ return tab
89+ }
90+
91+ return tab . name
92+ } , [ ] )
7793
78- // Memoize tab change handler
7994 const handleChange = useCallback (
8095 ( event : React . SyntheticEvent , newValue : number ) => {
8196 setValue ( newValue )
8297 if ( withNavigation ) {
83- const tab = tabNames [ newValue ]
84- if ( isNavigationTab ( tab ) ) {
85- navigate ( tab . path , { replace : true } )
98+ const tab = tabNames [ newValue ] ?? null
99+ if ( isNavigationTab ( tab ) && tab . path !== path . pathname ) {
100+ navigateToRoute ( tab . path , { replace : true } )
86101 }
87102 }
88103 } ,
89- [ withNavigation , tabNames , navigate ] ,
104+ [ withNavigation , tabNames , navigateToRoute , path . pathname ] ,
90105 )
91106
92- // Memoize tabs styling
93107 const tabsSx = useMemo (
94108 ( ) => ( {
95109 '& .MuiTab-root.Mui-selected' : {
@@ -111,10 +125,16 @@ export default function GluuTabs({ tabNames, tabToShow, withNavigation = false }
111125 [ ] ,
112126 )
113127
114- // Memoize tab labels array
128+ const tabsContainerSx = useMemo (
129+ ( ) => ( {
130+ borderBottom : 1 ,
131+ borderColor : 'divider' ,
132+ } ) ,
133+ [ ] ,
134+ )
135+
115136 const tabLabels = useMemo ( ( ) => tabNames . map ( getTabLabel ) , [ tabNames , getTabLabel ] )
116137
117- // Sync tab value with URL pathname
118138 useEffect ( ( ) => {
119139 if ( ! withNavigation ) {
120140 return
@@ -127,23 +147,24 @@ export default function GluuTabs({ tabNames, tabToShow, withNavigation = false }
127147 if ( activeIndex === - 1 ) {
128148 const firstNavIndex = tabNames . findIndex ( isNavigationTab )
129149 if ( firstNavIndex !== - 1 ) {
130- const firstNavTab = tabNames [ firstNavIndex ] as NavigationTab
131- navigate ( firstNavTab . path , { replace : true } )
150+ const firstNavTab = tabNames [ firstNavIndex ] ?? null
151+ if ( isNavigationTab ( firstNavTab ) && firstNavTab . path !== path . pathname ) {
152+ navigateToRoute ( firstNavTab . path , { replace : true } )
153+ }
132154 setValue ( firstNavIndex )
133155 } else {
134156 setValue ( 0 )
135157 }
136158 return
137159 }
138160
139- const activeTab = tabNames [ activeIndex ] as NavigationTab
140- if ( activeTab . path !== path . pathname ) {
141- navigate ( activeTab . path , { replace : true } )
161+ const activeTab = tabNames [ activeIndex ] ?? null
162+ if ( isNavigationTab ( activeTab ) ) {
163+ navigateToRoute ( activeTab . path , { replace : true } )
142164 }
143165 setValue ( activeIndex )
144- } , [ withNavigation , tabNames , path . pathname , navigate ] )
166+ } , [ withNavigation , tabNames , path . pathname , navigateToRoute ] )
145167
146- // Memoize tab elements
147168 const tabElements = useMemo (
148169 ( ) =>
149170 tabLabels . map ( ( label , index ) => (
@@ -152,7 +173,6 @@ export default function GluuTabs({ tabNames, tabToShow, withNavigation = false }
152173 [ tabLabels ] ,
153174 )
154175
155- // Memoize tab panel elements
156176 const tabPanels = useMemo (
157177 ( ) =>
158178 tabLabels . map ( ( label , index ) => (
@@ -165,7 +185,7 @@ export default function GluuTabs({ tabNames, tabToShow, withNavigation = false }
165185
166186 return (
167187 < Box sx = { { width : '100%' } } >
168- < Box sx = { { borderBottom : 1 , borderColor : 'divider' } } >
188+ < Box sx = { tabsContainerSx } >
169189 < Tabs value = { value } variant = "scrollable" onChange = { handleChange } sx = { tabsSx } >
170190 { tabElements }
171191 </ Tabs >
0 commit comments