sozsoft-platform/ui/src/components/template/StackedSideNav/StackedSideNavMini.tsx
Sedat Öztürk 429227df1d Initial
2026-02-24 23:44:16 +03:00

150 lines
4.5 KiB
TypeScript

import type { CommonProps } from '@/proxy/common'
import type { NavigationTree } from '@/proxy/menus/navigation'
import type { Direction, Mode, NavMode } from '@/proxy/theme/models'
import { PermissionCheck } from '@/components/shared'
import Logo from '@/components/template/Logo'
import Menu from '@/components/ui/Menu'
import ScrollBar from '@/components/ui/ScrollBar'
import navigationIcon from '@/proxy/menus/navigation-icon.config'
import { NAV_ITEM_TYPE_ITEM } from '@/constants/navigation.constant'
import {
NAV_MODE_DARK,
NAV_MODE_THEMED,
NAV_MODE_TRANSPARENT,
SIDE_NAV_CONTENT_GUTTER,
} from '@/constants/theme.constant'
import { useStoreState } from '@/store'
import useMenuActive from '@/utils/hooks/useMenuActive'
import isEmpty from 'lodash/isEmpty'
import React from 'react'
import { useEffect } from 'react'
import { FaQuestionCircle } from 'react-icons/fa'
import { Link, useLocation } from 'react-router-dom'
export type SelectedMenuItem = {
key?: string
title?: string
menu?: NavigationTree[]
translateKey?: string
}
interface StackedSideNavMiniProps extends CommonProps {
className?: string
navMode: NavMode
onChange: (item: SelectedMenuItem) => void
routeKey: string
activeKeys: string[]
onSetActiveKey: (activeKey: string[]) => void
userAuthority: string[]
mode: Mode
direction: Direction
}
const StackedSideNavMini = (props: StackedSideNavMiniProps) => {
const { pathname } = useLocation()
const {
navMode,
onChange,
routeKey,
activeKeys,
onSetActiveKey,
mode,
direction,
...rest
} = props
const { mainMenu: navigationConfig } = useStoreState((state) => state.abpConfig.menu)
const { includedRouteTree } = useMenuActive(navigationConfig, routeKey, pathname)
const logoMode = () => {
if (navMode === NAV_MODE_THEMED) {
return NAV_MODE_DARK
}
if (navMode === NAV_MODE_TRANSPARENT) {
return mode
}
return navMode
}
const handleMenuItemSelect = ({ key, title, menu, translateKey }: SelectedMenuItem) => {
onChange({ title, menu, translateKey })
onSetActiveKey([key as string])
}
const handleLinkMenuItemSelect = ({ key }: SelectedMenuItem) => {
onChange({})
onSetActiveKey([key as string])
}
useEffect(() => {
if (includedRouteTree.type !== NAV_ITEM_TYPE_ITEM && !isEmpty(includedRouteTree)) {
onChange({
key: includedRouteTree.key,
title: includedRouteTree.title,
menu: includedRouteTree.subMenu,
translateKey: includedRouteTree.translateKey,
})
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [includedRouteTree.key])
return (
<div {...rest}>
<Logo mode={logoMode()} type="streamline" className={SIDE_NAV_CONTENT_GUTTER} />
<ScrollBar autoHide direction={direction}>
<Menu
className="px-6 pb-4 py-1"
variant={navMode}
defaultActiveKeys={activeKeys || [includedRouteTree.key]}
>
{navigationConfig.map((nav) => (
<PermissionCheck key={nav.key} permissions={nav.authority}>
{nav.subMenu && nav.subMenu.length > 0 ? (
<Menu.MenuItem
icon={nav.icon}
eventKey={nav.key}
className="mb-2"
onSelect={() =>
handleMenuItemSelect({
key: nav.key,
title: nav.title,
menu: nav.subMenu,
translateKey: nav.translateKey,
})
}
>
<div className="text-2xl">
{React.createElement(navigationIcon[nav.icon] || FaQuestionCircle)}{' '}
</div>
</Menu.MenuItem>
) : (
<Link
to={nav.path}
className="flex items-center h-full w-full"
onClick={() =>
handleLinkMenuItemSelect({
key: nav.key,
})
}
>
<Menu.MenuItem icon={nav.icon} eventKey={nav.key} className="mb-2">
<div className="text-2xl">
{React.createElement(navigationIcon[nav.icon] || FaQuestionCircle)}
</div>
</Menu.MenuItem>
</Link>
)}
</PermissionCheck>
))}
</Menu>
</ScrollBar>
</div>
)
}
export default StackedSideNavMini