stabile version
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import { useState } from 'react';
|
||||
import { useNavigate, useLocation, Outlet } from 'react-router-dom';
|
||||
import {
|
||||
Box, Drawer, List, ListItem, ListItemButton, ListItemIcon, ListItemText,
|
||||
@@ -10,91 +9,109 @@ import NotificationsActiveIcon from '@mui/icons-material/NotificationsActive';
|
||||
import CorporateFareIcon from '@mui/icons-material/CorporateFare';
|
||||
import LogoutIcon from '@mui/icons-material/Logout';
|
||||
import DashboardIcon from '@mui/icons-material/Dashboard';
|
||||
import HomeIcon from '@mui/icons-material/Home';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
|
||||
const DRAWER_WIDTH = 240;
|
||||
|
||||
const navItems = [
|
||||
{ label: 'Users', path: '/users', icon: <PeopleIcon />, roles: ['ADMIN'] },
|
||||
{ label: 'Posts', path: '/posts', icon: <ArticleIcon />, roles: ['ADMIN', 'REPORTER'] },
|
||||
{ label: 'Push', path: '/push', icon: <NotificationsActiveIcon />, roles: ['ADMIN'] },
|
||||
{ label: 'Organization', path: '/organizations', icon: <CorporateFareIcon />, roles: ['ADMIN', 'REPORTER'] },
|
||||
{ label: 'Home', path: '/', icon: <HomeIcon />, roles: null },
|
||||
{ label: 'Users', path: '/users', icon: <PeopleIcon />, roles: ['ADMIN'] },
|
||||
{ label: 'Posts', path: '/posts', icon: <ArticleIcon />, roles: ['ADMIN', 'REPORTER'] },
|
||||
{ label: 'Push', path: '/push', icon: <NotificationsActiveIcon />, roles: ['ADMIN'] },
|
||||
{ label: 'Organization', path: '/organizations', icon: <CorporateFareIcon />, roles: ['ADMIN', 'SITE_OWNER'] },
|
||||
];
|
||||
|
||||
function getActiveLabel(pathname) {
|
||||
// Exakter Match für "/" zuerst prüfen, dann startsWith für den Rest
|
||||
const exact = navItems.find((i) => i.path === pathname);
|
||||
if (exact) return exact.label;
|
||||
const partial = navItems.find((i) => i.path !== '/' && pathname.startsWith(i.path));
|
||||
return partial?.label ?? 'Admin';
|
||||
}
|
||||
|
||||
export default function Layout() {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const { logout } = useAuth();
|
||||
const { logout, role } = useAuth();
|
||||
|
||||
const visibleNavItems = navItems.filter(
|
||||
(item) => !item.roles || item.roles.includes(role)
|
||||
);
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
{/* Sidebar */}
|
||||
<Drawer
|
||||
variant="permanent"
|
||||
sx={{
|
||||
width: DRAWER_WIDTH,
|
||||
flexShrink: 0,
|
||||
'& .MuiDrawer-paper': {
|
||||
width: DRAWER_WIDTH,
|
||||
boxSizing: 'border-box',
|
||||
borderRight: '1px solid',
|
||||
borderColor: 'divider',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Toolbar sx={{ px: 2 }}>
|
||||
<DashboardIcon sx={{ mr: 1, color: 'primary.main' }} />
|
||||
<Typography variant="h6" fontWeight={600} color="primary.main">
|
||||
Admin Panel
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
<Divider />
|
||||
<List sx={{ px: 1, pt: 1 }}>
|
||||
{navItems.map((item) => (
|
||||
<ListItem key={item.path} disablePadding sx={{ mb: 0.5 }}>
|
||||
<ListItemButton
|
||||
selected={location.pathname.startsWith(item.path)}
|
||||
onClick={() => navigate(item.path)}
|
||||
sx={{ borderRadius: 2 }}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 36 }}>{item.icon}</ListItemIcon>
|
||||
<ListItemText primary={item.label} />
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
{/* Sidebar */}
|
||||
<Drawer
|
||||
variant="permanent"
|
||||
sx={{
|
||||
width: DRAWER_WIDTH,
|
||||
flexShrink: 0,
|
||||
'& .MuiDrawer-paper': {
|
||||
width: DRAWER_WIDTH,
|
||||
boxSizing: 'border-box',
|
||||
borderRight: '1px solid',
|
||||
borderColor: 'divider',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Toolbar sx={{ px: 2 }}>
|
||||
<DashboardIcon sx={{ mr: 1, color: 'primary.main' }} />
|
||||
<Typography variant="h6" fontWeight={600} color="primary.main">
|
||||
Admin Panel
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
<Divider />
|
||||
<List sx={{ px: 1, pt: 1 }}>
|
||||
{visibleNavItems.map((item) => (
|
||||
<ListItem key={item.path} disablePadding sx={{ mb: 0.5 }}>
|
||||
<ListItemButton
|
||||
selected={
|
||||
item.path === '/'
|
||||
? location.pathname === '/'
|
||||
: location.pathname.startsWith(item.path)
|
||||
}
|
||||
onClick={() => navigate(item.path)}
|
||||
sx={{ borderRadius: 2 }}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 36 }}>{item.icon}</ListItemIcon>
|
||||
<ListItemText primary={item.label} />
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
<Box sx={{ flexGrow: 1 }} />
|
||||
<Divider />
|
||||
<List sx={{ px: 1, py: 1 }}>
|
||||
<ListItem disablePadding>
|
||||
<ListItemButton onClick={logout} sx={{ borderRadius: 2 }}>
|
||||
<ListItemIcon sx={{ minWidth: 36 }}><LogoutIcon /></ListItemIcon>
|
||||
<ListItemText primary="Logout" />
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
<Box sx={{ flexGrow: 1 }} />
|
||||
<Divider />
|
||||
<List sx={{ px: 1, py: 1 }}>
|
||||
<ListItem disablePadding>
|
||||
<ListItemButton onClick={logout} sx={{ borderRadius: 2 }}>
|
||||
<ListItemIcon sx={{ minWidth: 36 }}><LogoutIcon /></ListItemIcon>
|
||||
<ListItemText primary="Logout" />
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
</List>
|
||||
</Drawer>
|
||||
</List>
|
||||
</Drawer>
|
||||
|
||||
{/* Main content */}
|
||||
<Box component="main" sx={{ flexGrow: 1, minHeight: '100vh', bgcolor: 'grey.50' }}>
|
||||
<AppBar
|
||||
position="static"
|
||||
elevation={0}
|
||||
sx={{ bgcolor: 'white', borderBottom: '1px solid', borderColor: 'divider' }}
|
||||
>
|
||||
<Toolbar>
|
||||
<Typography variant="h6" color="text.primary" sx={{ flexGrow: 1 }}>
|
||||
{navItems.find((i) => location.pathname.startsWith(i.path))?.label ?? 'Admin'}
|
||||
</Typography>
|
||||
<Tooltip title="Account">
|
||||
<Avatar sx={{ width: 32, height: 32, bgcolor: 'primary.main', fontSize: 14 }}>A</Avatar>
|
||||
</Tooltip>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Box sx={{ p: 3 }}>
|
||||
<Outlet />
|
||||
{/* Main content */}
|
||||
<Box component="main" sx={{ flexGrow: 1, minHeight: '100vh', bgcolor: 'grey.50' }}>
|
||||
<AppBar
|
||||
position="static"
|
||||
elevation={0}
|
||||
sx={{ bgcolor: 'white', borderBottom: '1px solid', borderColor: 'divider' }}
|
||||
>
|
||||
<Toolbar>
|
||||
<Typography variant="h6" color="text.primary" sx={{ flexGrow: 1 }}>
|
||||
{getActiveLabel(location.pathname)}
|
||||
</Typography>
|
||||
<Tooltip title="Account">
|
||||
<Avatar sx={{ width: 32, height: 32, bgcolor: 'primary.main', fontSize: 14 }}>A</Avatar>
|
||||
</Tooltip>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Box sx={{ p: 3 }}>
|
||||
<Outlet />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user