header fixes
This commit is contained in:
@@ -2,17 +2,12 @@ import * as React from 'react';
|
||||
import {
|
||||
Box,
|
||||
Drawer,
|
||||
AppBar,
|
||||
Toolbar,
|
||||
List,
|
||||
Typography,
|
||||
Divider,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
CssBaseline,
|
||||
Button,
|
||||
IconButton,
|
||||
Tooltip,
|
||||
useMediaQuery,
|
||||
@@ -20,7 +15,6 @@ import {
|
||||
} from '@mui/material';
|
||||
import TableViewIcon from '@mui/icons-material/TableView';
|
||||
import DashboardIcon from '@mui/icons-material/Dashboard';
|
||||
import LogoutIcon from '@mui/icons-material/Logout';
|
||||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
|
||||
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
||||
@@ -41,105 +35,151 @@ interface AdminLayoutProps {
|
||||
export default function AdminLayout({
|
||||
children,
|
||||
onSelectResource,
|
||||
onLogout,
|
||||
username,
|
||||
resources,
|
||||
}: AdminLayoutProps) {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
||||
const [isCollapsed, setIsCollapsed] = React.useState(false);
|
||||
const [mobileOpen, setMobileOpen] = React.useState(false);
|
||||
|
||||
const activeResourceName = location.pathname.split('/admin')[1] || null;
|
||||
|
||||
// AUTO-TOGGLE LOGIC
|
||||
// AUTO-TOGGLE LOGIC (unchanged)
|
||||
React.useEffect(() => {
|
||||
if (isMobile) {
|
||||
setIsCollapsed(false); // Mobile drawer is never "mini"
|
||||
setMobileOpen(false); // Close on navigation
|
||||
setIsCollapsed(false);
|
||||
setMobileOpen(false);
|
||||
} else {
|
||||
if (location.pathname === '/admin' || location.pathname === '') {
|
||||
setIsCollapsed(false);
|
||||
} else {
|
||||
setIsCollapsed(true);
|
||||
}
|
||||
if (location.pathname === '/admin' || location.pathname === '') {
|
||||
setIsCollapsed(false);
|
||||
} else {
|
||||
setIsCollapsed(true);
|
||||
}
|
||||
}
|
||||
}, [location.pathname, isMobile]);
|
||||
|
||||
const currentWidth = isMobile ? drawerWidth : (isCollapsed ? collapsedWidth : drawerWidth);
|
||||
const currentWidth = isMobile
|
||||
? drawerWidth
|
||||
: isCollapsed
|
||||
? collapsedWidth
|
||||
: drawerWidth;
|
||||
|
||||
const handleDrawerToggle = () => {
|
||||
setMobileOpen(!mobileOpen);
|
||||
setMobileOpen((prev) => !prev);
|
||||
};
|
||||
|
||||
const handleSidebarToggle = () => {
|
||||
setIsCollapsed(!isCollapsed);
|
||||
setIsCollapsed((prev) => !prev);
|
||||
};
|
||||
|
||||
const drawerContent = (
|
||||
<Box sx={{ overflow: 'hidden', display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||
{!isMobile && (
|
||||
<>
|
||||
<Box sx={{ display: 'flex', justifyContent: isCollapsed ? 'center' : 'flex-end', p: 1 }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: isCollapsed ? 'center' : 'flex-end',
|
||||
p: 1,
|
||||
}}
|
||||
>
|
||||
<IconButton onClick={handleSidebarToggle}>
|
||||
{isCollapsed ? <ChevronRightIcon /> : <ChevronLeftIcon />}
|
||||
{isCollapsed ? <ChevronRightIcon /> : <ChevronLeftIcon />}
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Divider />
|
||||
</>
|
||||
)}
|
||||
{isMobile && <Toolbar />}
|
||||
|
||||
|
||||
{/* Mobile spacing (replaces Toolbar) */}
|
||||
{isMobile && (
|
||||
<Box sx={{ height: (theme) => theme.spacing(7) }} />
|
||||
)}
|
||||
|
||||
<List>
|
||||
<ListItem disablePadding>
|
||||
<Tooltip title={(isCollapsed && !isMobile) ? "Dashboard" : ""} placement="right">
|
||||
<ListItemButton
|
||||
selected={location.pathname === '/admin'}
|
||||
onClick={() => navigate('/admin')}
|
||||
sx={{
|
||||
minHeight: 48,
|
||||
justifyContent: (isCollapsed && !isMobile) ? 'center' : 'initial',
|
||||
px: 2.5,
|
||||
}}
|
||||
<Tooltip
|
||||
title={isCollapsed && !isMobile ? 'Dashboard' : ''}
|
||||
placement="right"
|
||||
>
|
||||
<ListItemButton
|
||||
selected={location.pathname === '/admin'}
|
||||
onClick={() => navigate('/admin')}
|
||||
sx={{
|
||||
minHeight: 48,
|
||||
justifyContent:
|
||||
isCollapsed && !isMobile ? 'center' : 'initial',
|
||||
px: 2.5,
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{
|
||||
minWidth: 0,
|
||||
mr: (isCollapsed && !isMobile) ? 0 : 3,
|
||||
justifyContent: 'center',
|
||||
}}>
|
||||
<DashboardIcon color={location.pathname === '/admin' ? 'primary' : 'inherit'} />
|
||||
</ListItemIcon>
|
||||
{(!isCollapsed || isMobile) && <ListItemText primary="Dashboard" />}
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
mr: isCollapsed && !isMobile ? 0 : 3,
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<DashboardIcon
|
||||
color={
|
||||
location.pathname === '/admin'
|
||||
? 'primary'
|
||||
: 'inherit'
|
||||
}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
{(!isCollapsed || isMobile) && (
|
||||
<ListItemText primary="Dashboard" />
|
||||
)}
|
||||
</ListItemButton>
|
||||
</Tooltip>
|
||||
</ListItem>
|
||||
</List>
|
||||
|
||||
<Divider />
|
||||
|
||||
<List sx={{ flexGrow: 1 }}>
|
||||
{resources.map((res) => (
|
||||
<ListItem key={res.name} disablePadding>
|
||||
<Tooltip title={(isCollapsed && !isMobile) ? res.pluralLabel : ""} placement="right">
|
||||
<ListItemButton
|
||||
<Tooltip
|
||||
title={
|
||||
isCollapsed && !isMobile ? res.pluralLabel : ''
|
||||
}
|
||||
placement="right"
|
||||
>
|
||||
<ListItemButton
|
||||
selected={activeResourceName === res.name}
|
||||
onClick={() => onSelectResource(res.name)}
|
||||
sx={{
|
||||
minHeight: 48,
|
||||
justifyContent: (isCollapsed && !isMobile) ? 'center' : 'initial',
|
||||
px: 2.5,
|
||||
minHeight: 48,
|
||||
justifyContent:
|
||||
isCollapsed && !isMobile
|
||||
? 'center'
|
||||
: 'initial',
|
||||
px: 2.5,
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
mr: (isCollapsed && !isMobile) ? 0 : 3,
|
||||
mr: isCollapsed && !isMobile ? 0 : 3,
|
||||
justifyContent: 'center',
|
||||
}}>
|
||||
<TableViewIcon color={activeResourceName === res.name ? 'primary' : 'inherit'} />
|
||||
}}
|
||||
>
|
||||
<TableViewIcon
|
||||
color={
|
||||
activeResourceName === res.name
|
||||
? 'primary'
|
||||
: 'inherit'
|
||||
}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
{(!isCollapsed || isMobile) && <ListItemText primary={res.pluralLabel} />}
|
||||
</ListItemButton>
|
||||
{(!isCollapsed || isMobile) && (
|
||||
<ListItemText primary={res.pluralLabel} />
|
||||
)}
|
||||
</ListItemButton>
|
||||
</Tooltip>
|
||||
</ListItem>
|
||||
))}
|
||||
@@ -149,51 +189,7 @@ export default function AdminLayout({
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<CssBaseline />
|
||||
<AppBar
|
||||
position="fixed"
|
||||
sx={{
|
||||
zIndex: (theme) => theme.zIndex.drawer + 1,
|
||||
backdropFilter: 'blur(8px)',
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
||||
color: 'text.primary',
|
||||
boxShadow: 'none',
|
||||
borderBottom: '1px solid',
|
||||
borderColor: 'divider',
|
||||
}}
|
||||
>
|
||||
<Toolbar>
|
||||
{isMobile && (
|
||||
<IconButton
|
||||
color="inherit"
|
||||
aria-label="open drawer"
|
||||
edge="start"
|
||||
onClick={handleDrawerToggle}
|
||||
sx={{ mr: 2 }}
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1, fontWeight: 'bold' }}>
|
||||
Admin Panel
|
||||
</Typography>
|
||||
<Box sx={{ display: { xs: 'none', sm: 'flex' }, alignItems: 'center', mr: 2 }}>
|
||||
<Button
|
||||
color="inherit"
|
||||
onClick={() => navigate('/admin/profile')}
|
||||
sx={{ textTransform: 'none', fontWeight: 500 }}
|
||||
>
|
||||
{username}
|
||||
</Button>
|
||||
</Box>
|
||||
<Tooltip title="Logout">
|
||||
<IconButton color="inherit" onClick={onLogout}>
|
||||
<LogoutIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
|
||||
{/* NAV */}
|
||||
<Box
|
||||
component="nav"
|
||||
sx={{ width: { md: currentWidth }, flexShrink: { md: 0 } }}
|
||||
@@ -203,10 +199,12 @@ export default function AdminLayout({
|
||||
variant="temporary"
|
||||
open={mobileOpen}
|
||||
onClose={handleDrawerToggle}
|
||||
ModalProps={{ keepMounted: true }}
|
||||
ModalProps={{ keepMounted: true }}
|
||||
sx={{
|
||||
display: { xs: 'block', md: 'none' },
|
||||
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
|
||||
'& .MuiDrawer-paper': {
|
||||
width: drawerWidth,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{drawerContent}
|
||||
@@ -214,46 +212,52 @@ export default function AdminLayout({
|
||||
) : (
|
||||
<Drawer
|
||||
variant="permanent"
|
||||
open
|
||||
sx={{
|
||||
display: { xs: 'none', md: 'block' },
|
||||
width: currentWidth,
|
||||
flexShrink: 0,
|
||||
whiteSpace: 'nowrap',
|
||||
boxSizing: 'border-box',
|
||||
transition: (theme) => theme.transitions.create('width', {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.enteringScreen,
|
||||
}),
|
||||
[`& .MuiDrawer-paper`]: {
|
||||
width: currentWidth,
|
||||
boxSizing: 'border-box',
|
||||
[`& .MuiDrawer-paper`]: {
|
||||
width: currentWidth,
|
||||
overflowX: 'hidden',
|
||||
transition: (theme) => theme.transitions.create('width', {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.enteringScreen,
|
||||
}),
|
||||
transition: theme.transitions.create('width'),
|
||||
},
|
||||
}}
|
||||
open
|
||||
>
|
||||
{drawerContent}
|
||||
</Drawer>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
component="main"
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
p: { xs: 2, md: 3 },
|
||||
width: { xs: '100%', md: `calc(100% - ${currentWidth}px)` },
|
||||
transition: (theme) => theme.transitions.create(['margin', 'width'], {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.enteringScreen,
|
||||
}),
|
||||
{/* MAIN */}
|
||||
<Box
|
||||
component="main"
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
p: { xs: 2, md: 3 },
|
||||
width: {
|
||||
xs: '100%',
|
||||
md: `calc(100% - ${currentWidth}px)`,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Toolbar />
|
||||
{/* Control row (replaces AppBar) */}
|
||||
{isMobile && (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
mb: 2,
|
||||
height: (theme) => theme.spacing(7),
|
||||
}}
|
||||
>
|
||||
<IconButton onClick={handleDrawerToggle}>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user