first
This commit is contained in:
35
src/layout/MainLayout/Header/AppBarStyled.js
Normal file
35
src/layout/MainLayout/Header/AppBarStyled.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// material-ui
|
||||
import { styled } from '@mui/material/styles';
|
||||
import AppBar from '@mui/material/AppBar';
|
||||
|
||||
// project import
|
||||
import { DRAWER_WIDTH } from 'config';
|
||||
|
||||
// ==============================|| HEADER - APP BAR STYLED ||============================== //
|
||||
|
||||
const AppBarStyled = styled(AppBar, { shouldForwardProp: (prop) => prop !== 'open' })(({ theme, open }) => ({
|
||||
zIndex: theme.zIndex.drawer + 1,
|
||||
transition: theme.transitions.create(['width', 'margin'], {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.leavingScreen
|
||||
}),
|
||||
...(!open && {
|
||||
width: `calc(100% - ${theme.spacing(7.5)})`
|
||||
}),
|
||||
...(open && {
|
||||
marginLeft: DRAWER_WIDTH,
|
||||
width: `calc(100% - ${DRAWER_WIDTH}px)`,
|
||||
transition: theme.transitions.create(['width', 'margin'], {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.enteringScreen
|
||||
})
|
||||
})
|
||||
}));
|
||||
|
||||
AppBarStyled.propTypes = {
|
||||
open: PropTypes.bool
|
||||
};
|
||||
|
||||
export default AppBarStyled;
|
||||
301
src/layout/MainLayout/Header/HeaderContent/MegaMenuSection.js
Normal file
301
src/layout/MainLayout/Header/HeaderContent/MegaMenuSection.js
Normal file
@@ -0,0 +1,301 @@
|
||||
import { useRef, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import {
|
||||
Button,
|
||||
Box,
|
||||
CardMedia,
|
||||
ClickAwayListener,
|
||||
Grid,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
ListSubheader,
|
||||
Paper,
|
||||
Popper,
|
||||
Stack,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
|
||||
// project import
|
||||
import MainCard from 'components/MainCard';
|
||||
import Dot from 'components/@extended/Dot';
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
import Transitions from 'components/@extended/Transitions';
|
||||
import { DRAWER_WIDTH, ThemeMode } from 'config';
|
||||
|
||||
// assets
|
||||
import { ArrowRightOutlined, WindowsOutlined } from '@ant-design/icons';
|
||||
import backgroundVector from 'assets/images/mega-menu/back.svg';
|
||||
import imageChart from 'assets/images/mega-menu/chart.svg';
|
||||
import AnimateButton from 'components/@extended/AnimateButton';
|
||||
|
||||
// ==============================|| HEADER CONTENT - MEGA MENU SECTION ||============================== //
|
||||
|
||||
const MegaMenuSection = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
const anchorRef = useRef(null);
|
||||
const [open, setOpen] = useState(false);
|
||||
const handleToggle = () => {
|
||||
setOpen((prevOpen) => !prevOpen);
|
||||
};
|
||||
|
||||
const handleClose = (event) => {
|
||||
if (anchorRef.current && anchorRef.current.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const iconBackColorOpen = theme.palette.mode === ThemeMode.DARK ? 'grey.200' : 'grey.300';
|
||||
const iconBackColor = theme.palette.mode === ThemeMode.DARK ? 'background.default' : 'grey.100';
|
||||
|
||||
return (
|
||||
<Box sx={{ flexShrink: 0, ml: 0.75 }}>
|
||||
<IconButton
|
||||
color="secondary"
|
||||
variant="light"
|
||||
sx={{ color: 'text.primary', bgcolor: open ? iconBackColorOpen : iconBackColor }}
|
||||
aria-label="open profile"
|
||||
ref={anchorRef}
|
||||
aria-controls={open ? 'profile-grow' : undefined}
|
||||
aria-haspopup="true"
|
||||
onClick={handleToggle}
|
||||
>
|
||||
<WindowsOutlined />
|
||||
</IconButton>
|
||||
<Popper
|
||||
placement="bottom"
|
||||
open={open}
|
||||
anchorEl={anchorRef.current}
|
||||
role={undefined}
|
||||
transition
|
||||
disablePortal
|
||||
popperOptions={{
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [-180, 9]
|
||||
}
|
||||
}
|
||||
]
|
||||
}}
|
||||
>
|
||||
{({ TransitionProps }) => (
|
||||
<Transitions type="grow" position="top" in={open} {...TransitionProps}>
|
||||
<Paper
|
||||
sx={{
|
||||
boxShadow: theme.customShadows.z1,
|
||||
minWidth: 750,
|
||||
width: {
|
||||
md: `calc(100vw - 100px)`,
|
||||
lg: `calc(100vw - ${DRAWER_WIDTH + 100}px)`,
|
||||
xl: `calc(100vw - ${DRAWER_WIDTH + 140}px)`
|
||||
},
|
||||
maxWidth: 1024
|
||||
}}
|
||||
>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<MainCard elevation={0} border={false} content={false}>
|
||||
<Grid container>
|
||||
<Grid
|
||||
item
|
||||
md={4}
|
||||
sx={{
|
||||
background: `url(${backgroundVector}), linear-gradient(183.77deg, ${theme.palette.primary.main} 11.46%, ${theme.palette.primary[700]} 100.33%)`
|
||||
}}
|
||||
>
|
||||
<Box sx={{ p: 4.5, pb: 3 }}>
|
||||
<Stack sx={{ color: 'background.paper' }}>
|
||||
<Typography variant="h2" sx={{ fontSize: '1.875rem', mb: 1 }}>
|
||||
Explore Components
|
||||
</Typography>
|
||||
<Typography variant="h6">
|
||||
Try our pre made component pages to check how it feels and suits as per your need.
|
||||
</Typography>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="flex-end" sx={{ mt: -1 }}>
|
||||
<AnimateButton>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
sx={{
|
||||
bgcolor: 'background.paper',
|
||||
color: 'text.primary',
|
||||
'&:hover': { bgcolor: 'background.paper', color: 'text.primary' }
|
||||
}}
|
||||
endIcon={<ArrowRightOutlined />}
|
||||
component={Link}
|
||||
to="/components-overview/buttons"
|
||||
target="_blank"
|
||||
>
|
||||
View All
|
||||
</Button>
|
||||
</AnimateButton>
|
||||
<CardMedia component="img" src={imageChart} alt="Chart" sx={{ mr: -2.5, mb: -2.5, width: 124 }} />
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item md={8}>
|
||||
<Box
|
||||
sx={{
|
||||
p: 4,
|
||||
'& .MuiList-root': {
|
||||
pb: 0
|
||||
},
|
||||
'& .MuiListSubheader-root': {
|
||||
p: 0,
|
||||
pb: 1.5
|
||||
},
|
||||
'& .MuiListItemButton-root': {
|
||||
p: 0.5,
|
||||
'&:hover': {
|
||||
background: 'transparent',
|
||||
'& .MuiTypography-root': {
|
||||
color: 'primary.main'
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Grid container spacing={6}>
|
||||
<Grid item xs={4}>
|
||||
<List
|
||||
component="nav"
|
||||
aria-labelledby="nested-list-user"
|
||||
subheader={
|
||||
<ListSubheader id="nested-list-user">
|
||||
<Typography variant="subtitle1" color="textPrimary">
|
||||
Authentication
|
||||
</Typography>
|
||||
</ListSubheader>
|
||||
}
|
||||
>
|
||||
<ListItemButton disableRipple component={Link} target="_blank" to="/auth/login">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Login" />
|
||||
</ListItemButton>
|
||||
<ListItemButton disableRipple component={Link} target="_blank" to="/auth/register">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Register" />
|
||||
</ListItemButton>
|
||||
<ListItemButton disableRipple component={Link} target="_blank" to="/auth/reset-password">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Reset Password" />
|
||||
</ListItemButton>
|
||||
<ListItemButton disableRipple component={Link} target="_blank" to="/auth/forgot-password">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Forgot Password" />
|
||||
</ListItemButton>
|
||||
<ListItemButton disableRipple component={Link} target="_blank" to="/auth/code-verification">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Verification Code" />
|
||||
</ListItemButton>
|
||||
</List>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<List
|
||||
component="nav"
|
||||
aria-labelledby="nested-list-user"
|
||||
subheader={
|
||||
<ListSubheader id="nested-list-user">
|
||||
<Typography variant="subtitle1" color="textPrimary">
|
||||
Other Pages
|
||||
</Typography>
|
||||
</ListSubheader>
|
||||
}
|
||||
>
|
||||
<ListItemButton disableRipple component={Link} target="_blank" to="/">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="About us" />
|
||||
</ListItemButton>
|
||||
<ListItemButton disableRipple component={Link} target="_blank" to="/contact-us">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Contact us" />
|
||||
</ListItemButton>
|
||||
<ListItemButton disableRipple component={Link} to="/pricing">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Pricing" />
|
||||
</ListItemButton>
|
||||
<ListItemButton disableRipple component={Link} to="/apps/profiles/user/payment">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Payment" />
|
||||
</ListItemButton>
|
||||
<ListItemButton disableRipple component={Link} target="_blank" to="/maintenance/under-construction">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Construction" />
|
||||
</ListItemButton>
|
||||
<ListItemButton disableRipple component={Link} target="_blank" to="/maintenance/coming-soon">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Coming Soon" />
|
||||
</ListItemButton>
|
||||
</List>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<List
|
||||
component="nav"
|
||||
aria-labelledby="nested-list-user"
|
||||
subheader={
|
||||
<ListSubheader id="nested-list-user">
|
||||
<Typography variant="subtitle1" color="textPrimary">
|
||||
SAAS Pages
|
||||
</Typography>
|
||||
</ListSubheader>
|
||||
}
|
||||
>
|
||||
<ListItemButton disableRipple component={Link} target="_blank" to="/maintenance/404">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="404 Error" />
|
||||
</ListItemButton>
|
||||
<ListItemButton disableRipple component={Link} target="_blank" to="/">
|
||||
<ListItemIcon>
|
||||
<Dot size={7} color="secondary" variant="outlined" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Landing" />
|
||||
</ListItemButton>
|
||||
</List>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</MainCard>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Transitions>
|
||||
)}
|
||||
</Popper>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default MegaMenuSection;
|
||||
252
src/layout/MainLayout/Header/HeaderContent/Message.js
Normal file
252
src/layout/MainLayout/Header/HeaderContent/Message.js
Normal file
@@ -0,0 +1,252 @@
|
||||
import { useRef, useState } from 'react';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
ClickAwayListener,
|
||||
Divider,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemAvatar,
|
||||
ListItemText,
|
||||
ListItemSecondaryAction,
|
||||
Paper,
|
||||
Popper,
|
||||
Typography,
|
||||
useMediaQuery
|
||||
} from '@mui/material';
|
||||
|
||||
// project import
|
||||
import MainCard from 'components/MainCard';
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
import Transitions from 'components/@extended/Transitions';
|
||||
import { ThemeMode } from 'config';
|
||||
|
||||
// assets
|
||||
import avatar2 from 'assets/images/users/avatar-2.png';
|
||||
import avatar3 from 'assets/images/users/avatar-3.png';
|
||||
import avatar4 from 'assets/images/users/avatar-4.png';
|
||||
import avatar5 from 'assets/images/users/avatar-5.png';
|
||||
import { MailOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
|
||||
// sx styles
|
||||
const avatarSX = {
|
||||
width: 48,
|
||||
height: 48
|
||||
};
|
||||
|
||||
const actionSX = {
|
||||
mt: '6px',
|
||||
ml: 1,
|
||||
top: 'auto',
|
||||
right: 'auto',
|
||||
alignSelf: 'flex-start',
|
||||
transform: 'none'
|
||||
};
|
||||
|
||||
// ==============================|| HEADER CONTENT - MESSAGES ||============================== //
|
||||
|
||||
const Message = () => {
|
||||
const theme = useTheme();
|
||||
const matchesXs = useMediaQuery(theme.breakpoints.down('md'));
|
||||
|
||||
const anchorRef = useRef(null);
|
||||
const [open, setOpen] = useState(false);
|
||||
const handleToggle = () => {
|
||||
setOpen((prevOpen) => !prevOpen);
|
||||
};
|
||||
|
||||
const handleClose = (event) => {
|
||||
if (anchorRef.current && anchorRef.current.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const iconBackColorOpen = theme.palette.mode === ThemeMode.DARK ? 'grey.200' : 'grey.300';
|
||||
const iconBackColor = theme.palette.mode === ThemeMode.DARK ? 'background.default' : 'grey.100';
|
||||
|
||||
return (
|
||||
<Box sx={{ flexShrink: 0, ml: 0.75 }}>
|
||||
<IconButton
|
||||
color="secondary"
|
||||
variant="light"
|
||||
sx={{ color: 'text.primary', bgcolor: open ? iconBackColorOpen : iconBackColor }}
|
||||
aria-label="open profile"
|
||||
ref={anchorRef}
|
||||
aria-controls={open ? 'profile-grow' : undefined}
|
||||
aria-haspopup="true"
|
||||
onClick={handleToggle}
|
||||
>
|
||||
<MailOutlined />
|
||||
</IconButton>
|
||||
<Popper
|
||||
placement={matchesXs ? 'bottom' : 'bottom-end'}
|
||||
open={open}
|
||||
anchorEl={anchorRef.current}
|
||||
role={undefined}
|
||||
transition
|
||||
disablePortal
|
||||
sx={{
|
||||
maxHeight: 'calc(100vh - 250px)',
|
||||
overflow: 'auto'
|
||||
}}
|
||||
popperOptions={{
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [matchesXs ? -60 : 0, 9]
|
||||
}
|
||||
}
|
||||
]
|
||||
}}
|
||||
>
|
||||
{({ TransitionProps }) => (
|
||||
<Transitions type="grow" position={matchesXs ? 'top' : 'top-right'} in={open} {...TransitionProps}>
|
||||
<Paper
|
||||
sx={{
|
||||
boxShadow: theme.customShadows.z1,
|
||||
width: '100%',
|
||||
minWidth: 285,
|
||||
maxWidth: 420,
|
||||
[theme.breakpoints.down('md')]: {
|
||||
maxWidth: 285
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<MainCard
|
||||
title="Message"
|
||||
elevation={0}
|
||||
border={false}
|
||||
content={false}
|
||||
secondary={
|
||||
<IconButton size="small" onClick={handleToggle}>
|
||||
<CloseOutlined />
|
||||
</IconButton>
|
||||
}
|
||||
>
|
||||
<List
|
||||
component="nav"
|
||||
sx={{
|
||||
p: 0,
|
||||
'& .MuiListItemButton-root': {
|
||||
py: 1.5,
|
||||
'& .MuiAvatar-root': avatarSX,
|
||||
'& .MuiListItemSecondaryAction-root': { ...actionSX, position: 'relative' }
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ListItemButton>
|
||||
<ListItemAvatar>
|
||||
<Avatar alt="profile user" src={avatar2} />
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6">
|
||||
It's{' '}
|
||||
<Typography component="span" variant="subtitle1">
|
||||
Cristina danny's
|
||||
</Typography>{' '}
|
||||
birthday today.
|
||||
</Typography>
|
||||
}
|
||||
secondary="2 min ago"
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Typography variant="caption" noWrap>
|
||||
3:00 AM
|
||||
</Typography>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
<ListItemButton>
|
||||
<ListItemAvatar>
|
||||
<Avatar alt="profile user" src={avatar3} />
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6">
|
||||
<Typography component="span" variant="subtitle1">
|
||||
Aida Burg
|
||||
</Typography>{' '}
|
||||
commented your post.
|
||||
</Typography>
|
||||
}
|
||||
secondary="5 August"
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Typography variant="caption" noWrap>
|
||||
6:00 PM
|
||||
</Typography>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
<ListItemButton>
|
||||
<ListItemAvatar>
|
||||
<Avatar alt="profile user" src={avatar4} />
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography component="span" variant="subtitle1">
|
||||
There was a failure to your setup.
|
||||
</Typography>
|
||||
}
|
||||
secondary="7 hours ago"
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Typography variant="caption" noWrap>
|
||||
2:45 PM
|
||||
</Typography>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
<ListItemButton>
|
||||
<ListItemAvatar>
|
||||
<Avatar alt="profile user" src={avatar5} />
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6">
|
||||
<Typography component="span" variant="subtitle1">
|
||||
Cristina Danny
|
||||
</Typography>{' '}
|
||||
invited to join{' '}
|
||||
<Typography component="span" variant="subtitle1">
|
||||
Meeting.
|
||||
</Typography>
|
||||
</Typography>
|
||||
}
|
||||
secondary="Daily scrum meeting time"
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Typography variant="caption" noWrap>
|
||||
9:10 PM
|
||||
</Typography>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
<ListItemButton sx={{ textAlign: 'center' }}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6" color="primary">
|
||||
View All
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</List>
|
||||
</MainCard>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Transitions>
|
||||
)}
|
||||
</Popper>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Message;
|
||||
103
src/layout/MainLayout/Header/HeaderContent/MobileSection.js
Normal file
103
src/layout/MainLayout/Header/HeaderContent/MobileSection.js
Normal file
@@ -0,0 +1,103 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { AppBar, Box, ClickAwayListener, Paper, Popper, Toolbar } from '@mui/material';
|
||||
|
||||
// project import
|
||||
import Search from './Search';
|
||||
import Profile from './Profile';
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
import Transitions from 'components/@extended/Transitions';
|
||||
import { ThemeMode } from 'config';
|
||||
|
||||
// assets
|
||||
import { MoreOutlined } from '@ant-design/icons';
|
||||
|
||||
// ==============================|| HEADER CONTENT - MOBILE ||============================== //
|
||||
|
||||
const MobileSection = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const anchorRef = useRef(null);
|
||||
|
||||
const handleToggle = () => {
|
||||
setOpen((prevOpen) => !prevOpen);
|
||||
};
|
||||
|
||||
const handleClose = (event) => {
|
||||
if (anchorRef.current && anchorRef.current.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const prevOpen = useRef(open);
|
||||
useEffect(() => {
|
||||
if (prevOpen.current === true && open === false) {
|
||||
anchorRef.current.focus();
|
||||
}
|
||||
|
||||
prevOpen.current = open;
|
||||
}, [open]);
|
||||
|
||||
const iconBackColorOpen = theme.palette.mode === ThemeMode.DARK ? 'grey.200' : 'grey.300';
|
||||
const iconBackColor = theme.palette.mode === ThemeMode.DARK ? 'background.default' : 'grey.100';
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box sx={{ flexShrink: 0, ml: 0.75 }}>
|
||||
<IconButton
|
||||
sx={{ color: 'text.primary', bgcolor: open ? iconBackColorOpen : iconBackColor }}
|
||||
aria-label="open more menu"
|
||||
ref={anchorRef}
|
||||
aria-controls={open ? 'menu-list-grow' : undefined}
|
||||
aria-haspopup="true"
|
||||
onClick={handleToggle}
|
||||
color="secondary"
|
||||
variant="light"
|
||||
>
|
||||
<MoreOutlined />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Popper
|
||||
placement="bottom-end"
|
||||
open={open}
|
||||
anchorEl={anchorRef.current}
|
||||
role={undefined}
|
||||
transition
|
||||
disablePortal
|
||||
style={{ width: '100%' }}
|
||||
popperOptions={{
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [0, 9]
|
||||
}
|
||||
}
|
||||
]
|
||||
}}
|
||||
>
|
||||
{({ TransitionProps }) => (
|
||||
<Transitions type="fade" in={open} {...TransitionProps}>
|
||||
<Paper sx={{ boxShadow: theme.customShadows.z1 }}>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<AppBar color="inherit">
|
||||
<Toolbar>
|
||||
<Search />
|
||||
<Profile />
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Transitions>
|
||||
)}
|
||||
</Popper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MobileSection;
|
||||
289
src/layout/MainLayout/Header/HeaderContent/Notification.js
Normal file
289
src/layout/MainLayout/Header/HeaderContent/Notification.js
Normal file
@@ -0,0 +1,289 @@
|
||||
import { useRef, useState } from 'react';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Box,
|
||||
ClickAwayListener,
|
||||
Divider,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemAvatar,
|
||||
ListItemText,
|
||||
ListItemSecondaryAction,
|
||||
Paper,
|
||||
Popper,
|
||||
Tooltip,
|
||||
Typography,
|
||||
useMediaQuery
|
||||
} from '@mui/material';
|
||||
|
||||
// project import
|
||||
import MainCard from 'components/MainCard';
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
import Transitions from 'components/@extended/Transitions';
|
||||
import { ThemeMode } from 'config';
|
||||
|
||||
// assets
|
||||
import { BellOutlined, CheckCircleOutlined, GiftOutlined, MessageOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
|
||||
// sx styles
|
||||
const avatarSX = {
|
||||
width: 36,
|
||||
height: 36,
|
||||
fontSize: '1rem'
|
||||
};
|
||||
|
||||
const actionSX = {
|
||||
mt: '6px',
|
||||
ml: 1,
|
||||
top: 'auto',
|
||||
right: 'auto',
|
||||
alignSelf: 'flex-start',
|
||||
|
||||
transform: 'none'
|
||||
};
|
||||
|
||||
// ==============================|| HEADER CONTENT - NOTIFICATION ||============================== //
|
||||
|
||||
const Notification = () => {
|
||||
const theme = useTheme();
|
||||
const matchesXs = useMediaQuery(theme.breakpoints.down('md'));
|
||||
|
||||
const anchorRef = useRef(null);
|
||||
const [read, setRead] = useState(2);
|
||||
const [open, setOpen] = useState(false);
|
||||
const handleToggle = () => {
|
||||
setOpen((prevOpen) => !prevOpen);
|
||||
};
|
||||
|
||||
const handleClose = (event) => {
|
||||
if (anchorRef.current && anchorRef.current.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const iconBackColorOpen = theme.palette.mode === ThemeMode.DARK ? 'grey.200' : 'grey.300';
|
||||
const iconBackColor = theme.palette.mode === ThemeMode.DARK ? 'background.default' : 'grey.100';
|
||||
|
||||
return (
|
||||
<Box sx={{ flexShrink: 0, ml: 0.75 }}>
|
||||
<IconButton
|
||||
color="secondary"
|
||||
variant="light"
|
||||
sx={{ color: 'text.primary', bgcolor: open ? iconBackColorOpen : iconBackColor }}
|
||||
aria-label="open profile"
|
||||
ref={anchorRef}
|
||||
aria-controls={open ? 'profile-grow' : undefined}
|
||||
aria-haspopup="true"
|
||||
onClick={handleToggle}
|
||||
>
|
||||
<Badge badgeContent={read} color="primary">
|
||||
<BellOutlined />
|
||||
</Badge>
|
||||
</IconButton>
|
||||
<Popper
|
||||
placement={matchesXs ? 'bottom' : 'bottom-end'}
|
||||
open={open}
|
||||
anchorEl={anchorRef.current}
|
||||
role={undefined}
|
||||
transition
|
||||
disablePortal
|
||||
popperOptions={{
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [matchesXs ? -5 : 0, 9]
|
||||
}
|
||||
}
|
||||
]
|
||||
}}
|
||||
>
|
||||
{({ TransitionProps }) => (
|
||||
<Transitions type="grow" position={matchesXs ? 'top' : 'top-right'} sx={{ overflow: 'hidden' }} in={open} {...TransitionProps}>
|
||||
<Paper
|
||||
sx={{
|
||||
boxShadow: theme.customShadows.z1,
|
||||
width: '100%',
|
||||
minWidth: 285,
|
||||
maxWidth: 420,
|
||||
[theme.breakpoints.down('md')]: {
|
||||
maxWidth: 285
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<MainCard
|
||||
title="Notification"
|
||||
elevation={0}
|
||||
border={false}
|
||||
content={false}
|
||||
secondary={
|
||||
<>
|
||||
{read > 0 && (
|
||||
<Tooltip title="Mark as all read">
|
||||
<IconButton color="success" size="small" onClick={() => setRead(0)}>
|
||||
<CheckCircleOutlined style={{ fontSize: '1.15rem' }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<List
|
||||
component="nav"
|
||||
sx={{
|
||||
p: 0,
|
||||
'& .MuiListItemButton-root': {
|
||||
py: 0.5,
|
||||
'&.Mui-selected': { bgcolor: 'grey.50', color: 'text.primary' },
|
||||
'& .MuiAvatar-root': avatarSX,
|
||||
'& .MuiListItemSecondaryAction-root': { ...actionSX, position: 'relative' }
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ListItemButton selected={read > 0}>
|
||||
<ListItemAvatar>
|
||||
<Avatar
|
||||
sx={{
|
||||
color: 'success.main',
|
||||
bgcolor: 'success.lighter'
|
||||
}}
|
||||
>
|
||||
<GiftOutlined />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6">
|
||||
It's{' '}
|
||||
<Typography component="span" variant="subtitle1">
|
||||
Cristina danny's
|
||||
</Typography>{' '}
|
||||
birthday today.
|
||||
</Typography>
|
||||
}
|
||||
secondary="2 min ago"
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Typography variant="caption" noWrap>
|
||||
3:00 AM
|
||||
</Typography>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
<ListItemButton selected={read > 0}>
|
||||
<ListItemAvatar>
|
||||
<Avatar
|
||||
sx={{
|
||||
color: 'primary.main',
|
||||
bgcolor: 'primary.lighter'
|
||||
}}
|
||||
>
|
||||
<MessageOutlined />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6">
|
||||
<Typography component="span" variant="subtitle1">
|
||||
Aida Burg
|
||||
</Typography>{' '}
|
||||
commented your post.
|
||||
</Typography>
|
||||
}
|
||||
secondary="5 August"
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Typography variant="caption" noWrap>
|
||||
6:00 PM
|
||||
</Typography>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
<ListItemButton>
|
||||
<ListItemAvatar>
|
||||
<Avatar
|
||||
sx={{
|
||||
color: 'error.main',
|
||||
bgcolor: 'error.lighter'
|
||||
}}
|
||||
>
|
||||
<SettingOutlined />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6">
|
||||
Your Profile is Complete
|
||||
<Typography component="span" variant="subtitle1">
|
||||
60%
|
||||
</Typography>{' '}
|
||||
</Typography>
|
||||
}
|
||||
secondary="7 hours ago"
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Typography variant="caption" noWrap>
|
||||
2:45 PM
|
||||
</Typography>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
<ListItemButton>
|
||||
<ListItemAvatar>
|
||||
<Avatar
|
||||
sx={{
|
||||
color: 'primary.main',
|
||||
bgcolor: 'primary.lighter'
|
||||
}}
|
||||
>
|
||||
C
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6">
|
||||
<Typography component="span" variant="subtitle1">
|
||||
Cristina Danny
|
||||
</Typography>{' '}
|
||||
invited to join{' '}
|
||||
<Typography component="span" variant="subtitle1">
|
||||
Meeting.
|
||||
</Typography>
|
||||
</Typography>
|
||||
}
|
||||
secondary="Daily scrum meeting time"
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Typography variant="caption" noWrap>
|
||||
9:10 PM
|
||||
</Typography>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
<ListItemButton sx={{ textAlign: 'center', py: `${12}px !important` }}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="h6" color="primary">
|
||||
View All
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</List>
|
||||
</MainCard>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Transitions>
|
||||
)}
|
||||
</Popper>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Notification;
|
||||
@@ -0,0 +1,59 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { useState } from 'react';
|
||||
|
||||
// material-ui
|
||||
import { List, ListItemButton, ListItemIcon, ListItemText } from '@mui/material';
|
||||
|
||||
// assets
|
||||
import { EditOutlined, ProfileOutlined, LogoutOutlined, UserOutlined, WalletOutlined } from '@ant-design/icons';
|
||||
|
||||
// ==============================|| HEADER PROFILE - PROFILE TAB ||============================== //
|
||||
|
||||
const ProfileTab = ({ handleLogout }) => {
|
||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||
const handleListItemClick = (event, index) => {
|
||||
setSelectedIndex(index);
|
||||
};
|
||||
|
||||
return (
|
||||
<List component="nav" sx={{ p: 0, '& .MuiListItemIcon-root': { minWidth: 32 } }}>
|
||||
<ListItemButton selected={selectedIndex === 0} onClick={(event) => handleListItemClick(event, 0)}>
|
||||
<ListItemIcon>
|
||||
<EditOutlined />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Edit Profile" />
|
||||
</ListItemButton>
|
||||
<ListItemButton selected={selectedIndex === 1} onClick={(event) => handleListItemClick(event, 1)}>
|
||||
<ListItemIcon>
|
||||
<UserOutlined />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="View Profile" />
|
||||
</ListItemButton>
|
||||
|
||||
<ListItemButton selected={selectedIndex === 3} onClick={(event) => handleListItemClick(event, 3)}>
|
||||
<ListItemIcon>
|
||||
<ProfileOutlined />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Social Profile" />
|
||||
</ListItemButton>
|
||||
<ListItemButton selected={selectedIndex === 4} onClick={(event) => handleListItemClick(event, 4)}>
|
||||
<ListItemIcon>
|
||||
<WalletOutlined />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Billing" />
|
||||
</ListItemButton>
|
||||
<ListItemButton selected={selectedIndex === 2} onClick={handleLogout}>
|
||||
<ListItemIcon>
|
||||
<LogoutOutlined />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Logout" />
|
||||
</ListItemButton>
|
||||
</List>
|
||||
);
|
||||
};
|
||||
|
||||
ProfileTab.propTypes = {
|
||||
handleLogout: PropTypes.func
|
||||
};
|
||||
|
||||
export default ProfileTab;
|
||||
@@ -0,0 +1,53 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
// material-ui
|
||||
import { List, ListItemButton, ListItemIcon, ListItemText } from '@mui/material';
|
||||
|
||||
// assets
|
||||
import { CommentOutlined, LockOutlined, QuestionCircleOutlined, UserOutlined, UnorderedListOutlined } from '@ant-design/icons';
|
||||
|
||||
// ==============================|| HEADER PROFILE - SETTING TAB ||============================== //
|
||||
|
||||
const SettingTab = () => {
|
||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||
const handleListItemClick = (event, index) => {
|
||||
setSelectedIndex(index);
|
||||
};
|
||||
|
||||
return (
|
||||
<List component="nav" sx={{ p: 0, '& .MuiListItemIcon-root': { minWidth: 32 } }}>
|
||||
<ListItemButton selected={selectedIndex === 0} onClick={(event) => handleListItemClick(event, 0)}>
|
||||
<ListItemIcon>
|
||||
<QuestionCircleOutlined />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Support" />
|
||||
</ListItemButton>
|
||||
<ListItemButton selected={selectedIndex === 1} onClick={(event) => handleListItemClick(event, 1)}>
|
||||
<ListItemIcon>
|
||||
<UserOutlined />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Account Settings" />
|
||||
</ListItemButton>
|
||||
<ListItemButton selected={selectedIndex === 2} onClick={(event) => handleListItemClick(event, 2)}>
|
||||
<ListItemIcon>
|
||||
<LockOutlined />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Privacy Center" />
|
||||
</ListItemButton>
|
||||
<ListItemButton selected={selectedIndex === 3} onClick={(event) => handleListItemClick(event, 3)}>
|
||||
<ListItemIcon>
|
||||
<CommentOutlined />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Feedback" />
|
||||
</ListItemButton>
|
||||
<ListItemButton selected={selectedIndex === 4} onClick={(event) => handleListItemClick(event, 4)}>
|
||||
<ListItemIcon>
|
||||
<UnorderedListOutlined />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="History" />
|
||||
</ListItemButton>
|
||||
</List>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingTab;
|
||||
211
src/layout/MainLayout/Header/HeaderContent/Profile/index.js
Normal file
211
src/layout/MainLayout/Header/HeaderContent/Profile/index.js
Normal file
@@ -0,0 +1,211 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { useRef, useState } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { Box, ButtonBase, CardContent, ClickAwayListener, Grid, Paper, Popper, Stack, Tab, Tabs, Tooltip, Typography } from '@mui/material';
|
||||
|
||||
// project import
|
||||
import ProfileTab from './ProfileTab';
|
||||
import SettingTab from './SettingTab';
|
||||
import Avatar from 'components/@extended/Avatar';
|
||||
import MainCard from 'components/MainCard';
|
||||
import Transitions from 'components/@extended/Transitions';
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
|
||||
import { ThemeMode } from 'config';
|
||||
import useAuth from 'hooks/useAuth';
|
||||
|
||||
// assets
|
||||
import avatar1 from 'assets/images/users/avatar-1.png';
|
||||
import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
|
||||
|
||||
// tab panel wrapper
|
||||
function TabPanel({ children, value, index, ...other }) {
|
||||
return (
|
||||
<div role="tabpanel" hidden={value !== index} id={`profile-tabpanel-${index}`} aria-labelledby={`profile-tab-${index}`} {...other}>
|
||||
{value === index && children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
TabPanel.propTypes = {
|
||||
children: PropTypes.node,
|
||||
index: PropTypes.any.isRequired,
|
||||
value: PropTypes.any.isRequired
|
||||
};
|
||||
|
||||
function a11yProps(index) {
|
||||
return {
|
||||
id: `profile-tab-${index}`,
|
||||
'aria-controls': `profile-tabpanel-${index}`
|
||||
};
|
||||
}
|
||||
|
||||
// ==============================|| HEADER CONTENT - PROFILE ||============================== //
|
||||
|
||||
const Profile = () => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { logout, user } = useAuth();
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
await logout();
|
||||
navigate(`/login`, {
|
||||
state: {
|
||||
from: ''
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
const anchorRef = useRef(null);
|
||||
const [open, setOpen] = useState(false);
|
||||
const handleToggle = () => {
|
||||
setOpen((prevOpen) => !prevOpen);
|
||||
};
|
||||
|
||||
const handleClose = (event) => {
|
||||
if (anchorRef.current && anchorRef.current.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const [value, setValue] = useState(0);
|
||||
|
||||
const handleChange = (event, newValue) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
const iconBackColorOpen = theme.palette.mode === ThemeMode.DARK ? 'grey.200' : 'grey.300';
|
||||
|
||||
return (
|
||||
<Box sx={{ flexShrink: 0, ml: 0.75 }}>
|
||||
<ButtonBase
|
||||
sx={{
|
||||
p: 0.25,
|
||||
bgcolor: open ? iconBackColorOpen : 'transparent',
|
||||
borderRadius: 1,
|
||||
'&:hover': { bgcolor: theme.palette.mode === ThemeMode.DARK ? 'secondary.light' : 'secondary.lighter' },
|
||||
'&:focus-visible': {
|
||||
outline: `2px solid ${theme.palette.secondary.dark}`,
|
||||
outlineOffset: 2
|
||||
}
|
||||
}}
|
||||
aria-label="open profile"
|
||||
ref={anchorRef}
|
||||
aria-controls={open ? 'profile-grow' : undefined}
|
||||
aria-haspopup="true"
|
||||
onClick={handleToggle}
|
||||
>
|
||||
<Stack direction="row" spacing={2} alignItems="center" sx={{ p: 0.5 }}>
|
||||
<Avatar alt="profile user" src={avatar1} size="xs" />
|
||||
<Typography variant="subtitle1">{user?.name}</Typography>
|
||||
</Stack>
|
||||
</ButtonBase>
|
||||
<Popper
|
||||
placement="bottom-end"
|
||||
open={open}
|
||||
anchorEl={anchorRef.current}
|
||||
role={undefined}
|
||||
transition
|
||||
disablePortal
|
||||
popperOptions={{
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [0, 9]
|
||||
}
|
||||
}
|
||||
]
|
||||
}}
|
||||
>
|
||||
{({ TransitionProps }) => (
|
||||
<Transitions type="grow" position="top-right" in={open} {...TransitionProps}>
|
||||
<Paper
|
||||
sx={{
|
||||
boxShadow: theme.customShadows.z1,
|
||||
width: 290,
|
||||
minWidth: 240,
|
||||
maxWidth: 290,
|
||||
[theme.breakpoints.down('md')]: {
|
||||
maxWidth: 250
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<MainCard elevation={0} border={false} content={false}>
|
||||
<CardContent sx={{ px: 2.5, pt: 3 }}>
|
||||
<Grid container justifyContent="space-between" alignItems="center">
|
||||
<Grid item>
|
||||
<Stack direction="row" spacing={1.25} alignItems="center">
|
||||
<Avatar alt="profile user" src={avatar1} sx={{ width: 32, height: 32 }} />
|
||||
<Stack>
|
||||
<Typography variant="h6">{user?.name}</Typography>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
UI/UX Designer
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Tooltip title="Logout">
|
||||
<IconButton size="large" sx={{ color: 'text.primary' }} onClick={handleLogout}>
|
||||
<LogoutOutlined />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</CardContent>
|
||||
|
||||
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
||||
<Tabs variant="fullWidth" value={value} onChange={handleChange} aria-label="profile tabs">
|
||||
<Tab
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
textTransform: 'capitalize'
|
||||
}}
|
||||
icon={<UserOutlined style={{ marginBottom: 0, marginRight: '10px' }} />}
|
||||
label="Profile"
|
||||
{...a11yProps(0)}
|
||||
/>
|
||||
<Tab
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
textTransform: 'capitalize'
|
||||
}}
|
||||
icon={<SettingOutlined style={{ marginBottom: 0, marginRight: '10px' }} />}
|
||||
label="Setting"
|
||||
{...a11yProps(1)}
|
||||
/>
|
||||
</Tabs>
|
||||
</Box>
|
||||
<TabPanel value={value} index={0} dir={theme.direction}>
|
||||
<ProfileTab handleLogout={handleLogout} />
|
||||
</TabPanel>
|
||||
<TabPanel value={value} index={1} dir={theme.direction}>
|
||||
<SettingTab />
|
||||
</TabPanel>
|
||||
</MainCard>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Transitions>
|
||||
)}
|
||||
</Popper>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Profile;
|
||||
30
src/layout/MainLayout/Header/HeaderContent/Search.js
Normal file
30
src/layout/MainLayout/Header/HeaderContent/Search.js
Normal file
@@ -0,0 +1,30 @@
|
||||
// material-ui
|
||||
import { Box, FormControl, InputAdornment, OutlinedInput } from '@mui/material';
|
||||
|
||||
// assets
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
|
||||
// ==============================|| HEADER CONTENT - SEARCH ||============================== //
|
||||
|
||||
const Search = () => (
|
||||
<Box sx={{ width: '100%', ml: { xs: 0, md: 1 } }}>
|
||||
<FormControl sx={{ width: { xs: '100%', md: 224 } }}>
|
||||
<OutlinedInput
|
||||
size="small"
|
||||
id="header-search"
|
||||
startAdornment={
|
||||
<InputAdornment position="start" sx={{ mr: -0.5 }}>
|
||||
<SearchOutlined />
|
||||
</InputAdornment>
|
||||
}
|
||||
aria-describedby="header-search-text"
|
||||
inputProps={{
|
||||
'aria-label': 'weight'
|
||||
}}
|
||||
placeholder="Ctrl + K"
|
||||
/>
|
||||
</FormControl>
|
||||
</Box>
|
||||
);
|
||||
|
||||
export default Search;
|
||||
36
src/layout/MainLayout/Header/HeaderContent/index.js
Normal file
36
src/layout/MainLayout/Header/HeaderContent/index.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
// material-ui
|
||||
import { Box, useMediaQuery } from '@mui/material';
|
||||
|
||||
// project import
|
||||
import Search from './Search';
|
||||
import Message from './Message';
|
||||
import Profile from './Profile';
|
||||
import Notification from './Notification';
|
||||
import MobileSection from './MobileSection';
|
||||
import MegaMenuSection from './MegaMenuSection';
|
||||
|
||||
// ==============================|| HEADER - CONTENT ||============================== //
|
||||
|
||||
const HeaderContent = () => {
|
||||
const matchesXs = useMediaQuery((theme) => theme.breakpoints.down('md'));
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const megaMenu = useMemo(() => <MegaMenuSection />, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{!matchesXs && <Search />}
|
||||
{!matchesXs && megaMenu}
|
||||
{matchesXs && <Box sx={{ width: '100%', ml: 1 }} />}
|
||||
|
||||
<Notification />
|
||||
<Message />
|
||||
{!matchesXs && <Profile />}
|
||||
{matchesXs && <MobileSection />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeaderContent;
|
||||
83
src/layout/MainLayout/Header/index.js
Normal file
83
src/layout/MainLayout/Header/index.js
Normal file
@@ -0,0 +1,83 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { AppBar, Toolbar, useMediaQuery } from '@mui/material';
|
||||
|
||||
// project import
|
||||
import AppBarStyled from './AppBarStyled';
|
||||
import HeaderContent from './HeaderContent';
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
|
||||
import { MenuOrientation, ThemeMode } from 'config';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
import { dispatch, useSelector } from 'store';
|
||||
import { openDrawer } from 'store/reducers/menu';
|
||||
|
||||
// assets
|
||||
import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';
|
||||
|
||||
// ==============================|| MAIN LAYOUT - HEADER ||============================== //
|
||||
|
||||
const Header = () => {
|
||||
const theme = useTheme();
|
||||
const downLG = useMediaQuery(theme.breakpoints.down('lg'));
|
||||
const { menuOrientation } = useConfig();
|
||||
|
||||
const menu = useSelector((state) => state.menu);
|
||||
const { drawerOpen } = menu;
|
||||
|
||||
const isHorizontal = menuOrientation === MenuOrientation.HORIZONTAL && !downLG;
|
||||
|
||||
// header content
|
||||
const headerContent = useMemo(() => <HeaderContent />, []);
|
||||
|
||||
const iconBackColorOpen = theme.palette.mode === ThemeMode.DARK ? 'grey.200' : 'grey.300';
|
||||
const iconBackColor = theme.palette.mode === ThemeMode.DARK ? 'background.default' : 'grey.100';
|
||||
|
||||
// common header
|
||||
const mainHeader = (
|
||||
<Toolbar>
|
||||
{!isHorizontal ? (
|
||||
<IconButton
|
||||
aria-label="open drawer"
|
||||
onClick={() => dispatch(openDrawer(!drawerOpen))}
|
||||
edge="start"
|
||||
color="secondary"
|
||||
variant="light"
|
||||
sx={{ color: 'text.primary', bgcolor: drawerOpen ? iconBackColorOpen : iconBackColor, ml: { xs: 0, lg: -2 } }}
|
||||
>
|
||||
{!drawerOpen ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||||
</IconButton>
|
||||
) : null}
|
||||
{headerContent}
|
||||
</Toolbar>
|
||||
);
|
||||
|
||||
// app-bar params
|
||||
const appBar = {
|
||||
position: 'fixed',
|
||||
color: 'inherit',
|
||||
elevation: 0,
|
||||
sx: {
|
||||
borderBottom: `1px solid ${theme.palette.divider}`,
|
||||
zIndex: 1200,
|
||||
width: isHorizontal ? '100%' : drawerOpen ? 'calc(100% - 260px)' : { xs: '100%', lg: 'calc(100% - 60px)' }
|
||||
// boxShadow: theme.customShadows.z1
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{!downLG ? (
|
||||
<AppBarStyled open={drawerOpen} {...appBar}>
|
||||
{mainHeader}
|
||||
</AppBarStyled>
|
||||
) : (
|
||||
<AppBar {...appBar}>{mainHeader}</AppBar>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
Reference in New Issue
Block a user