adding chat features, admin features and bug fixes

This commit is contained in:
Matthias Hochmeister
2026-03-12 08:16:34 +01:00
parent 7b14e3d5ba
commit 31f1414e06
43 changed files with 2610 additions and 16 deletions

View File

@@ -1,5 +1,8 @@
import { useMemo } from 'react';
import {
Box,
Drawer,
IconButton,
List,
ListItem,
ListItemButton,
@@ -15,10 +18,16 @@ import {
People,
Air,
CalendarMonth,
MenuBook,
AdminPanelSettings,
ChevronLeft,
ChevronRight,
} from '@mui/icons-material';
import { useNavigate, useLocation } from 'react-router-dom';
import { useLayout, DRAWER_WIDTH, DRAWER_WIDTH_COLLAPSED } from '../../contexts/LayoutContext';
import { useAuth } from '../../contexts/AuthContext';
const DRAWER_WIDTH = 240;
export { DRAWER_WIDTH, DRAWER_WIDTH_COLLAPSED };
interface NavigationItem {
text: string;
@@ -26,7 +35,7 @@ interface NavigationItem {
path: string;
}
const navigationItems: NavigationItem[] = [
const baseNavigationItems: NavigationItem[] = [
{
text: 'Dashboard',
icon: <DashboardIcon />,
@@ -57,8 +66,19 @@ const navigationItems: NavigationItem[] = [
icon: <Air />,
path: '/atemschutz',
},
{
text: 'Wissen',
icon: <MenuBook />,
path: '/wissen',
},
];
const adminItem: NavigationItem = {
text: 'Admin',
icon: <AdminPanelSettings />,
path: '/admin',
};
interface SidebarProps {
mobileOpen: boolean;
onMobileClose: () => void;
@@ -67,6 +87,14 @@ interface SidebarProps {
function Sidebar({ mobileOpen, onMobileClose }: SidebarProps) {
const navigate = useNavigate();
const location = useLocation();
const { sidebarCollapsed, toggleSidebar } = useLayout();
const { user } = useAuth();
const isAdmin = user?.groups?.includes('dashboard_admin') ?? false;
const navigationItems = useMemo(() => {
return isAdmin ? [...baseNavigationItems, adminItem] : baseNavigationItems;
}, [isAdmin]);
const handleNavigation = (path: string) => {
navigate(path);
@@ -74,19 +102,25 @@ function Sidebar({ mobileOpen, onMobileClose }: SidebarProps) {
};
const drawerContent = (
<>
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<Toolbar />
<List>
<List sx={{ flex: 1 }}>
{navigationItems.map((item) => {
const isActive = location.pathname === item.path;
return (
<ListItem key={item.text} disablePadding>
<Tooltip title={item.text} placement="right" arrow>
<Tooltip
title={item.text}
placement="right"
arrow
disableHoverListener={!sidebarCollapsed}
>
<ListItemButton
selected={isActive}
onClick={() => handleNavigation(item.path)}
aria-label={`Zu ${item.text} navigieren`}
sx={{
justifyContent: sidebarCollapsed ? 'center' : 'initial',
'&.Mui-selected': {
backgroundColor: 'primary.light',
color: 'primary.contrastText',
@@ -102,18 +136,30 @@ function Sidebar({ mobileOpen, onMobileClose }: SidebarProps) {
<ListItemIcon
sx={{
color: isActive ? 'inherit' : 'text.secondary',
minWidth: sidebarCollapsed ? 0 : undefined,
justifyContent: 'center',
}}
>
{item.icon}
</ListItemIcon>
<ListItemText primary={item.text} />
<ListItemText
primary={item.text}
sx={{
display: sidebarCollapsed ? 'none' : 'block',
}}
/>
</ListItemButton>
</Tooltip>
</ListItem>
);
})}
</List>
</>
<Box sx={{ display: 'flex', justifyContent: 'center', mb: 1 }}>
<IconButton onClick={toggleSidebar} aria-label="Sidebar umschalten">
{sidebarCollapsed ? <ChevronRight /> : <ChevronLeft />}
</IconButton>
</Box>
</Box>
);
return (
@@ -143,11 +189,13 @@ function Sidebar({ mobileOpen, onMobileClose }: SidebarProps) {
variant="permanent"
sx={{
display: { xs: 'none', sm: 'block' },
width: DRAWER_WIDTH,
width: sidebarCollapsed ? DRAWER_WIDTH_COLLAPSED : DRAWER_WIDTH,
flexShrink: 0,
'& .MuiDrawer-paper': {
width: DRAWER_WIDTH,
width: sidebarCollapsed ? DRAWER_WIDTH_COLLAPSED : DRAWER_WIDTH,
boxSizing: 'border-box',
transition: 'width 225ms cubic-bezier(0.4, 0, 0.6, 1)',
overflowX: 'hidden',
},
}}
open