11import { useRouter } from 'next/router'
2- import { useState , useEffect , useRef } from 'react'
2+ import { useState , useEffect , useMemo , useRef } from 'react'
33import { siteConfig } from '@/lib/config'
44import { handleEmailClick } from '@/lib/plugins/mailEncrypt'
55import { useGlobal } from '@/lib/global'
6- import CONFIG from '../config'
76import SmartLink from '@/components/SmartLink'
87import { EndspacePlayer } from './EndspacePlayer'
8+ import { buildMenuItems , isMenuItemActive } from './menu'
99import {
1010 IconMenu2 ,
1111 IconX ,
@@ -70,23 +70,19 @@ const SocialIconComponents = {
7070export const MobileNav = ( props ) => {
7171 const router = useRouter ( )
7272 const { siteInfo } = useGlobal ( )
73+ const { customNav, customMenu } = props
7374 const [ activeTab , setActiveTab ] = useState ( 'Home' )
7475 const [ isMenuOpen , setIsMenuOpen ] = useState ( false )
76+ const [ openSubMenu , setOpenSubMenu ] = useState ( null )
7577 const emailIcon = useRef ( null )
7678
7779 // Get avatar from props or global context
7880 const avatarUrl = props ?. siteInfo ?. icon || siteInfo ?. icon || siteConfig ( 'AVATAR' )
7981
80- // All navigation items
81- const menuItems = [
82- { name : 'Home' , path : '/' } ,
83- { name : 'Category' , path : '/category' , show : siteConfig ( 'ENDSPACE_MENU_CATEGORY' , null , CONFIG ) } ,
84- { name : 'Tag' , path : '/tag' , show : siteConfig ( 'ENDSPACE_MENU_TAG' , null , CONFIG ) } ,
85- { name : 'Archive' , path : '/archive' , show : siteConfig ( 'ENDSPACE_MENU_ARCHIVE' , null , CONFIG ) } ,
86- { name : 'Portfolio' , path : '/portfolio' } ,
87- { name : 'Friends' , path : '/friends' } ,
88- { name : 'Search' , path : '/search' , show : siteConfig ( 'ENDSPACE_MENU_SEARCH' , null , CONFIG ) }
89- ] . filter ( item => item . show !== false )
82+ const menuItems = useMemo (
83+ ( ) => buildMenuItems ( { customNav, customMenu } ) ,
84+ [ customNav , customMenu ]
85+ )
9086
9187 // Social icon config - using contact.config.js settings
9288 const socialLinks = [
@@ -107,18 +103,14 @@ export const MobileNav = (props) => {
107103
108104 useEffect ( ( ) => {
109105 const path = router . asPath
110- if ( path === '/' ) setActiveTab ( 'Home' )
111- else if ( path . includes ( '/category' ) ) setActiveTab ( 'Category' )
112- else if ( path . includes ( '/tag' ) ) setActiveTab ( 'Tag' )
113- else if ( path . includes ( '/archive' ) ) setActiveTab ( 'Archive' )
114- else if ( path . includes ( '/search' ) ) setActiveTab ( 'Search' )
115- else if ( path . includes ( '/friends' ) ) setActiveTab ( 'Friends' )
116- else if ( path . includes ( '/portfolio' ) ) setActiveTab ( 'Portfolio' )
117- } , [ router . asPath ] )
106+ const activeItem = menuItems . find ( item => isMenuItemActive ( item , path ) )
107+ setActiveTab ( activeItem ?. name || 'Home' )
108+ } , [ router . asPath , menuItems ] )
118109
119110 // Close menu when route changes
120111 useEffect ( ( ) => {
121112 setIsMenuOpen ( false )
113+ setOpenSubMenu ( null )
122114 } , [ router . asPath ] )
123115
124116 // Prevent body scroll when menu is open
@@ -135,8 +127,7 @@ export const MobileNav = (props) => {
135127
136128 // Render icon component
137129 const renderIcon = ( name ) => {
138- const IconComponent = IconComponents [ name ]
139- if ( ! IconComponent ) return null
130+ const IconComponent = IconComponents [ name ] || BookMarkFillIcon
140131 return < IconComponent size = { 20 } className = "w-6 text-center" />
141132 }
142133
@@ -199,22 +190,69 @@ export const MobileNav = (props) => {
199190 >
200191 { /* Navigation Items */ }
201192 < div className = "flex flex-col items-start p-6 space-y-2" >
202- { menuItems . map ( item => (
203- < SmartLink
204- key = { item . name }
205- href = { item . path }
206- className = { `flex items-center gap-4 py-3 w-full transition-all group ${
207- activeTab === item . name
208- ? 'text-black font-bold'
209- : 'text-[var(--endspace-text-secondary)] hover:text-black'
210- } `}
211- >
212- < div className = { `transition-colors ${ activeTab === item . name ? 'text-black' : 'text-gray-400 group-hover:text-black' } ` } >
213- { renderIcon ( item . name ) }
193+ { menuItems . map ( item => {
194+ const hasSubMenu = item . subMenus ?. length > 0
195+ const itemKey = `${ item . name } -${ item . path } `
196+ const isOpen = openSubMenu === itemKey
197+ const itemClassName = `flex items-center gap-4 py-3 w-full transition-all group ${
198+ activeTab === item . name
199+ ? 'text-black font-bold'
200+ : 'text-[var(--endspace-text-secondary)] hover:text-black'
201+ } `
202+ const itemContent = (
203+ < >
204+ < div className = { `transition-colors ${ activeTab === item . name ? 'text-black' : 'text-gray-400 group-hover:text-black' } ` } >
205+ { item . icon ? < i className = { item . icon } /> : renderIcon ( item . name ) }
206+ </ div >
207+ < span className = "text-xl font-medium" > { item . name } </ span >
208+ { hasSubMenu && (
209+ < span className = { `ml-auto text-xl transition-transform duration-200 ${ isOpen ? 'rotate-90' : '' } ` } >
210+ ›
211+ </ span >
212+ ) }
213+ </ >
214+ )
215+
216+ return (
217+ < div key = { itemKey } className = 'w-full' >
218+ { hasSubMenu ? (
219+ < button
220+ type = 'button'
221+ onClick = { ( ) => setOpenSubMenu ( isOpen ? null : itemKey ) }
222+ className = { itemClassName }
223+ >
224+ { itemContent }
225+ </ button >
226+ ) : (
227+ < SmartLink
228+ href = { item . path }
229+ target = { item . target }
230+ className = { itemClassName }
231+ >
232+ { itemContent }
233+ </ SmartLink >
234+ ) }
235+
236+ { hasSubMenu && isOpen && (
237+ < div className = 'mb-2 ml-10 flex flex-col border-l border-[var(--endspace-border-base)] pl-4' >
238+ { item . subMenus . map ( subMenu => (
239+ < SmartLink
240+ key = { `${ subMenu . name } -${ subMenu . path } ` }
241+ href = { subMenu . path }
242+ target = { subMenu . target || item . target }
243+ className = 'flex items-center gap-3 py-2 text-base text-[var(--endspace-text-secondary)] transition-colors hover:text-black'
244+ >
245+ < span className = 'w-4 text-center text-gray-400' >
246+ { subMenu . icon ? < i className = { subMenu . icon } /> : renderIcon ( subMenu . name ) }
247+ </ span >
248+ < span > { subMenu . name } </ span >
249+ </ SmartLink >
250+ ) ) }
251+ </ div >
252+ ) }
214253 </ div >
215- < span className = "text-xl font-medium" > { item . name } </ span >
216- </ SmartLink >
217- ) ) }
254+ )
255+ } ) }
218256 </ div >
219257
220258 { /* Music Player (No Label, No Divider) */ }
0 commit comments