refactor: eliminate code duplication in App.tsx navigation logic

- Extract findNavItemByPath as a reusable helper function
- Remove duplicate findItem function definitions
- Use consistent updateSEO function in both handleItemClick and popstate handler
- Move updateSEO function definition before its usage to fix reference order

This improves code maintainability by reducing duplication and ensuring
consistent SEO update behavior across all navigation paths.

Co-authored-by: Mervin Praison <[email protected]>
This commit is contained in:
praisonai-triage-agent[bot]andMervin Praison committed 2026-06-23 10:16:56 +00:00
1 parent de6d655250
commit 963735699c
1 file changed
+87 -117
+87 -117
View File
@@ -31,131 +31,32 @@ export default function App() {
const [selectedItem, setSelectedItem] = useState<NavItem | null>(null)
const [activeItemPath, setActiveItemPath] = useState<string>('')
useEffect(() => {
async function loadManifests() {
try {
const [configRes, navRes, routesRes] = await Promise.all([
fetch('/ui-config.json'),
fetch('/docs-nav.json'),
fetch('/route-manifest.json'),
])
if (!configRes.ok || !navRes.ok || !routesRes.ok) {
throw new Error('Failed to load manifests')
// Helper function to find nav item by path
const findNavItemByPath = (navData: DocsNav, path: string): NavItem | null => {
const findItem = (items: NavItem[]): NavItem | null => {
for (const item of items) {
if (item.path === path || item.path === path.replace(/^\//, '')) {
return item
}
const configData = await configRes.json()
const navData = await navRes.json()
setConfig(configData)
setNav(navData)
setRoutes(await routesRes.json())
// Apply theme from YAML config
const theme = configData.site?.theme
applyTheme(
theme?.preset || 'zinc',
theme?.darkMode !== false,
theme?.radius || 'md'
)
// Handle initial URL path for SPA routing
const currentPath = window.location.pathname
if (currentPath && currentPath !== '/') {
// Find matching nav item by path
const findItem = (items: NavItem[]): NavItem | null => {
for (const item of items) {
if (item.path === currentPath || item.path === currentPath.replace(/^\//, '')) {
return item
}
if (item.children) {
const found = findItem(item.children)
if (found) return found
}
}
return null
}
// Search all nav groups
if (navData.items) {
for (const group of navData.items) {
if (group.children) {
const found = findItem(group.children)
if (found) {
setSelectedItem(found)
setActiveItemPath(found.path || found.title)
break
}
}
}
}
if (item.children) {
const found = findItem(item.children)
if (found) return found
}
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error')
} finally {
setLoading(false)
}
return null
}
loadManifests()
}, [])
// Handle browser back/forward navigation in a separate effect
useEffect(() => {
const handlePopState = () => {
const path = window.location.pathname
// Find matching nav item by path
const findItem = (items: NavItem[]): NavItem | null => {
for (const item of items) {
if (item.path === path || item.path === path.replace(/^\//, '')) {
return item
}
if (item.children) {
const found = findItem(item.children)
if (found) return found
}
// Search all nav groups
if (navData.items) {
for (const group of navData.items) {
if (group.children) {
const found = findItem(group.children)
if (found) return found
}
return null
}
// Search all nav groups for the matching path
let found: NavItem | null = null
if (nav.items) {
for (const group of nav.items) {
if (group.children) {
found = findItem(group.children)
if (found) break
}
}
}
if (found) {
setSelectedItem(found)
setActiveItemPath(found.path || found.title)
// Update SEO meta tags with current page title
const siteName = config.site?.title || 'Documentation'
const titleTemplate = config.seo?.titleTemplate || '%s | %s'
if (titleTemplate.includes('%s')) {
// Replace first %s with page title, second %s (if exists) with site name
let formattedTitle = titleTemplate.replace('%s', found.title)
if (formattedTitle.includes('%s')) {
formattedTitle = formattedTitle.replace('%s', siteName)
}
document.title = formattedTitle
} else {
document.title = `${found.title} | ${siteName}`
}
} else if (path === '/') {
setSelectedItem(null)
setActiveItemPath('')
// Reset title to site title
document.title = config.site?.title || 'Documentation'
}
}
window.addEventListener('popstate', handlePopState)
return () => window.removeEventListener('popstate', handlePopState)
}, [nav, config])
return null
}
// Update SEO meta tags dynamically
const updateSEO = (title: string, path: string, description?: string) => {
@@ -233,6 +134,75 @@ export default function App() {
}
}
useEffect(() => {
async function loadManifests() {
try {
const [configRes, navRes, routesRes] = await Promise.all([
fetch('/ui-config.json'),
fetch('/docs-nav.json'),
fetch('/route-manifest.json'),
])
if (!configRes.ok || !navRes.ok || !routesRes.ok) {
throw new Error('Failed to load manifests')
}
const configData = await configRes.json()
const navData = await navRes.json()
setConfig(configData)
setNav(navData)
setRoutes(await routesRes.json())
// Apply theme from YAML config
const theme = configData.site?.theme
applyTheme(
theme?.preset || 'zinc',
theme?.darkMode !== false,
theme?.radius || 'md'
)
// Handle initial URL path for SPA routing
const currentPath = window.location.pathname
if (currentPath && currentPath !== '/') {
const found = findNavItemByPath(navData, currentPath)
if (found) {
setSelectedItem(found)
setActiveItemPath(found.path || found.title)
}
}
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error')
} finally {
setLoading(false)
}
}
loadManifests()
}, [])
// Handle browser back/forward navigation in a separate effect
useEffect(() => {
const handlePopState = () => {
const path = window.location.pathname
const found = findNavItemByPath(nav, path)
if (found) {
setSelectedItem(found)
setActiveItemPath(found.path || found.title)
// Use updateSEO function for consistency
updateSEO(found.title, path)
} else if (path === '/') {
setSelectedItem(null)
setActiveItemPath('')
// Reset title to site title
document.title = config.site?.title || 'Documentation'
}
}
window.addEventListener('popstate', handlePopState)
return () => window.removeEventListener('popstate', handlePopState)
}, [nav, config])
const handleItemClick = (item: NavItem) => {
setSelectedItem(item)
setActiveItemPath(item.path || item.title)