127 lines
3.4 KiB
JavaScript

import { 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}
className={isElectron ? 'electron-sider' : ''}
>
<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