resolve issues with new features
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useState, useMemo } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Collapse,
|
||||
Drawer,
|
||||
IconButton,
|
||||
List,
|
||||
@@ -22,6 +23,8 @@ import {
|
||||
AdminPanelSettings,
|
||||
Settings,
|
||||
Menu as MenuIcon,
|
||||
ExpandMore,
|
||||
ExpandLess,
|
||||
} from '@mui/icons-material';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useLayout, DRAWER_WIDTH, DRAWER_WIDTH_COLLAPSED } from '../../contexts/LayoutContext';
|
||||
@@ -29,12 +32,32 @@ import { useAuth } from '../../contexts/AuthContext';
|
||||
|
||||
export { DRAWER_WIDTH, DRAWER_WIDTH_COLLAPSED };
|
||||
|
||||
interface SubItem {
|
||||
text: string;
|
||||
tabIndex: number;
|
||||
}
|
||||
|
||||
interface NavigationItem {
|
||||
text: string;
|
||||
icon: JSX.Element;
|
||||
path: string;
|
||||
subItems?: SubItem[];
|
||||
}
|
||||
|
||||
const kalenderSubItems: SubItem[] = [
|
||||
{ text: 'Veranstaltungen', tabIndex: 0 },
|
||||
{ text: 'Fahrzeugbuchungen', tabIndex: 1 },
|
||||
];
|
||||
|
||||
const adminSubItems: SubItem[] = [
|
||||
{ text: 'Services', tabIndex: 0 },
|
||||
{ text: 'System', tabIndex: 1 },
|
||||
{ text: 'Benutzer', tabIndex: 2 },
|
||||
{ text: 'Broadcast', tabIndex: 3 },
|
||||
{ text: 'Banner', tabIndex: 4 },
|
||||
{ text: 'Wartung', tabIndex: 5 },
|
||||
];
|
||||
|
||||
const baseNavigationItems: NavigationItem[] = [
|
||||
{
|
||||
text: 'Dashboard',
|
||||
@@ -45,6 +68,7 @@ const baseNavigationItems: NavigationItem[] = [
|
||||
text: 'Kalender',
|
||||
icon: <CalendarMonth />,
|
||||
path: '/kalender',
|
||||
subItems: kalenderSubItems,
|
||||
},
|
||||
{
|
||||
text: 'Fahrzeuge',
|
||||
@@ -77,6 +101,7 @@ const adminItem: NavigationItem = {
|
||||
text: 'Admin',
|
||||
icon: <AdminPanelSettings />,
|
||||
path: '/admin',
|
||||
subItems: adminSubItems,
|
||||
};
|
||||
|
||||
const adminSettingsItem: NavigationItem = {
|
||||
@@ -102,6 +127,19 @@ function Sidebar({ mobileOpen, onMobileClose }: SidebarProps) {
|
||||
return isAdmin ? [...baseNavigationItems, adminItem, adminSettingsItem] : baseNavigationItems;
|
||||
}, [isAdmin]);
|
||||
|
||||
// Expand state for items with sub-items — auto-expand when route matches
|
||||
const [expandedItems, setExpandedItems] = useState<Record<string, boolean>>({});
|
||||
|
||||
const isExpanded = (item: NavigationItem) => {
|
||||
if (expandedItems[item.path] !== undefined) return expandedItems[item.path];
|
||||
// Auto-expand when the current route matches
|
||||
return location.pathname === item.path || location.pathname.startsWith(item.path + '/');
|
||||
};
|
||||
|
||||
const toggleExpand = (path: string) => {
|
||||
setExpandedItems((prev) => ({ ...prev, [path]: !isExpanded({ path } as NavigationItem) }));
|
||||
};
|
||||
|
||||
const handleNavigation = (path: string) => {
|
||||
navigate(path);
|
||||
onMobileClose();
|
||||
@@ -118,50 +156,101 @@ function Sidebar({ mobileOpen, onMobileClose }: SidebarProps) {
|
||||
<List sx={{ flex: 1 }}>
|
||||
{navigationItems.map((item) => {
|
||||
const isActive = location.pathname === item.path;
|
||||
const hasSubItems = item.subItems && item.subItems.length > 0;
|
||||
const expanded = hasSubItems && isExpanded(item);
|
||||
return (
|
||||
<ListItem key={item.text} disablePadding>
|
||||
<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',
|
||||
'&:hover': {
|
||||
backgroundColor: 'primary.main',
|
||||
},
|
||||
'& .MuiListItemIcon-root': {
|
||||
color: 'primary.contrastText',
|
||||
},
|
||||
},
|
||||
}}
|
||||
<Box key={item.text}>
|
||||
<ListItem disablePadding>
|
||||
<Tooltip
|
||||
title={item.text}
|
||||
placement="right"
|
||||
arrow
|
||||
disableHoverListener={!sidebarCollapsed}
|
||||
>
|
||||
<ListItemIcon
|
||||
<ListItemButton
|
||||
selected={isActive}
|
||||
onClick={() => handleNavigation(hasSubItems ? `${item.path}?tab=0` : item.path)}
|
||||
aria-label={`Zu ${item.text} navigieren`}
|
||||
sx={{
|
||||
color: isActive ? 'inherit' : 'text.secondary',
|
||||
minWidth: sidebarCollapsed ? 0 : undefined,
|
||||
justifyContent: 'center',
|
||||
justifyContent: sidebarCollapsed ? 'center' : 'initial',
|
||||
'&.Mui-selected': {
|
||||
backgroundColor: 'primary.light',
|
||||
color: 'primary.contrastText',
|
||||
'&:hover': {
|
||||
backgroundColor: 'primary.main',
|
||||
},
|
||||
'& .MuiListItemIcon-root': {
|
||||
color: 'primary.contrastText',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{item.icon}
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={item.text}
|
||||
sx={{
|
||||
display: sidebarCollapsed ? 'none' : 'block',
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</Tooltip>
|
||||
</ListItem>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
color: isActive ? 'inherit' : 'text.secondary',
|
||||
minWidth: sidebarCollapsed ? 0 : undefined,
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{item.icon}
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={item.text}
|
||||
sx={{
|
||||
display: sidebarCollapsed ? 'none' : 'block',
|
||||
}}
|
||||
/>
|
||||
{hasSubItems && !sidebarCollapsed && (
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
toggleExpand(item.path);
|
||||
}}
|
||||
sx={{ color: isActive ? 'inherit' : 'text.secondary' }}
|
||||
>
|
||||
{expanded ? <ExpandLess fontSize="small" /> : <ExpandMore fontSize="small" />}
|
||||
</IconButton>
|
||||
)}
|
||||
</ListItemButton>
|
||||
</Tooltip>
|
||||
</ListItem>
|
||||
{hasSubItems && !sidebarCollapsed && (
|
||||
<Collapse in={expanded} timeout="auto" unmountOnExit>
|
||||
<List disablePadding>
|
||||
{item.subItems!.map((sub) => {
|
||||
const subPath = `${item.path}?tab=${sub.tabIndex}`;
|
||||
const isSubActive =
|
||||
location.pathname === item.path &&
|
||||
location.search === `?tab=${sub.tabIndex}`;
|
||||
return (
|
||||
<ListItemButton
|
||||
key={sub.tabIndex}
|
||||
onClick={() => handleNavigation(subPath)}
|
||||
selected={isSubActive}
|
||||
sx={{
|
||||
pl: 4,
|
||||
py: 0.5,
|
||||
'&.Mui-selected': {
|
||||
backgroundColor: 'primary.light',
|
||||
color: 'primary.contrastText',
|
||||
'&:hover': {
|
||||
backgroundColor: 'primary.main',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ListItemText
|
||||
primary={sub.text}
|
||||
primaryTypographyProps={{ variant: 'body2' }}
|
||||
/>
|
||||
</ListItemButton>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</Collapse>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
|
||||
Reference in New Issue
Block a user