initial commit
This commit is contained in:
32
src/layout/MainLayout/Drawer/DrawerContent/NavCard.js
Normal file
32
src/layout/MainLayout/Drawer/DrawerContent/NavCard.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// material-ui
|
||||
import { Button, Link, CardMedia, Stack, Typography } from '@mui/material';
|
||||
|
||||
// project import
|
||||
import MainCard from 'components/MainCard';
|
||||
|
||||
// assets
|
||||
import avatar from 'assets/images/users/avatar-group.png';
|
||||
import AnimateButton from 'components/@extended/AnimateButton';
|
||||
|
||||
// ==============================|| DRAWER CONTENT - NAVIGATION CARD ||============================== //
|
||||
|
||||
const NavCard = () => (
|
||||
<MainCard sx={{ bgcolor: 'grey.50', m: 3 }}>
|
||||
<Stack alignItems="center" spacing={2.5}>
|
||||
<CardMedia component="img" image={avatar} />
|
||||
<Stack alignItems="center">
|
||||
<Typography variant="h5">Help?</Typography>
|
||||
<Typography variant="h6" color="secondary">
|
||||
Get to resolve query
|
||||
</Typography>
|
||||
</Stack>
|
||||
<AnimateButton>
|
||||
<Button variant="shadow" size="small" component={Link} href="https://codedthemes.support-hub.io/" target="_blank">
|
||||
Support
|
||||
</Button>
|
||||
</AnimateButton>
|
||||
</Stack>
|
||||
</MainCard>
|
||||
);
|
||||
|
||||
export default NavCard;
|
||||
@@ -0,0 +1,503 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { useEffect, useState, useMemo } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
|
||||
// material-ui
|
||||
import { styled, useTheme } from '@mui/material/styles';
|
||||
import {
|
||||
Box,
|
||||
Collapse,
|
||||
ClickAwayListener,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Paper,
|
||||
Popper,
|
||||
Typography,
|
||||
useMediaQuery
|
||||
} from '@mui/material';
|
||||
|
||||
// project import
|
||||
import NavItem from './NavItem';
|
||||
import Dot from 'components/@extended/Dot';
|
||||
import SimpleBar from 'components/third-party/SimpleBar';
|
||||
import Transitions from 'components/@extended/Transitions';
|
||||
|
||||
import useConfig from 'hooks/useConfig';
|
||||
import { dispatch, useSelector } from 'store';
|
||||
import { activeItem } from 'store/reducers/menu';
|
||||
import { MenuOrientation, ThemeMode } from 'config';
|
||||
|
||||
// assets
|
||||
import { BorderOutlined, DownOutlined, UpOutlined, RightOutlined } from '@ant-design/icons';
|
||||
|
||||
// mini-menu - wrapper
|
||||
const PopperStyled = styled(Popper)(({ theme }) => ({
|
||||
overflow: 'visible',
|
||||
zIndex: 1202,
|
||||
minWidth: 180,
|
||||
'&:before': {
|
||||
content: '""',
|
||||
display: 'block',
|
||||
position: 'absolute',
|
||||
top: 38,
|
||||
left: -5,
|
||||
width: 10,
|
||||
height: 10,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
transform: 'translateY(-50%) rotate(45deg)',
|
||||
zIndex: 120,
|
||||
borderLeft: `1px solid ${theme.palette.grey.A800}`,
|
||||
borderBottom: `1px solid ${theme.palette.grey.A800}`
|
||||
}
|
||||
}));
|
||||
|
||||
// ==============================|| NAVIGATION - LIST COLLAPSE ||============================== //
|
||||
|
||||
const NavCollapse = ({ menu, level, parentId, setSelectedItems, selectedItems, setSelectedLevel, selectedLevel }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const downLG = useMediaQuery(theme.breakpoints.down('lg'));
|
||||
const menuState = useSelector((state) => state.menu);
|
||||
|
||||
const { drawerOpen } = menuState;
|
||||
const { menuOrientation } = useConfig();
|
||||
const navigation = useNavigate();
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [selected, setSelected] = useState(null);
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
|
||||
const handleClick = (event) => {
|
||||
setAnchorEl(null);
|
||||
setSelectedLevel(level);
|
||||
if (drawerOpen) {
|
||||
setOpen(!open);
|
||||
setSelected(!selected ? menu.id : null);
|
||||
setSelectedItems(!selected ? menu.id : '');
|
||||
if (menu.url) navigation(`${menu.url}`);
|
||||
} else {
|
||||
setAnchorEl(event?.currentTarget);
|
||||
}
|
||||
};
|
||||
|
||||
const handlerIconLink = () => {
|
||||
if (!drawerOpen) {
|
||||
if (menu.url) navigation(`${menu.url}`);
|
||||
setSelected(menu.id);
|
||||
}
|
||||
};
|
||||
|
||||
const handleHover = (event) => {
|
||||
setAnchorEl(event?.currentTarget);
|
||||
if (!drawerOpen) {
|
||||
setSelected(menu.id);
|
||||
}
|
||||
};
|
||||
|
||||
const miniMenuOpened = Boolean(anchorEl);
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
if (!miniMenuOpened) {
|
||||
if (!menu.url) {
|
||||
setSelected(null);
|
||||
}
|
||||
}
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
useMemo(() => {
|
||||
if (selected === selectedItems) {
|
||||
if (level === 1) {
|
||||
setOpen(true);
|
||||
}
|
||||
} else {
|
||||
if (level === selectedLevel) {
|
||||
setOpen(false);
|
||||
if (!miniMenuOpened && !drawerOpen && !selected) {
|
||||
setSelected(null);
|
||||
}
|
||||
if (drawerOpen) {
|
||||
setSelected(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [selectedItems, level, selected, miniMenuOpened, drawerOpen, selectedLevel]);
|
||||
|
||||
const { pathname } = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
if (pathname === menu.url) {
|
||||
setSelected(menu.id);
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
}, [pathname]);
|
||||
|
||||
const checkOpenForParent = (child, id) => {
|
||||
child.forEach((item) => {
|
||||
if (item.url === pathname) {
|
||||
setOpen(true);
|
||||
setSelected(id);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setOpen(false);
|
||||
if (!miniMenuOpened) {
|
||||
setSelected(null);
|
||||
}
|
||||
if (miniMenuOpened) setAnchorEl(null);
|
||||
if (menu.children) {
|
||||
menu.children.forEach((item) => {
|
||||
if (item.children?.length) {
|
||||
checkOpenForParent(item.children, menu.id);
|
||||
}
|
||||
if (pathname && pathname.includes('product-details')) {
|
||||
if (item.url && item.url.includes('product-details')) {
|
||||
setSelected(menu.id);
|
||||
setOpen(true);
|
||||
}
|
||||
}
|
||||
if (item.url === pathname) {
|
||||
setSelected(menu.id);
|
||||
setOpen(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [pathname, menu.children]);
|
||||
|
||||
useEffect(() => {
|
||||
if (menu.url === pathname) {
|
||||
dispatch(activeItem({ openItem: [menu.id] }));
|
||||
setSelected(menu.id);
|
||||
setAnchorEl(null);
|
||||
setOpen(true);
|
||||
}
|
||||
}, [pathname, menu]);
|
||||
|
||||
const navCollapse = menu.children?.map((item) => {
|
||||
switch (item.type) {
|
||||
case 'collapse':
|
||||
return (
|
||||
<NavCollapse
|
||||
key={item.id}
|
||||
setSelectedItems={setSelectedItems}
|
||||
setSelectedLevel={setSelectedLevel}
|
||||
selectedLevel={selectedLevel}
|
||||
selectedItems={selectedItems}
|
||||
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" color="error" align="center">
|
||||
Fix - Collapse or Item
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const isSelected = selected === menu.id;
|
||||
const borderIcon = level === 1 ? <BorderOutlined style={{ fontSize: '1rem' }} /> : false;
|
||||
const Icon = menu.icon;
|
||||
const menuIcon = menu.icon ? <Icon style={{ fontSize: drawerOpen ? '1rem' : '1.25rem', color: 'white' }} /> : borderIcon;
|
||||
// const textColor = theme.palette.mode === ThemeMode.DARK ? 'grey.400' : 'text.primary';
|
||||
// const iconSelectedColor = theme.palette.mode === ThemeMode.DARK && drawerOpen ? theme.palette.text.primary : theme.palette.primary.main;
|
||||
const popperId = miniMenuOpened ? `collapse-pop-${menu.id}` : undefined;
|
||||
const FlexBox = { display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' };
|
||||
const textColor = 'white';
|
||||
const iconSelectedColor = 'white';
|
||||
// const isSelected = true;
|
||||
|
||||
return (
|
||||
<>
|
||||
{menuOrientation === MenuOrientation.VERTICAL || downLG ? (
|
||||
<>
|
||||
<ListItemButton
|
||||
disableRipple
|
||||
selected={selected === menu.id}
|
||||
{...(!drawerOpen && { onMouseEnter: handleClick, onMouseLeave: handleClose })}
|
||||
onClick={handleClick}
|
||||
sx={{
|
||||
pl: drawerOpen ? `${level * 28}px` : 1.5,
|
||||
py: !drawerOpen && level === 1 ? 1.25 : 1,
|
||||
|
||||
...(drawerOpen && {
|
||||
'&:hover': {
|
||||
// bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter'
|
||||
bgcolor: '#7b1fa2'
|
||||
},
|
||||
'&.Mui-selected': {
|
||||
bgcolor: 'transparent',
|
||||
color: iconSelectedColor,
|
||||
'&:hover': { color: iconSelectedColor, bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'transparent' }
|
||||
}
|
||||
}),
|
||||
...(!drawerOpen && {
|
||||
'&:hover': {
|
||||
bgcolor: 'transparent'
|
||||
// bgcolor:'#7b1fa2'
|
||||
},
|
||||
'&.Mui-selected': {
|
||||
'&:hover': {
|
||||
bgcolor: 'transparent'
|
||||
},
|
||||
bgcolor: 'transparent'
|
||||
}
|
||||
})
|
||||
}}
|
||||
>
|
||||
{menuIcon && (
|
||||
<ListItemIcon
|
||||
onClick={handlerIconLink}
|
||||
sx={{
|
||||
minWidth: 28,
|
||||
// color: selected === menu.id ? 'primary.main' : textColor,
|
||||
// color: selected === menu.id ? textColor : textColor,
|
||||
// bgcolor:'white',
|
||||
// color:'white',
|
||||
...(!drawerOpen && {
|
||||
borderRadius: 1.5,
|
||||
width: 36,
|
||||
height: 36,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
'&:hover': {
|
||||
// bgcolor: theme.palette.mode === ThemeMode.DARK ? 'secondary.light' : 'secondary.lighter'
|
||||
bgcolor: '#7b1fa2',
|
||||
color: 'white'
|
||||
}
|
||||
}),
|
||||
...(!drawerOpen &&
|
||||
selected === menu.id && {
|
||||
bgcolor: 'primary.light',
|
||||
color: 'primary.main',
|
||||
'&:hover': {
|
||||
bgcolor: '#7b1fa2',
|
||||
color: 'primary.main'
|
||||
}
|
||||
})
|
||||
}}
|
||||
>
|
||||
{menuIcon}
|
||||
</ListItemIcon>
|
||||
)}
|
||||
{(drawerOpen || (!drawerOpen && level !== 1)) && (
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography
|
||||
variant="h6"
|
||||
// color={selected === menu.id ? 'primary' : textColor}
|
||||
// color={'white'}
|
||||
color={selected === menu.id ? textColor : textColor}
|
||||
>
|
||||
{menu.title}
|
||||
</Typography>
|
||||
}
|
||||
secondary={
|
||||
menu.caption && (
|
||||
<Typography variant="caption" color="secondary">
|
||||
{menu.caption}
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{(drawerOpen || (!drawerOpen && level !== 1)) &&
|
||||
(miniMenuOpened || open ? (
|
||||
<UpOutlined
|
||||
style={{
|
||||
fontSize: '0.625rem',
|
||||
marginLeft: 1,
|
||||
// color: theme.palette.primary.main
|
||||
color: 'white'
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<DownOutlined
|
||||
style={{
|
||||
fontSize: '0.625rem',
|
||||
marginLeft: 1,
|
||||
color: 'white'
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{!drawerOpen && (
|
||||
<PopperStyled
|
||||
open={miniMenuOpened}
|
||||
anchorEl={anchorEl}
|
||||
placement="right-start"
|
||||
style={{
|
||||
zIndex: 2001
|
||||
}}
|
||||
popperOptions={{
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [-12, 1]
|
||||
}
|
||||
}
|
||||
]
|
||||
}}
|
||||
>
|
||||
{({ TransitionProps }) => (
|
||||
<Transitions in={miniMenuOpened} {...TransitionProps}>
|
||||
<Paper
|
||||
sx={{
|
||||
overflow: 'hidden',
|
||||
mt: 1.5,
|
||||
boxShadow: theme.customShadows.z1,
|
||||
backgroundImage: 'none',
|
||||
border: `2px solid ${theme.palette.primary.main}`,
|
||||
width: 'auto'
|
||||
}}
|
||||
>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<SimpleBar
|
||||
sx={{
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
maxHeight: 'calc(100vh - 170px)'
|
||||
}}
|
||||
>
|
||||
{navCollapse}
|
||||
</SimpleBar>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Transitions>
|
||||
)}
|
||||
</PopperStyled>
|
||||
)}
|
||||
</ListItemButton>
|
||||
{drawerOpen && (
|
||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||
<List sx={{ p: 0 }}>{navCollapse}</List>
|
||||
</Collapse>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<ListItemButton
|
||||
id={`boundary-${popperId}`}
|
||||
disableRipple
|
||||
selected={isSelected}
|
||||
onMouseEnter={handleHover}
|
||||
onMouseLeave={handleClose}
|
||||
onClick={handleHover}
|
||||
aria-describedby={popperId}
|
||||
sx={{
|
||||
'&.Mui-selected': {
|
||||
bgcolor: 'transparent'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Box onClick={handlerIconLink} sx={FlexBox}>
|
||||
{menuIcon && (
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
my: 'auto',
|
||||
minWidth: !menu.icon ? 18 : 36
|
||||
// color: theme.palette.secondary.dark
|
||||
// color:'white'
|
||||
}}
|
||||
>
|
||||
{menuIcon}
|
||||
</ListItemIcon>
|
||||
)}
|
||||
{!menuIcon && level !== 1 && (
|
||||
<ListItemIcon
|
||||
sx={{ my: 'auto', minWidth: !menu.icon ? 18 : 36, bgcolor: 'transparent', '&:hover': { bgcolor: 'transparent' } }}
|
||||
>
|
||||
<Dot size={4} color={isSelected ? 'primary' : 'secondary'} />
|
||||
</ListItemIcon>
|
||||
)}
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography
|
||||
variant="body1"
|
||||
// color="inherit"
|
||||
// color="white"
|
||||
sx={{ my: 'auto' }}
|
||||
>
|
||||
{menu.title}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
{miniMenuOpened ? <RightOutlined /> : <DownOutlined />}
|
||||
</Box>
|
||||
|
||||
{anchorEl && (
|
||||
<PopperStyled
|
||||
id={popperId}
|
||||
open={miniMenuOpened}
|
||||
anchorEl={anchorEl}
|
||||
placement="right-start"
|
||||
style={{
|
||||
zIndex: 2001
|
||||
}}
|
||||
modifiers={[
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [-10, 0]
|
||||
}
|
||||
}
|
||||
]}
|
||||
>
|
||||
{({ TransitionProps }) => (
|
||||
<Transitions in={miniMenuOpened} {...TransitionProps}>
|
||||
<Paper
|
||||
sx={{
|
||||
overflow: 'hidden',
|
||||
mt: 1.5,
|
||||
py: 0.5,
|
||||
boxShadow: theme.shadows[8],
|
||||
backgroundImage: 'none'
|
||||
}}
|
||||
>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<SimpleBar
|
||||
sx={{
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
maxHeight: 'calc(100vh - 170px)'
|
||||
}}
|
||||
>
|
||||
{navCollapse}
|
||||
</SimpleBar>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Transitions>
|
||||
)}
|
||||
</PopperStyled>
|
||||
)}
|
||||
</ListItemButton>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
NavCollapse.propTypes = {
|
||||
menu: PropTypes.object,
|
||||
level: PropTypes.number,
|
||||
parentId: PropTypes.string,
|
||||
setSelectedItems: PropTypes.func,
|
||||
selectedItems: PropTypes.string,
|
||||
setSelectedLevel: PropTypes.func,
|
||||
selectedLevel: PropTypes.number
|
||||
};
|
||||
|
||||
export default NavCollapse;
|
||||
@@ -0,0 +1,343 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { Fragment, useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router';
|
||||
|
||||
// material-ui
|
||||
import { styled, useTheme } from '@mui/material/styles';
|
||||
import {
|
||||
Box,
|
||||
ClickAwayListener,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Paper,
|
||||
Popper,
|
||||
Typography,
|
||||
useMediaQuery
|
||||
} from '@mui/material';
|
||||
|
||||
// third-party
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
// project import
|
||||
import NavItem from './NavItem';
|
||||
import NavCollapse from './NavCollapse';
|
||||
import SimpleBar from 'components/third-party/SimpleBar';
|
||||
import Transitions from 'components/@extended/Transitions';
|
||||
|
||||
import { MenuOrientation } from 'config';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
import { dispatch, useSelector } from 'store';
|
||||
import { activeID } from 'store/reducers/menu';
|
||||
|
||||
// assets
|
||||
import { DownOutlined, RightOutlined } from '@ant-design/icons';
|
||||
|
||||
// ==============================|| NAVIGATION - LIST GROUP ||============================== //
|
||||
|
||||
const PopperStyled = styled(Popper)(({ theme }) => ({
|
||||
overflow: 'visible',
|
||||
zIndex: 1202,
|
||||
minWidth: 180,
|
||||
'&:before': {
|
||||
content: '""',
|
||||
display: 'block',
|
||||
position: 'absolute',
|
||||
top: 5,
|
||||
left: 32,
|
||||
width: 12,
|
||||
height: 12,
|
||||
transform: 'translateY(-50%) rotate(45deg)',
|
||||
zIndex: 120,
|
||||
borderWidth: '6px',
|
||||
borderStyle: 'solid',
|
||||
borderColor: `${theme.palette.background.paper} transparent transparent ${theme.palette.background.paper}`
|
||||
}
|
||||
}));
|
||||
|
||||
const NavGroup = ({ item, lastItem, remItems, lastItemId, setSelectedItems, selectedItems, setSelectedLevel, selectedLevel }) => {
|
||||
const theme = useTheme();
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const { menuOrientation } = useConfig();
|
||||
const menu = useSelector((state) => state.menu);
|
||||
const { drawerOpen, selectedID } = menu;
|
||||
|
||||
const downLG = useMediaQuery(theme.breakpoints.down('lg'));
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const [currentItem, setCurrentItem] = useState(item);
|
||||
|
||||
const openMini = Boolean(anchorEl);
|
||||
|
||||
useEffect(() => {
|
||||
if (lastItem) {
|
||||
if (item.id === lastItemId) {
|
||||
const localItem = { ...item };
|
||||
const elements = remItems.map((ele) => ele.elements);
|
||||
localItem.children = elements.flat(1);
|
||||
setCurrentItem(localItem);
|
||||
} else {
|
||||
setCurrentItem(item);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [item, lastItem, downLG]);
|
||||
|
||||
const checkOpenForParent = (child, id) => {
|
||||
child.forEach((ele) => {
|
||||
if (ele.children?.length) {
|
||||
checkOpenForParent(ele.children, currentItem.id);
|
||||
}
|
||||
if (ele.url === pathname) {
|
||||
dispatch(activeID(id));
|
||||
}
|
||||
});
|
||||
};
|
||||
const checkSelectedOnload = (data) => {
|
||||
const childrens = data.children ? data.children : [];
|
||||
childrens.forEach((itemCheck) => {
|
||||
if (itemCheck.children?.length) {
|
||||
checkOpenForParent(itemCheck.children, currentItem.id);
|
||||
}
|
||||
if (itemCheck.url === pathname) {
|
||||
dispatch(activeID(currentItem.id));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
checkSelectedOnload(currentItem);
|
||||
if (openMini) setAnchorEl(null);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [pathname, currentItem]);
|
||||
|
||||
const handleClick = (event) => {
|
||||
if (!openMini) {
|
||||
setAnchorEl(event?.currentTarget);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const Icon = currentItem?.icon;
|
||||
const itemIcon = currentItem?.icon ? (
|
||||
<Icon
|
||||
style={{
|
||||
fontSize: 20,
|
||||
stroke: '1.5',
|
||||
color: selectedID === currentItem.id ? theme.palette.primary.main : theme.palette.secondary.dark
|
||||
}}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
const navCollapse = item.children?.map((menuItem) => {
|
||||
switch (menuItem.type) {
|
||||
case 'collapse':
|
||||
return (
|
||||
<NavCollapse
|
||||
key={menuItem.id}
|
||||
menu={menuItem}
|
||||
setSelectedItems={setSelectedItems}
|
||||
setSelectedLevel={setSelectedLevel}
|
||||
selectedLevel={selectedLevel}
|
||||
selectedItems={selectedItems}
|
||||
level={1}
|
||||
parentId={currentItem.id}
|
||||
/>
|
||||
);
|
||||
case 'item':
|
||||
return <NavItem key={menuItem.id} item={menuItem} level={1} />;
|
||||
default:
|
||||
}
|
||||
});
|
||||
|
||||
const moreItems = remItems.map((itemRem, i) => (
|
||||
<Fragment key={i}>
|
||||
{itemRem.title && (
|
||||
<Typography variant="caption" sx={{ pl: 2 }}>
|
||||
{itemRem.title}
|
||||
</Typography>
|
||||
)}
|
||||
{itemRem?.elements?.map((menu) => {
|
||||
switch (menu.type) {
|
||||
case 'collapse':
|
||||
return (
|
||||
<NavCollapse
|
||||
key={menu.id}
|
||||
menu={menu}
|
||||
level={1}
|
||||
parentId={currentItem.id}
|
||||
setSelectedItems={setSelectedItems}
|
||||
setSelectedLevel={setSelectedLevel}
|
||||
selectedLevel={selectedLevel}
|
||||
selectedItems={selectedItems}
|
||||
/>
|
||||
);
|
||||
case 'item':
|
||||
return <NavItem key={menu.id} item={menu} level={1} />;
|
||||
default:
|
||||
return (
|
||||
<Typography key={menu.id} variant="h6" color="error" align="center">
|
||||
Menu Items Error
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</Fragment>
|
||||
));
|
||||
|
||||
// menu list collapse & items
|
||||
const items = currentItem.children?.map((menu) => {
|
||||
switch (menu.type) {
|
||||
case 'collapse':
|
||||
return (
|
||||
<NavCollapse
|
||||
key={menu.id}
|
||||
menu={menu}
|
||||
level={1}
|
||||
parentId={currentItem.id}
|
||||
setSelectedItems={setSelectedItems}
|
||||
setSelectedLevel={setSelectedLevel}
|
||||
selectedLevel={selectedLevel}
|
||||
selectedItems={selectedItems}
|
||||
/>
|
||||
);
|
||||
case 'item':
|
||||
return <NavItem key={menu.id} item={menu} level={1} />;
|
||||
default:
|
||||
return (
|
||||
<Typography key={menu.id} variant="h6" color="error" align="center">
|
||||
Menu Items Error
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const popperId = openMini ? `group-pop-${item.id}` : undefined;
|
||||
|
||||
return (
|
||||
<>
|
||||
{menuOrientation === MenuOrientation.VERTICAL || downLG ? (
|
||||
<List
|
||||
subheader={
|
||||
item.title &&
|
||||
drawerOpen && (
|
||||
<Box sx={{ pl: 3, mb: 1.5 }}>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
sx={{ color: '#fff' }}
|
||||
>
|
||||
{item.title}
|
||||
</Typography>
|
||||
{item.caption && (
|
||||
<Typography variant="caption" color="secondary">
|
||||
{item.caption}
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
sx={{ mt: drawerOpen && item.title ? 1.5 : 0, py: 0, zIndex: 0 }}
|
||||
>
|
||||
{navCollapse}
|
||||
</List>
|
||||
) : (
|
||||
<List>
|
||||
<ListItemButton
|
||||
selected={selectedID === currentItem.id}
|
||||
sx={{
|
||||
p: 1,
|
||||
my: 0.5,
|
||||
mr: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'inherit',
|
||||
'&.Mui-selected': {
|
||||
bgcolor: 'transparent'
|
||||
}
|
||||
}}
|
||||
onMouseEnter={handleClick}
|
||||
onClick={handleClick}
|
||||
onMouseLeave={handleClose}
|
||||
aria-describedby={popperId}
|
||||
>
|
||||
{itemIcon && (
|
||||
<ListItemIcon sx={{ minWidth: 28 }}>
|
||||
{currentItem.id === lastItemId ? <DownOutlined style={{ fontSize: 20, stroke: '1.5' }} /> : itemIcon}
|
||||
</ListItemIcon>
|
||||
)}
|
||||
<ListItemText
|
||||
sx={{ mr: 1 }}
|
||||
primary={
|
||||
<Typography
|
||||
variant="body1"
|
||||
color={selectedID === currentItem.id ? theme.palette.primary.main : theme.palette.secondary.dark}
|
||||
>
|
||||
{currentItem.id === lastItemId ? <FormattedMessage id="More Items" /> : currentItem.title}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
{openMini ? (
|
||||
<DownOutlined style={{ fontSize: 16, stroke: '1.5' }} />
|
||||
) : (
|
||||
<RightOutlined style={{ fontSize: 16, stroke: '1.5' }} />
|
||||
)}
|
||||
{anchorEl && (
|
||||
<PopperStyled
|
||||
id={popperId}
|
||||
open={openMini}
|
||||
anchorEl={anchorEl}
|
||||
placement="bottom-start"
|
||||
style={{
|
||||
zIndex: 2001
|
||||
}}
|
||||
>
|
||||
{({ TransitionProps }) => (
|
||||
<Transitions in={openMini} {...TransitionProps}>
|
||||
<Paper
|
||||
sx={{
|
||||
mt: 0.5,
|
||||
py: 1.25,
|
||||
boxShadow: theme.shadows[8],
|
||||
backgroundImage: 'none'
|
||||
}}
|
||||
>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<SimpleBar
|
||||
sx={{
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
maxHeight: 'calc(100vh - 170px)'
|
||||
}}
|
||||
>
|
||||
{currentItem.id !== lastItemId ? items : moreItems}
|
||||
</SimpleBar>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Transitions>
|
||||
)}
|
||||
</PopperStyled>
|
||||
)}
|
||||
</ListItemButton>
|
||||
</List>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
NavGroup.propTypes = {
|
||||
item: PropTypes.object,
|
||||
lastItem: PropTypes.number,
|
||||
remItems: PropTypes.array,
|
||||
lastItemId: PropTypes.string,
|
||||
setSelectedItems: PropTypes.func,
|
||||
selectedItems: PropTypes.string,
|
||||
setSelectedLevel: PropTypes.func,
|
||||
selectedLevel: PropTypes.number
|
||||
};
|
||||
|
||||
export default NavGroup;
|
||||
283
src/layout/MainLayout/Drawer/DrawerContent/Navigation/NavItem.js
Normal file
283
src/layout/MainLayout/Drawer/DrawerContent/Navigation/NavItem.js
Normal file
@@ -0,0 +1,283 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { forwardRef, useEffect, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { Avatar, Chip, ListItemButton, ListItemIcon, ListItemText, Typography, useMediaQuery } from '@mui/material';
|
||||
|
||||
// project import
|
||||
import Dot from 'components/@extended/Dot';
|
||||
|
||||
import { MenuOrientation, ThemeMode } from 'config';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
// import { dispatch, useSelector } from 'store';
|
||||
import { activeItem, openDrawer, setSelectedMenu } from 'store/reducers/menu';
|
||||
|
||||
// ==============================|| NAVIGATION - LIST ITEM ||============================== //
|
||||
|
||||
const NavItem = ({ item, level }) => {
|
||||
const theme = useTheme();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const { menuOrientation } = useConfig();
|
||||
const { drawerOpen, openItem } = useSelector((state) => state.menu);
|
||||
|
||||
const downLG = useMediaQuery(theme.breakpoints.down('lg'));
|
||||
|
||||
let itemTarget = '_self';
|
||||
if (item.target) {
|
||||
itemTarget = '_blank';
|
||||
}
|
||||
|
||||
let listItemProps = { component: forwardRef((props, ref) => <Link {...props} to={item.url} target={itemTarget} ref={ref} />) };
|
||||
if (item?.external) {
|
||||
listItemProps = { component: 'a', href: item.url, target: itemTarget };
|
||||
}
|
||||
|
||||
const Icon = item.icon;
|
||||
|
||||
const isSelected = openItem.findIndex((id) => id === item.id) > -1;
|
||||
|
||||
const itemIcon = item.icon ? (
|
||||
<Icon style={{ fontSize: drawerOpen ? '1rem' : '1.25rem', color: isSelected ? '#662582' : '#fff' }} />
|
||||
) : (
|
||||
false
|
||||
);
|
||||
|
||||
// const { pathname } = useLocation();
|
||||
const pathname = document.location.pathname;
|
||||
|
||||
// active menu item on page load
|
||||
useEffect(() => {
|
||||
if (pathname && pathname.includes('product-details')) {
|
||||
if (item.url && item.url.includes('product-details')) {
|
||||
dispatch(activeItem({ openItem: [item.id] }));
|
||||
}
|
||||
}
|
||||
|
||||
if (pathname && pathname.includes('kanban')) {
|
||||
if (item.url && item.url.includes('kanban')) {
|
||||
dispatch(activeItem({ openItem: [item.id] }));
|
||||
}
|
||||
}
|
||||
|
||||
if (pathname.includes(item.url)) {
|
||||
dispatch(activeItem({ openItem: [item.id] }));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
}, [pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setSelectedMenu(pathname));
|
||||
}, [pathname]);
|
||||
|
||||
const textColor = theme.palette.mode === ThemeMode.DARK ? 'grey.400' : '#fff';
|
||||
const iconSelectedColor = theme.palette.mode === ThemeMode.DARK && drawerOpen ? 'text.primary' : 'primary.main';
|
||||
|
||||
return (
|
||||
<>
|
||||
{menuOrientation === MenuOrientation.VERTICAL || downLG ? (
|
||||
<ListItemButton
|
||||
{...listItemProps}
|
||||
disabled={item.disabled}
|
||||
selected={isSelected}
|
||||
onClick={() => {
|
||||
// dispatch(setSelectedMenu(item));
|
||||
}}
|
||||
sx={{
|
||||
zIndex: 1201,
|
||||
pl: drawerOpen ? `${level * 28}px` : 1.5,
|
||||
py: !drawerOpen && level === 1 ? 1.25 : 1,
|
||||
...(drawerOpen && {
|
||||
'&:hover': {
|
||||
bgcolor: '#7b1fa2'
|
||||
},
|
||||
'&.Mui-selected': {
|
||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter',
|
||||
borderRight: `2px solid ${theme.palette.primary.main}`,
|
||||
color: iconSelectedColor,
|
||||
'&:hover': {
|
||||
color: iconSelectedColor,
|
||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter'
|
||||
}
|
||||
}
|
||||
}),
|
||||
...(!drawerOpen && {
|
||||
bgcolor: '#662582',
|
||||
'&:hover': {
|
||||
bgcolor: '#662582'
|
||||
},
|
||||
'&.Mui-selected': {
|
||||
'&:hover': {
|
||||
bgcolor: 'transparent'
|
||||
},
|
||||
bgcolor: 'transparent'
|
||||
}
|
||||
})
|
||||
}}
|
||||
{...(downLG && {
|
||||
onClick: () => {
|
||||
dispatch(openDrawer(false));
|
||||
}
|
||||
})}
|
||||
>
|
||||
{itemIcon && (
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: 28,
|
||||
...(!drawerOpen && {
|
||||
borderRadius: 1.5,
|
||||
width: 36,
|
||||
height: 36,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
'&:hover': {
|
||||
bgcolor: '#7b1fa2'
|
||||
}
|
||||
}),
|
||||
...(!drawerOpen &&
|
||||
isSelected && {
|
||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'primary.900' : 'primary.lighter',
|
||||
'&:hover': {
|
||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'primary.darker' : 'primary.lighter'
|
||||
}
|
||||
})
|
||||
}}
|
||||
>
|
||||
{itemIcon}
|
||||
</ListItemIcon>
|
||||
)}
|
||||
{(drawerOpen || (!drawerOpen && level !== 1)) && (
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6" sx={{ color: isSelected ? iconSelectedColor : textColor, whiteSpace: 'nowrap' }}>
|
||||
{item.title}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{(drawerOpen || (!drawerOpen && level !== 1)) && item.chip && (
|
||||
<Chip
|
||||
color={item.chip.color}
|
||||
variant={item.chip.variant}
|
||||
size={item.chip.size}
|
||||
label={item.chip.label}
|
||||
avatar={item.chip.avatar && <Avatar>{item.chip.avatar}</Avatar>}
|
||||
/>
|
||||
)}
|
||||
</ListItemButton>
|
||||
) : (
|
||||
<ListItemButton
|
||||
{...listItemProps}
|
||||
disabled={item.disabled}
|
||||
selected={isSelected}
|
||||
sx={{
|
||||
zIndex: 1201,
|
||||
...(drawerOpen && {
|
||||
'&:hover': {
|
||||
bgcolor: 'transparent'
|
||||
},
|
||||
'&.Mui-selected': {
|
||||
bgcolor: 'transparent',
|
||||
color: iconSelectedColor,
|
||||
'&:hover': {
|
||||
color: iconSelectedColor,
|
||||
bgcolor: 'transparent'
|
||||
}
|
||||
}
|
||||
}),
|
||||
...(!drawerOpen && {
|
||||
'&:hover': {
|
||||
bgcolor: 'transparent'
|
||||
},
|
||||
'&.Mui-selected': {
|
||||
'&:hover': {
|
||||
bgcolor: 'transparent'
|
||||
},
|
||||
bgcolor: 'transparent'
|
||||
}
|
||||
})
|
||||
}}
|
||||
>
|
||||
{itemIcon && (
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: 36,
|
||||
...(!drawerOpen && {
|
||||
borderRadius: 1.5,
|
||||
width: 36,
|
||||
height: 36,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
'&:hover': {
|
||||
bgcolor: 'transparent'
|
||||
}
|
||||
}),
|
||||
...(!drawerOpen &&
|
||||
isSelected && {
|
||||
bgcolor: 'transparent',
|
||||
'&:hover': {
|
||||
bgcolor: 'transparent'
|
||||
}
|
||||
})
|
||||
}}
|
||||
>
|
||||
{itemIcon}
|
||||
</ListItemIcon>
|
||||
)}
|
||||
|
||||
{!itemIcon && (
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
color: isSelected ? 'primary.main' : 'secondary.main',
|
||||
...(!drawerOpen && {
|
||||
borderRadius: 1.5,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
'&:hover': {
|
||||
bgcolor: 'transparent'
|
||||
}
|
||||
}),
|
||||
...(!drawerOpen &&
|
||||
isSelected && {
|
||||
bgcolor: 'transparent',
|
||||
'&:hover': {
|
||||
bgcolor: 'transparent'
|
||||
}
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Dot size={4} color={isSelected ? 'primary' : 'secondary'} />
|
||||
</ListItemIcon>
|
||||
)}
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6" color="inherit">
|
||||
{item.title}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
{(drawerOpen || (!drawerOpen && level !== 1)) && item.chip && (
|
||||
<Chip
|
||||
color={item.chip.color}
|
||||
variant={item.chip.variant}
|
||||
size={item.chip.size}
|
||||
label={item.chip.label}
|
||||
avatar={item.chip.avatar && <Avatar>{item.chip.avatar}</Avatar>}
|
||||
/>
|
||||
)}
|
||||
</ListItemButton>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
NavItem.propTypes = {
|
||||
item: PropTypes.object,
|
||||
level: PropTypes.number
|
||||
};
|
||||
|
||||
export default NavItem;
|
||||
111
src/layout/MainLayout/Drawer/DrawerContent/Navigation/index.js
Normal file
111
src/layout/MainLayout/Drawer/DrawerContent/Navigation/index.js
Normal file
@@ -0,0 +1,111 @@
|
||||
import { useEffect, useLayoutEffect, useState } from 'react';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { Box, Typography, useMediaQuery } from '@mui/material';
|
||||
import { Menu } from 'menu-items/dashboard';
|
||||
|
||||
import { useSelector } from 'store';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
import { HORIZONTAL_MAX_ITEM, MenuOrientation } from 'config';
|
||||
|
||||
// project import
|
||||
import NavGroup from './NavGroup';
|
||||
import menuItem from 'menu-items';
|
||||
|
||||
// ==============================|| DRAWER CONTENT - NAVIGATION ||============================== //
|
||||
|
||||
const Navigation = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
const downLG = useMediaQuery(theme.breakpoints.down('lg'));
|
||||
|
||||
const { menuOrientation } = useConfig();
|
||||
const { drawerOpen } = useSelector((state) => state.menu);
|
||||
const [selectedItems, setSelectedItems] = useState('');
|
||||
const [selectedLevel, setSelectedLevel] = useState(0);
|
||||
const [menuItems, setMenuItems] = useState({ items: [] });
|
||||
|
||||
useEffect(() => {
|
||||
handlerMenuItem();
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
|
||||
let getMenu = Menu();
|
||||
const handlerMenuItem = () => {
|
||||
const isFound = menuItem.items.some((element) => {
|
||||
if (element.id === 'group-dashboard') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (getMenu?.id !== undefined && !isFound) {
|
||||
menuItem.items.splice(0, 0, getMenu);
|
||||
setMenuItems(menuItem);
|
||||
}
|
||||
};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setMenuItems(menuItem);
|
||||
// eslint-disable-next-line
|
||||
}, [menuItem]);
|
||||
|
||||
const isHorizontal = menuOrientation === MenuOrientation.HORIZONTAL && !downLG;
|
||||
|
||||
const lastItem = isHorizontal ? HORIZONTAL_MAX_ITEM : null;
|
||||
let lastItemIndex = menuItems.items.length - 1;
|
||||
let remItems = [];
|
||||
let lastItemId;
|
||||
|
||||
// first it checks menu item is more than giving HORIZONTAL_MAX_ITEM after that get lastItemid by giving horizontal max
|
||||
// item and it sets horizontal menu by giving horizontal max item lastly slice menuItem from array and set into remItems
|
||||
|
||||
if (lastItem && lastItem < menuItems.items.length) {
|
||||
lastItemId = menuItems.items[lastItem - 1].id;
|
||||
lastItemIndex = lastItem - 1;
|
||||
remItems = menuItems.items.slice(lastItem - 1, menuItems.items.length).map((item) => ({
|
||||
title: item.title,
|
||||
elements: item.children,
|
||||
icon: item.icon
|
||||
}));
|
||||
}
|
||||
|
||||
const navGroups = menuItems.items.slice(0, lastItemIndex + 1).map((item) => {
|
||||
switch (item.type) {
|
||||
case 'group':
|
||||
return (
|
||||
<NavGroup
|
||||
key={item.id}
|
||||
setSelectedItems={setSelectedItems}
|
||||
setSelectedLevel={setSelectedLevel}
|
||||
selectedLevel={selectedLevel}
|
||||
selectedItems={selectedItems}
|
||||
lastItem={lastItem}
|
||||
remItems={remItems}
|
||||
lastItemId={lastItemId}
|
||||
item={item}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<Typography key={item.id} variant="h6" color="error" align="center">
|
||||
Fix - Navigation Group
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
});
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
pt: drawerOpen ? (isHorizontal ? 0 : 2) : 0,
|
||||
'& > ul:first-of-type': { mt: 0 },
|
||||
display: isHorizontal ? { xs: 'block', lg: 'flex' } : 'block'
|
||||
}}
|
||||
>
|
||||
{navGroups}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Navigation;
|
||||
@@ -0,0 +1,99 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { forwardRef, useEffect } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { useMediaQuery, Avatar, Chip, ListItemButton, ListItemText, Typography } from '@mui/material';
|
||||
|
||||
// project imports
|
||||
import { ThemeMode } from 'config';
|
||||
import { dispatch, useSelector } from 'store';
|
||||
import { activeComponent, openComponentDrawer } from 'store/reducers/menu';
|
||||
|
||||
// ==============================|| NAVIGATION - LIST ITEM ||============================== //
|
||||
|
||||
const NavItem = ({ item }) => {
|
||||
const theme = useTheme();
|
||||
const matchesMD = useMediaQuery(theme.breakpoints.down('md'));
|
||||
|
||||
const menu = useSelector((state) => state.menu);
|
||||
const { openComponent } = menu;
|
||||
|
||||
let itemTarget = '_self';
|
||||
if (item.target) {
|
||||
itemTarget = '_blank';
|
||||
}
|
||||
|
||||
let listItemProps = { component: forwardRef((props, ref) => <Link {...props} to={item.url} target={itemTarget} ref={ref} />) };
|
||||
if (item?.external) {
|
||||
listItemProps = { component: 'a', href: item.url, target: itemTarget };
|
||||
}
|
||||
|
||||
const itemHandler = (id) => {
|
||||
dispatch(activeComponent({ openComponent: id }));
|
||||
if (matchesMD) dispatch(openComponentDrawer({ componentDrawerOpen: false }));
|
||||
};
|
||||
|
||||
// active menu item on page load
|
||||
useEffect(() => {
|
||||
const currentIndex = document.location.pathname
|
||||
.toString()
|
||||
.split('/')
|
||||
.findIndex((id) => id === item.id);
|
||||
if (currentIndex > -1) {
|
||||
dispatch(activeComponent({ openComponent: item.id }));
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
|
||||
const textColor = theme.palette.mode === ThemeMode.DARK ? 'grey.400' : 'text.primary';
|
||||
const iconSelectedColor = theme.palette.mode === ThemeMode.DARK ? 'text.primary' : 'primary.main';
|
||||
|
||||
return (
|
||||
<ListItemButton
|
||||
{...listItemProps}
|
||||
disabled={item.disabled}
|
||||
onClick={() => itemHandler(item.id)}
|
||||
selected={openComponent === item.id}
|
||||
sx={{
|
||||
pl: 4,
|
||||
py: 1,
|
||||
mb: 0.5,
|
||||
'&:hover': {
|
||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter'
|
||||
},
|
||||
'&.Mui-selected': {
|
||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter',
|
||||
borderRight: `2px solid ${theme.palette.primary.main}`,
|
||||
'&:hover': {
|
||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter'
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6" sx={{ color: openComponent === item.id ? iconSelectedColor : textColor }}>
|
||||
{item.title}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
{item.chip && (
|
||||
<Chip
|
||||
color={item.chip.color}
|
||||
variant={item.chip.variant}
|
||||
size={item.chip.size}
|
||||
label={item.chip.label}
|
||||
avatar={item.chip.avatar && <Avatar>{item.chip.avatar}</Avatar>}
|
||||
/>
|
||||
)}
|
||||
</ListItemButton>
|
||||
);
|
||||
};
|
||||
|
||||
NavItem.propTypes = {
|
||||
item: PropTypes.object
|
||||
};
|
||||
|
||||
export default NavItem;
|
||||
37
src/layout/MainLayout/Drawer/DrawerContent/index.js
Normal file
37
src/layout/MainLayout/Drawer/DrawerContent/index.js
Normal file
@@ -0,0 +1,37 @@
|
||||
// material-ui
|
||||
import // useMediaQuery,
|
||||
// useTheme
|
||||
'@mui/material';
|
||||
|
||||
// project import
|
||||
// import NavCard from './NavCard';
|
||||
import Navigation from './Navigation';
|
||||
// import { useSelector } from 'store';
|
||||
import SimpleBar from 'components/third-party/SimpleBar';
|
||||
|
||||
// ==============================|| DRAWER CONTENT ||============================== //
|
||||
|
||||
const DrawerContent = () => {
|
||||
// const theme = useTheme();
|
||||
// const matchDownMD = useMediaQuery(theme.breakpoints.down('lg'));
|
||||
|
||||
// const menu = useSelector((state) => state.menu);
|
||||
// const { drawerOpen } = menu;
|
||||
|
||||
return (
|
||||
<SimpleBar
|
||||
sx={{
|
||||
'& .simplebar-content': {
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Navigation />
|
||||
{/* no need navCrd just hided */}
|
||||
{/* {drawerOpen && !matchDownMD && <NavCard />} */}
|
||||
</SimpleBar>
|
||||
);
|
||||
};
|
||||
|
||||
export default DrawerContent;
|
||||
@@ -0,0 +1,22 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// material-ui
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { Box } from '@mui/material';
|
||||
|
||||
// ==============================|| DRAWER HEADER - STYLED ||============================== //
|
||||
|
||||
const DrawerHeaderStyled = styled(Box, { shouldForwardProp: (prop) => prop !== 'open' })(({ theme, open }) => ({
|
||||
...theme.mixins.toolbar,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: open ? 'flex-start' : 'center',
|
||||
paddingLeft: theme.spacing(open ? 3 : 0)
|
||||
}));
|
||||
|
||||
DrawerHeaderStyled.propTypes = {
|
||||
theme: PropTypes.object,
|
||||
open: PropTypes.bool
|
||||
};
|
||||
|
||||
export default DrawerHeaderStyled;
|
||||
58
src/layout/MainLayout/Drawer/DrawerHeader/index.js
Normal file
58
src/layout/MainLayout/Drawer/DrawerHeader/index.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { useMediaQuery } from '@mui/material';
|
||||
|
||||
// project import
|
||||
import DrawerHeaderStyled from './DrawerHeaderStyled';
|
||||
|
||||
import { MenuOrientation } from 'config';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
|
||||
import logo from 'assets/images/logo-nearle9.png'
|
||||
import logo1 from 'assets/images/logo-sm1.png'
|
||||
// ==============================|| DRAWER HEADER ||============================== //
|
||||
|
||||
const DrawerHeader = ({ open }) => {
|
||||
const theme = useTheme();
|
||||
const downLG = useMediaQuery(theme.breakpoints.down('lg'));
|
||||
|
||||
const { menuOrientation } = useConfig();
|
||||
const isHorizontal = menuOrientation === MenuOrientation.HORIZONTAL && !downLG;
|
||||
|
||||
return (
|
||||
<DrawerHeaderStyled
|
||||
theme={theme}
|
||||
open={open}
|
||||
sx={{
|
||||
minHeight: isHorizontal ? 'unset' : '60px',
|
||||
width: isHorizontal ? { xs: '100%', lg: '424px' } : 'inherit',
|
||||
paddingTop: isHorizontal ? { xs: '10px', lg: '0' } : '8px',
|
||||
paddingBottom: isHorizontal ? { xs: '18px', lg: '0' } : '8px',
|
||||
paddingLeft: isHorizontal ? { xs: '24px', lg: '0' } : open ? '24px' : 0
|
||||
}}
|
||||
>
|
||||
{/* <Logo isIcon={!open} sx={{ width: open ? 'auto' : 35, height: 35 }} /> */}
|
||||
|
||||
{(open) &&
|
||||
<img src={logo}
|
||||
// width='160px'
|
||||
// height='45px'
|
||||
// width='170px'
|
||||
alt='logo'/>
|
||||
}
|
||||
{(!open) &&
|
||||
<img src={logo1}
|
||||
width='40px'
|
||||
alt='logo'/>
|
||||
}
|
||||
</DrawerHeaderStyled>
|
||||
);
|
||||
};
|
||||
|
||||
DrawerHeader.propTypes = {
|
||||
open: PropTypes.bool
|
||||
};
|
||||
|
||||
export default DrawerHeader;
|
||||
62
src/layout/MainLayout/Drawer/HorizontalBar.js
Normal file
62
src/layout/MainLayout/Drawer/HorizontalBar.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import React from 'react';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { AppBar, Box, Container, useScrollTrigger } from '@mui/material';
|
||||
|
||||
// project imports
|
||||
import Navigation from './DrawerContent/Navigation';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
|
||||
// ==============================|| HORIZONTAL MENU LIST ||============================== //
|
||||
|
||||
function ElevationScroll({ children, window }) {
|
||||
const theme = useTheme();
|
||||
// Note that you normally won't need to set the window ref as useScrollTrigger
|
||||
// will default to window.
|
||||
// This is only being set here because the demo is in an iframe.
|
||||
const trigger = useScrollTrigger({
|
||||
disableHysteresis: true,
|
||||
threshold: 0,
|
||||
target: window
|
||||
});
|
||||
|
||||
theme.shadows[4] = theme.customShadows.z1;
|
||||
|
||||
return React.cloneElement(children, {
|
||||
elevation: trigger ? 4 : 0
|
||||
});
|
||||
}
|
||||
|
||||
// ==============================|| HORIZONTAL MENU LIST ||============================== //
|
||||
|
||||
const CustomAppBar = () => {
|
||||
const theme = useTheme();
|
||||
const { container } = useConfig();
|
||||
|
||||
return (
|
||||
<ElevationScroll>
|
||||
<AppBar
|
||||
sx={{
|
||||
top: 60,
|
||||
bgcolor: theme.palette.background.paper,
|
||||
width: '100%',
|
||||
height: 62,
|
||||
justifyContent: 'center',
|
||||
borderTop: `1px solid ${theme.palette.divider}`,
|
||||
borderBottom: `1px solid ${theme.palette.divider}`,
|
||||
zIndex: 1098,
|
||||
color: theme.palette.grey[500]
|
||||
}}
|
||||
>
|
||||
<Container maxWidth={container ? 'xl' : false}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Navigation />
|
||||
</Box>
|
||||
</Container>
|
||||
</AppBar>
|
||||
</ElevationScroll>
|
||||
);
|
||||
};
|
||||
|
||||
export default CustomAppBar;
|
||||
51
src/layout/MainLayout/Drawer/MiniDrawerStyled.js
Normal file
51
src/layout/MainLayout/Drawer/MiniDrawerStyled.js
Normal file
@@ -0,0 +1,51 @@
|
||||
// material-ui
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Drawer from '@mui/material/Drawer';
|
||||
|
||||
// project import
|
||||
import { DRAWER_WIDTH, ThemeMode } from 'config';
|
||||
|
||||
const openedMixin = (theme) => ({
|
||||
width: DRAWER_WIDTH,
|
||||
// borderRight: `1px solid ${theme.palette.divider}`,
|
||||
borderRight: 'none',
|
||||
transition: theme.transitions.create('width', {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.enteringScreen
|
||||
}),
|
||||
overflowX: 'hidden',
|
||||
boxShadow: theme.palette.mode === ThemeMode.DARK ? theme.customShadows.z1 : 'none',
|
||||
backgroundColor:'#662582',
|
||||
});
|
||||
|
||||
const closedMixin = (theme) => ({
|
||||
transition: theme.transitions.create('width', {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.leavingScreen
|
||||
}),
|
||||
// overflowX: 'hidden',
|
||||
width: theme.spacing(7.5),
|
||||
borderRight: 'none',
|
||||
boxShadow: theme.customShadows.z1,
|
||||
backgroundColor:'#662582',
|
||||
});
|
||||
|
||||
// ==============================|| DRAWER - MINI STYLED ||============================== //
|
||||
|
||||
const MiniDrawerStyled = styled(Drawer, { shouldForwardProp: (prop) => prop !== 'open' })(({ theme, open }) => ({
|
||||
width: DRAWER_WIDTH,
|
||||
flexShrink: 0,
|
||||
whiteSpace: 'nowrap',
|
||||
boxSizing: 'border-box',
|
||||
|
||||
...(open && {
|
||||
...openedMixin(theme),
|
||||
'& .MuiDrawer-paper': openedMixin(theme)
|
||||
}),
|
||||
...(!open && {
|
||||
...closedMixin(theme),
|
||||
'& .MuiDrawer-paper': closedMixin(theme)
|
||||
})
|
||||
}));
|
||||
|
||||
export default MiniDrawerStyled;
|
||||
74
src/layout/MainLayout/Drawer/index.js
Normal file
74
src/layout/MainLayout/Drawer/index.js
Normal file
@@ -0,0 +1,74 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { Box, Drawer, useMediaQuery } from '@mui/material';
|
||||
|
||||
// project import
|
||||
import DrawerHeader from './DrawerHeader';
|
||||
import DrawerContent from './DrawerContent';
|
||||
import MiniDrawerStyled from './MiniDrawerStyled';
|
||||
|
||||
import { DRAWER_WIDTH } from 'config';
|
||||
import { dispatch, useSelector } from 'store';
|
||||
import { openDrawer } from 'store/reducers/menu';
|
||||
|
||||
// ==============================|| MAIN LAYOUT - DRAWER ||============================== //
|
||||
|
||||
const MainDrawer = ({ window }) => {
|
||||
const theme = useTheme();
|
||||
const matchDownMD = useMediaQuery(theme.breakpoints.down('lg'));
|
||||
|
||||
const menu = useSelector((state) => state.menu);
|
||||
const { drawerOpen } = menu;
|
||||
|
||||
// responsive drawer container
|
||||
const container = window !== undefined ? () => window().document.body : undefined;
|
||||
|
||||
// header content
|
||||
const drawerContent = useMemo(() => <DrawerContent />, []);
|
||||
const drawerHeader = useMemo(() => <DrawerHeader open={drawerOpen} />, [drawerOpen]);
|
||||
|
||||
return (
|
||||
<Box component="nav" sx={{ flexShrink: { md: 0 }, zIndex: 1200 }} aria-label="mailbox folders">
|
||||
{!matchDownMD ? (
|
||||
<MiniDrawerStyled
|
||||
variant="permanent"
|
||||
open={drawerOpen}
|
||||
>
|
||||
{drawerHeader}
|
||||
{drawerContent}
|
||||
</MiniDrawerStyled>
|
||||
) : (
|
||||
<Drawer
|
||||
container={container}
|
||||
variant="temporary"
|
||||
open={drawerOpen}
|
||||
onClose={() => dispatch(openDrawer(!drawerOpen))}
|
||||
ModalProps={{ keepMounted: true }}
|
||||
sx={{
|
||||
display: { xs: 'block', lg: 'none' },
|
||||
'& .MuiDrawer-paper': {
|
||||
boxSizing: 'border-box',
|
||||
width: DRAWER_WIDTH,
|
||||
borderRight: `1px solid ${theme.palette.divider}`,
|
||||
backgroundImage: 'none',
|
||||
boxShadow: 'inherit',
|
||||
bgcolor:'#662582'
|
||||
}
|
||||
}}
|
||||
>
|
||||
{drawerHeader}
|
||||
{drawerContent}
|
||||
</Drawer>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
MainDrawer.propTypes = {
|
||||
window: PropTypes.object
|
||||
};
|
||||
|
||||
export default MainDrawer;
|
||||
Reference in New Issue
Block a user