import {
cloneElement,
isValidElement,
useState,
useEffect,
useContext
} from 'react'
import { Layout, Menu, Flex, Button, Divider } from 'antd'
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'
import { AuthContext } from '../context/AuthContext'
import { getSidebarIconNode } from '../../Icons/sidebarIconMap'
import SimpleBar from 'simplebar-react'
import { useThemeContext } from '../context/ThemeContext'
import { filterSidebarItemsByListPermission } from '../../../database/Sidebars'
import Tooltip from './Tooltip'
import KeyboardShortcut from './KeyboardShortcut'
const { Sider } = Layout
const CollapsedItemIcon = ({ className, icon, title }) => {
const iconNode = isValidElement(icon)
? cloneElement(icon, {
className: [icon.props.className, className].filter(Boolean).join(' ')
})
: icon
return (
{iconNode ?? }
)
}
CollapsedItemIcon.propTypes = {
className: PropTypes.string,
icon: PropTypes.node,
title: PropTypes.node
}
const DashboardSidebar = ({
items = [],
selectedKey = '',
onCollapse,
collapsed: collapsedProp,
collapsedWidth: collapsedWidthProp,
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 { isDarkMode } = useThemeContext()
const { isElectron } = useContext(ElectronContext)
const collapsedWidth = collapsedWidthProp ?? (isElectron ? 55 : 80)
const { userProfile } = useContext(AuthContext)
const allowedItems = filterSidebarItemsByListPermission(items, userProfile)
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, showCollapsedTooltip = true) => {
return items.map((item) => {
if (item?.type === 'divider') {
return item
}
const icon = item.icon || getSidebarIconNode(item.iconKey)
const mappedItem = {
key: item.key,
icon:
collapsed && !isMobile && showCollapsedTooltip && !item.children ? (
) : (
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, false)
}
return mappedItem
})
}
// Map items recursively
const _items = mapItemsRecursively(allowedItems)
if (isMobile) {
return null
}
return (
handleCollapse(!collapsed)}
>
:
}
style={{ flexGrow: 1, width: '100%' }}
onClick={() => handleCollapse(!collapsed)}
/>
)
}
DashboardSidebar.propTypes = {
items: PropTypes.array.isRequired,
selectedKey: PropTypes.string,
onCollapse: PropTypes.func,
collapsed: PropTypes.bool,
collapsedWidth: PropTypes.number,
key: PropTypes.string
}
export default DashboardSidebar