| | import PropTypes from 'prop-types'; |
| | import { Activity, useEffect, useRef, useState } from 'react'; |
| | import { useLocation } from 'react-router-dom'; |
| |
|
| | |
| | import { useTheme } from '@mui/material/styles'; |
| | import ClickAwayListener from '@mui/material/ClickAwayListener'; |
| | import Collapse from '@mui/material/Collapse'; |
| | import List from '@mui/material/List'; |
| | import ListItemButton from '@mui/material/ListItemButton'; |
| | import ListItemIcon from '@mui/material/ListItemIcon'; |
| | import ListItemText from '@mui/material/ListItemText'; |
| | import Paper from '@mui/material/Paper'; |
| | import Popper from '@mui/material/Popper'; |
| | import Tooltip from '@mui/material/Tooltip'; |
| | import Typography from '@mui/material/Typography'; |
| | import Box from '@mui/material/Box'; |
| |
|
| | |
| | import NavItem from '../NavItem'; |
| | import Transitions from 'ui-component/extended/Transitions'; |
| |
|
| | import { useGetMenuMaster } from 'api/menu'; |
| | import useConfig from 'hooks/useConfig'; |
| | import useMenuCollapse from 'hooks/useMenuCollapse'; |
| |
|
| | |
| | import { IconChevronDown, IconChevronRight, IconChevronUp } from '@tabler/icons-react'; |
| | import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord'; |
| |
|
| | export default function NavCollapse({ menu, level, parentId }) { |
| | const theme = useTheme(); |
| | const ref = useRef(null); |
| |
|
| | const { |
| | state: { borderRadius } |
| | } = useConfig(); |
| |
|
| | const { menuMaster } = useGetMenuMaster(); |
| | const drawerOpen = menuMaster.isDashboardDrawerOpened; |
| |
|
| | const [open, setOpen] = useState(false); |
| | const [selected, setSelected] = useState(null); |
| | const [anchorEl, setAnchorEl] = useState(null); |
| |
|
| | const handleClickMini = (event) => { |
| | setAnchorEl(null); |
| | if (drawerOpen) { |
| | setOpen(!open); |
| | setSelected(!selected ? menu.id : null); |
| | } else { |
| | setAnchorEl(event?.currentTarget); |
| | } |
| | }; |
| |
|
| | const openMini = Boolean(anchorEl); |
| |
|
| | const handleMiniClose = () => { |
| | setAnchorEl(null); |
| | }; |
| |
|
| | const handleClosePopper = () => { |
| | setOpen(false); |
| | if (!openMini) { |
| | if (!menu.url) { |
| | setSelected(null); |
| | } |
| | } |
| | setAnchorEl(null); |
| | }; |
| |
|
| | const { pathname } = useLocation(); |
| |
|
| | |
| | useMenuCollapse(menu, pathname, openMini, setSelected, setOpen, setAnchorEl); |
| |
|
| | const [hoverStatus, setHover] = useState(false); |
| |
|
| | const compareSize = () => { |
| | const compare = ref.current && ref.current.scrollWidth > ref.current.clientWidth; |
| | setHover(compare); |
| | }; |
| |
|
| | useEffect(() => { |
| | compareSize(); |
| | window.addEventListener('resize', compareSize); |
| | window.removeEventListener('resize', compareSize); |
| | }, []); |
| |
|
| | useEffect(() => { |
| | if (menu.url === pathname) { |
| | setSelected(menu.id); |
| | setAnchorEl(null); |
| | setOpen(true); |
| | } |
| | }, [pathname, menu]); |
| |
|
| | |
| | const menus = menu.children?.map((item) => { |
| | switch (item.type) { |
| | case 'collapse': |
| | return <NavCollapse key={item.id} menu={item} level={level + 1} parentId={parentId} />; |
| | case 'item': |
| | return <NavItem key={item.id} item={item} level={level + 1} />; |
| | default: |
| | return ( |
| | <Typography key={item.id} variant="h6" align="center" sx={{ color: 'error.main' }}> |
| | Menu Items Error |
| | </Typography> |
| | ); |
| | } |
| | }); |
| |
|
| | const isSelected = selected === menu.id; |
| |
|
| | const Icon = menu.icon; |
| | const menuIcon = menu.icon ? ( |
| | <Icon strokeWidth={1.5} size={drawerOpen ? '20px' : '24px'} /> |
| | ) : ( |
| | <FiberManualRecordIcon |
| | sx={{ |
| | width: isSelected ? 8 : 6, |
| | height: isSelected ? 8 : 6 |
| | }} |
| | fontSize={level > 0 ? 'inherit' : 'medium'} |
| | /> |
| | ); |
| |
|
| | const collapseIcon = drawerOpen ? ( |
| | <IconChevronUp stroke={1.5} size="16px" style={{ marginTop: 'auto', marginBottom: 'auto' }} /> |
| | ) : ( |
| | <IconChevronRight stroke={1.5} size="16px" style={{ marginTop: 'auto', marginBottom: 'auto' }} /> |
| | ); |
| |
|
| | return ( |
| | <> |
| | <ListItemButton |
| | sx={{ |
| | zIndex: 1201, |
| | borderRadius: `${borderRadius}px`, |
| | mb: 0.5, |
| | ...(drawerOpen && level !== 1 && { ml: `${level * 18}px` }), |
| | ...(!drawerOpen && { pl: 1.25 }), |
| | ...((!drawerOpen || level !== 1) && { |
| | py: level === 1 ? 0 : 1, |
| | '&:hover': { bgcolor: 'transparent' }, |
| | '&.Mui-selected': { '&:hover': { bgcolor: 'transparent' }, bgcolor: 'transparent' } |
| | }) |
| | }} |
| | selected={isSelected} |
| | {...(!drawerOpen && { onMouseEnter: handleClickMini, onMouseLeave: handleMiniClose })} |
| | className={anchorEl ? 'Mui-selected' : ''} |
| | onClick={handleClickMini} |
| | > |
| | <Activity mode={menuIcon ? 'visible' : 'hidden'}> |
| | <ListItemIcon |
| | sx={{ |
| | minWidth: level === 1 ? 36 : 18, |
| | color: isSelected ? 'secondary.main' : 'text.primary', |
| | ...(!drawerOpen && |
| | level === 1 && { |
| | borderRadius: `${borderRadius}px`, |
| | width: 46, |
| | height: 46, |
| | alignItems: 'center', |
| | justifyContent: 'center', |
| | '&:hover': { bgcolor: 'secondary.light' }, |
| | |
| | ...((isSelected || anchorEl) && { |
| | bgcolor: 'secondary.light', |
| | '&:hover': { bgcolor: 'secondary.light' } |
| | }) |
| | }) |
| | }} |
| | > |
| | {menuIcon} |
| | </ListItemIcon> |
| | </Activity> |
| | {(drawerOpen || (!drawerOpen && level !== 1)) && ( |
| | <Tooltip title={menu.title} disableHoverListener={!hoverStatus}> |
| | <ListItemText |
| | primary={ |
| | <Typography |
| | ref={ref} |
| | noWrap |
| | variant={isSelected || anchorEl ? 'h5' : 'body1'} |
| | sx={{ |
| | color: 'inherit', |
| | overflow: 'hidden', |
| | textOverflow: 'ellipsis', |
| | width: 120 |
| | }} |
| | > |
| | {menu.title} |
| | </Typography> |
| | } |
| | secondary={ |
| | menu.caption && ( |
| | <Typography |
| | gutterBottom |
| | sx={{ |
| | display: 'block', |
| | fontSize: '0.6875rem', |
| | fontWeight: 500, |
| | color: 'text.secondary', |
| | textTransform: 'capitalize', |
| | lineHeight: 1.66 |
| | }} |
| | > |
| | {menu.caption} |
| | </Typography> |
| | ) |
| | } |
| | /> |
| | </Tooltip> |
| | )} |
| | |
| | {openMini || open ? collapseIcon : <IconChevronDown stroke={1.5} size="16px" style={{ marginTop: 'auto', marginBottom: 'auto' }} />} |
| | |
| | <Activity mode={!drawerOpen ? 'visible' : 'hidden'}> |
| | <Popper |
| | open={openMini} |
| | anchorEl={anchorEl} |
| | placement="right-start" |
| | modifiers={[ |
| | { |
| | name: 'offset', |
| | options: { |
| | offset: [-12, 0] |
| | } |
| | } |
| | ]} |
| | sx={{ |
| | overflow: 'visible', |
| | zIndex: 2001, |
| | minWidth: 180, |
| | '&:before': { |
| | content: '""', |
| | bgcolor: 'background.paper', |
| | transform: 'translateY(-50%) rotate(45deg)', |
| | zIndex: 120, |
| | borderLeft: `1px solid`, |
| | borderBottom: `1px solid`, |
| | borderColor: 'divider' |
| | } |
| | }} |
| | > |
| | {({ TransitionProps }) => ( |
| | <Transitions in={openMini} {...TransitionProps}> |
| | <Paper |
| | sx={{ |
| | overflow: 'hidden', |
| | boxShadow: theme.shadows[8], |
| | backgroundImage: 'none' |
| | }} |
| | > |
| | <ClickAwayListener onClickAway={handleClosePopper}> |
| | <Box>{menus}</Box> |
| | </ClickAwayListener> |
| | </Paper> |
| | </Transitions> |
| | )} |
| | </Popper> |
| | </Activity> |
| | </ListItemButton> |
| | <Activity mode={drawerOpen ? 'visible' : 'hidden'}> |
| | <Collapse in={open} timeout="auto" unmountOnExit> |
| | <Activity mode={open ? 'visible' : 'hidden'}> |
| | <List |
| | disablePadding |
| | sx={{ |
| | position: 'relative', |
| | '&:after': { |
| | content: "''", |
| | position: 'absolute', |
| | left: '25px', |
| | top: 0, |
| | height: '100%', |
| | width: '1px', |
| | opacity: 1, |
| | bgcolor: 'primary.light' |
| | } |
| | }} |
| | > |
| | {menus} |
| | </List> |
| | </Activity> |
| | </Collapse> |
| | </Activity> |
| | </> |
| | ); |
| | } |
| |
|
| | NavCollapse.propTypes = { menu: PropTypes.any, level: PropTypes.number, parentId: PropTypes.string }; |
| |
|