This commit is contained in:
seb
2026-06-23 11:04:28 +02:00
commit 24f68c94f3
16 changed files with 2580 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
import { useState } from 'react';
import Box from '@mui/material/Box';
import List from '@mui/material/List';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import UserMenu from './UserMenu';
import { NAV_ITEMS } from '../nav';
const SIDEBAR_WIDTH = 240;
// App layout. State lives in the children (UserMenu, page content) so the
// shell itself does not re-render when their state changes.
export default function AppShell() {
const [activeId, setActiveId] = useState(NAV_ITEMS[0].id);
const activeItem = NAV_ITEMS.find((item) => item.id === activeId) ?? NAV_ITEMS[0];
const ActivePage = activeItem.Page;
return (
<Box sx={{ display: 'flex', minHeight: '100vh', bgcolor: 'grey.50' }}>
<Box
component="nav"
sx={{
width: SIDEBAR_WIDTH,
flexShrink: 0,
display: 'flex',
flexDirection: 'column',
bgcolor: 'background.paper',
}}
>
<List disablePadding sx={{ flexGrow: 1 }}>
{NAV_ITEMS.map(({ id, label, icon: Icon }) => (
<ListItemButton
key={id}
disableGutters
selected={id === activeId}
onClick={() => setActiveId(id)}
sx={{ borderRadius: 0, px: 2 }}
>
<ListItemIcon sx={{ minWidth: 40 }}>
<Icon />
</ListItemIcon>
<ListItemText primary={label} />
</ListItemButton>
))}
</List>
<UserMenu />
</Box>
<Box component="main" sx={{ flexGrow: 1, py: 4, px: 3 }}>
<ActivePage />
</Box>
</Box>
);
}