- Introduced a recursive function to map sidebar items and their children, enhancing the structure and maintainability of the component. - Added onClick functionality for items with paths, improving navigation capabilities. - Improved code readability by restructuring the item mapping logic.
122 lines
3.4 KiB
JavaScript
122 lines
3.4 KiB
JavaScript
import React, { useState, useEffect, useContext } from 'react'
|
|
import { Layout, Menu, Flex, Button } from 'antd'
|
|
import { CaretDownFilled } from '@ant-design/icons'
|
|
import CollapseSidebarIcon from '../../Icons/CollapseSidebarIcon'
|
|
import ExpandSidebarIcon from '../../Icons/ExpandSidebarIcon'
|
|
import { useMediaQuery } from 'react-responsive'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import PropTypes from 'prop-types'
|
|
import { ElectronContext } from '../context/ElectronContext'
|
|
const { Sider } = Layout
|
|
|
|
const DashboardSidebar = ({
|
|
items = [],
|
|
selectedKey = '',
|
|
onCollapse,
|
|
collapsed: collapsedProp,
|
|
key = 'DashboardSidebar_collapseState'
|
|
}) => {
|
|
const [collapsed, setCollapsed] = useState(() => {
|
|
if (typeof collapsedProp === 'boolean') return collapsedProp
|
|
const savedState = sessionStorage.getItem(key)
|
|
return savedState ? JSON.parse(savedState) : false
|
|
})
|
|
const isMobile = useMediaQuery({ maxWidth: 768 })
|
|
const navigate = useNavigate()
|
|
|
|
const { isElectron } = useContext(ElectronContext)
|
|
|
|
useEffect(() => {
|
|
if (typeof collapsedProp === 'boolean') {
|
|
setCollapsed(collapsedProp)
|
|
}
|
|
}, [collapsedProp])
|
|
|
|
const handleCollapse = (newCollapsed) => {
|
|
setCollapsed(newCollapsed)
|
|
sessionStorage.setItem(key, JSON.stringify(newCollapsed))
|
|
if (onCollapse) onCollapse(newCollapsed)
|
|
}
|
|
|
|
// Recursive function to map items and their children
|
|
const mapItemsRecursively = (items) => {
|
|
return items.map((item) => {
|
|
if (item?.type === 'divider') {
|
|
return item
|
|
}
|
|
|
|
const mappedItem = {
|
|
key: item.key,
|
|
icon: item.icon,
|
|
label: item.label
|
|
}
|
|
|
|
// Add onClick for items with paths (leaf nodes)
|
|
if (item.path) {
|
|
mappedItem.onClick = () => navigate(item.path)
|
|
}
|
|
|
|
// Recursively map children if they exist
|
|
if (item?.children && Array.isArray(item.children)) {
|
|
mappedItem.children = mapItemsRecursively(item.children)
|
|
}
|
|
|
|
return mappedItem
|
|
})
|
|
}
|
|
|
|
// Map items recursively
|
|
const _items = mapItemsRecursively(items)
|
|
|
|
if (isMobile) {
|
|
return (
|
|
<Menu
|
|
mode='horizontal'
|
|
selectedKeys={[selectedKey]}
|
|
items={_items}
|
|
_internalDisableMenuItemTitleTooltip
|
|
style={{ lineHeight: '40px' }}
|
|
overflowedIndicator={<Button type='text' icon={<CaretDownFilled />} />}
|
|
/>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<Sider width={250} theme='light' collapsed={collapsed}>
|
|
<Flex
|
|
style={{ height: '100%' }}
|
|
vertical
|
|
className='ant-menu-root ant-menu-inline ant-menu-light'
|
|
>
|
|
<Menu
|
|
mode='inline'
|
|
selectedKeys={[selectedKey]}
|
|
items={_items}
|
|
className={isElectron ? 'electron-sidebar' : null}
|
|
style={{ flexGrow: 1, border: 'none' }}
|
|
_internalDisableMenuItemTitleTooltip
|
|
/>
|
|
<Flex style={{ padding: '4px', width: '100%' }}>
|
|
<Button
|
|
size='large'
|
|
type='text'
|
|
icon={collapsed ? <ExpandSidebarIcon /> : <CollapseSidebarIcon />}
|
|
style={{ flexGrow: 1 }}
|
|
onClick={() => handleCollapse(!collapsed)}
|
|
/>
|
|
</Flex>
|
|
</Flex>
|
|
</Sider>
|
|
)
|
|
}
|
|
|
|
DashboardSidebar.propTypes = {
|
|
items: PropTypes.array.isRequired,
|
|
selectedKey: PropTypes.string,
|
|
onCollapse: PropTypes.func,
|
|
collapsed: PropTypes.bool,
|
|
key: PropTypes.string
|
|
}
|
|
|
|
export default DashboardSidebar
|