erp-platform/ui/src/components/template/VerticalMenuContent/VerticalMenuContent.tsx

160 lines
4.6 KiB
TypeScript
Raw Normal View History

2025-05-06 06:45:49 +00:00
import type { NavigationTree } from '@/@types/navigation'
import { Direction, NavMode } from '@/@types/theme'
import { PermissionCheck } from '@/components/shared'
import Menu from '@/components/ui/Menu'
import { themeConfig } from '@/configs/theme.config'
import {
NAV_ITEM_TYPE_COLLAPSE,
NAV_ITEM_TYPE_ITEM,
NAV_ITEM_TYPE_TITLE,
} from '@/constants/navigation.constant'
import useMenuActive from '@/utils/hooks/useMenuActive'
import { useEffect, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { Link, useLocation } from 'react-router-dom'
import VerticalCollapsedMenuItem from './VerticalCollapsedMenuItem'
import VerticalSingleMenuItem from './VerticalSingleMenuItem'
import MenuCollapse from '@/components/ui/Menu/MenuCollapse'
import VerticalMenuIcon from './VerticalMenuIcon'
import { MenuItem } from '@/components/ui'
export interface VerticalMenuContentProps {
navMode: NavMode
collapsed?: boolean
routeKey: string
navigationTree?: NavigationTree[]
userAuthority: string[]
onMenuItemClick?: () => void
direction?: Direction
}
const { MenuGroup } = Menu
const VerticalMenuContent = (props: VerticalMenuContentProps) => {
const { pathname } = useLocation()
const {
navMode = themeConfig.navMode,
collapsed,
routeKey,
navigationTree = [],
userAuthority = [],
onMenuItemClick,
direction = themeConfig.direction,
} = props
const { t } = useTranslation()
const [defaultExpandedKeys, setDefaultExpandedKeys] = useState<string[]>([])
const [defaultActiveKeys, setDefaultActiveKeys] = useState<string[]>([])
const { activedRoute } = useMenuActive(navigationTree, routeKey, pathname)
useEffect(() => {
const expandedKeys = [
activedRoute.route?.parentKey,
activedRoute.parentRoute?.parentKey,
].filter(Boolean)
const activeKeys = [
activedRoute.route?.key,
activedRoute.route?.parentKey,
activedRoute.parentRoute?.parentKey,
].filter(Boolean)
setDefaultActiveKeys(activeKeys as string[])
setDefaultExpandedKeys(expandedKeys as string[])
}, [activedRoute])
const handleLinkClick = () => {
onMenuItemClick?.()
}
const getNavItem = (nav: NavigationTree) => {
if (nav.subMenu.length === 0 && nav.type === NAV_ITEM_TYPE_ITEM) {
return (
<VerticalSingleMenuItem
key={nav.key}
nav={nav}
sideCollapsed={collapsed}
userAuthority={userAuthority}
direction={direction}
onLinkClick={handleLinkClick}
/>
)
}
if (nav.subMenu.length > 0 && nav.type === NAV_ITEM_TYPE_COLLAPSE) {
return (
<VerticalCollapsedMenuItem
key={nav.key}
nav={nav}
sideCollapsed={collapsed}
userAuthority={userAuthority}
direction={direction}
onLinkClick={onMenuItemClick}
/>
)
}
if (nav.type === NAV_ITEM_TYPE_TITLE) {
if (nav.subMenu.length > 0) {
return (
<PermissionCheck key={nav.key} permissions={nav.authority}>
<MenuCollapse
key={nav.key}
label={
<>
<VerticalMenuIcon icon={nav.icon} />
<span>
<Trans i18nKey={nav.translateKey} defaults={nav.title} />
</span>
</>
}
eventKey={nav.key}
expanded={false}
>
{nav.subMenu.map((subNav) =>
subNav.subMenu.length > 0 ? (
<VerticalCollapsedMenuItem
key={subNav.key}
nav={subNav}
sideCollapsed={collapsed}
userAuthority={userAuthority}
direction={direction}
onLinkClick={onMenuItemClick}
/>
) : (
<VerticalSingleMenuItem
key={subNav.key}
nav={subNav}
sideCollapsed={collapsed}
userAuthority={userAuthority}
direction={direction}
onLinkClick={onMenuItemClick}
/>
),
)}
</MenuCollapse>
</PermissionCheck>
)
} else {
return <MenuGroup label={nav.title} />
}
}
}
return (
<Menu
className="px-4 pb-4"
variant={navMode}
sideCollapsed={collapsed}
defaultActiveKeys={defaultActiveKeys}
defaultExpandedKeys={defaultExpandedKeys}
>
{navigationTree.map((nav) => getNavItem(nav))}
</Menu>
)
}
export default VerticalMenuContent