fix financial and certificates
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useMemo, useState, type ReactNode } from 'react'
|
||||
import { Link, NavLink, Outlet, useLocation, useNavigate } from 'react-router-dom'
|
||||
import { ApiHttpError } from '../api/http'
|
||||
import { fetchNavMenu } from '../api/session'
|
||||
import type { NavItem } from '../api/types'
|
||||
import { useAuth } from '../auth/AuthProvider'
|
||||
@@ -8,6 +9,25 @@ import {
|
||||
spaPathFromCiUrl,
|
||||
} from '../lib/ciSpaPaths'
|
||||
|
||||
const navLabelCollator = new Intl.Collator(undefined, {
|
||||
sensitivity: 'base',
|
||||
numeric: true,
|
||||
})
|
||||
|
||||
function compareNavItemsByLabel(a: NavItem, b: NavItem): number {
|
||||
const labelResult = navLabelCollator.compare(a.label?.trim() || '', b.label?.trim() || '')
|
||||
return labelResult || a.id - b.id
|
||||
}
|
||||
|
||||
function sortNavTree(items: NavItem[]): NavItem[] {
|
||||
return [...items]
|
||||
.map((item) => ({
|
||||
...item,
|
||||
children: sortNavTree(item.children ?? []),
|
||||
}))
|
||||
.sort(compareNavItemsByLabel)
|
||||
}
|
||||
|
||||
function normalizeNavItems(payload: unknown): NavItem[] {
|
||||
const rawItems = Array.isArray(payload)
|
||||
? (payload as NavItem[])
|
||||
@@ -20,7 +40,7 @@ function normalizeNavItems(payload: unknown): NavItem[] {
|
||||
|
||||
if (rawItems.length === 0) return []
|
||||
if (rawItems.some((item) => Array.isArray(item.children) && item.children.length > 0)) {
|
||||
return rawItems
|
||||
return sortNavTree(rawItems)
|
||||
}
|
||||
|
||||
const byId = new Map<number, NavItem>()
|
||||
@@ -38,7 +58,7 @@ function normalizeNavItems(payload: unknown): NavItem[] {
|
||||
}
|
||||
}
|
||||
|
||||
return tree
|
||||
return sortNavTree(tree)
|
||||
}
|
||||
|
||||
function branchContainsPath(item: NavItem, pathname: string): boolean {
|
||||
@@ -59,8 +79,6 @@ function NavTree({ items, pathname }: { items: NavItem[]; pathname: string }) {
|
||||
|
||||
function NavBranch({ item, depth, pathname }: { item: NavItem; depth: number; pathname: string }) {
|
||||
const enabled = item.is_enabled !== 0
|
||||
if (!enabled) return null
|
||||
|
||||
const label = item.label?.trim() || 'Menu'
|
||||
const url = item.url?.trim() || ''
|
||||
const external = isExternalNavUrl(url)
|
||||
@@ -71,7 +89,7 @@ function NavBranch({ item, depth, pathname }: { item: NavItem; depth: number; pa
|
||||
<i className={`${item.icon_class} me-2`} aria-hidden />
|
||||
) : null
|
||||
|
||||
const children = (item.children ?? []).filter((c) => c.is_enabled !== 0)
|
||||
const children = sortNavTree((item.children ?? []).filter((c) => c.is_enabled !== 0))
|
||||
const hasChildren = children.length > 0
|
||||
const [open, setOpen] = useState(() => hasChildren && branchContainsPath(item, pathname))
|
||||
|
||||
@@ -81,6 +99,8 @@ function NavBranch({ item, depth, pathname }: { item: NavItem; depth: number; pa
|
||||
}
|
||||
}, [hasChildren, item, pathname])
|
||||
|
||||
if (!enabled) return null
|
||||
|
||||
const linkInner = (
|
||||
<>
|
||||
{icon}
|
||||
@@ -187,6 +207,17 @@ export function ManagementLayout() {
|
||||
}
|
||||
} catch (e) {
|
||||
if (!cancelled) {
|
||||
if (e instanceof ApiHttpError && e.status === 401) {
|
||||
logout()
|
||||
navigate('/login', {
|
||||
replace: true,
|
||||
state: {
|
||||
from: `${location.pathname}${location.search}${location.hash}`,
|
||||
message: 'Your session expired. Please sign in again.',
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
setItems([])
|
||||
setMenuError(e instanceof Error ? e.message : 'Unable to load menu.')
|
||||
}
|
||||
@@ -195,7 +226,7 @@ export function ManagementLayout() {
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [])
|
||||
}, [location.hash, location.pathname, location.search, logout, navigate])
|
||||
|
||||
const navTree = useMemo(() => normalizeNavItems(items), [items])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user