bug fix for atemschutz

This commit is contained in:
Matthias Hochmeister
2026-03-01 19:17:36 +01:00
parent d9e6c0658f
commit 2630224edd
5 changed files with 59 additions and 1 deletions

View File

@@ -78,6 +78,8 @@ import incidentRoutes from './routes/incident.routes';
import equipmentRoutes from './routes/equipment.routes'; import equipmentRoutes from './routes/equipment.routes';
import nextcloudRoutes from './routes/nextcloud.routes'; import nextcloudRoutes from './routes/nextcloud.routes';
import atemschutzRoutes from './routes/atemschutz.routes'; import atemschutzRoutes from './routes/atemschutz.routes';
import eventsRoutes from './routes/events.routes';
import bookingRoutes from './routes/booking.routes';
app.use('/api/auth', authRoutes); app.use('/api/auth', authRoutes);
app.use('/api/user', userRoutes); app.use('/api/user', userRoutes);
@@ -89,6 +91,8 @@ app.use('/api/incidents', incidentRoutes);
app.use('/api/equipment', equipmentRoutes); app.use('/api/equipment', equipmentRoutes);
app.use('/api/atemschutz', atemschutzRoutes); app.use('/api/atemschutz', atemschutzRoutes);
app.use('/api/nextcloud/talk', nextcloudRoutes); app.use('/api/nextcloud/talk', nextcloudRoutes);
app.use('/api/events', eventsRoutes);
app.use('/api/bookings', bookingRoutes);
// 404 handler // 404 handler
app.use(notFoundHandler); app.use(notFoundHandler);

View File

@@ -4,7 +4,7 @@ import { authenticate } from '../middleware/auth.middleware';
import { requireGroups } from '../middleware/rbac.middleware'; import { requireGroups } from '../middleware/rbac.middleware';
const ADMIN_GROUPS = ['dashboard_admin']; const ADMIN_GROUPS = ['dashboard_admin'];
const WRITE_GROUPS = ['dashboard_admin', 'dashboard_kommandant']; const WRITE_GROUPS = ['dashboard_admin', 'dashboard_atemschutz'];
const router = Router(); const router = Router();

View File

@@ -13,6 +13,7 @@ import EinsatzDetail from './pages/EinsatzDetail';
import Fahrzeuge from './pages/Fahrzeuge'; import Fahrzeuge from './pages/Fahrzeuge';
import FahrzeugDetail from './pages/FahrzeugDetail'; import FahrzeugDetail from './pages/FahrzeugDetail';
import FahrzeugForm from './pages/FahrzeugForm'; import FahrzeugForm from './pages/FahrzeugForm';
import FahrzeugBuchungen from './pages/FahrzeugBuchungen';
import Ausruestung from './pages/Ausruestung'; import Ausruestung from './pages/Ausruestung';
import AusruestungForm from './pages/AusruestungForm'; import AusruestungForm from './pages/AusruestungForm';
import AusruestungDetail from './pages/AusruestungDetail'; import AusruestungDetail from './pages/AusruestungDetail';
@@ -21,6 +22,8 @@ import Mitglieder from './pages/Mitglieder';
import MitgliedDetail from './pages/MitgliedDetail'; import MitgliedDetail from './pages/MitgliedDetail';
import Kalender from './pages/Kalender'; import Kalender from './pages/Kalender';
import UebungDetail from './pages/UebungDetail'; import UebungDetail from './pages/UebungDetail';
import Veranstaltungen from './pages/Veranstaltungen';
import VeranstaltungKategorien from './pages/VeranstaltungKategorien';
import NotFound from './pages/NotFound'; import NotFound from './pages/NotFound';
function App() { function App() {
@@ -176,6 +179,30 @@ function App() {
</ProtectedRoute> </ProtectedRoute>
} }
/> />
<Route
path="/veranstaltungen"
element={
<ProtectedRoute>
<Veranstaltungen />
</ProtectedRoute>
}
/>
<Route
path="/veranstaltungen/kategorien"
element={
<ProtectedRoute>
<VeranstaltungKategorien />
</ProtectedRoute>
}
/>
<Route
path="/fahrzeugbuchungen"
element={
<ProtectedRoute>
<FahrzeugBuchungen />
</ProtectedRoute>
}
/>
<Route path="*" element={<NotFound />} /> <Route path="*" element={<NotFound />} />
</Routes> </Routes>
</AuthProvider> </AuthProvider>

View File

@@ -14,6 +14,9 @@ import {
Build, Build,
People, People,
Air, Air,
Event,
BookOnline,
CalendarMonth,
} from '@mui/icons-material'; } from '@mui/icons-material';
import { useNavigate, useLocation } from 'react-router-dom'; import { useNavigate, useLocation } from 'react-router-dom';
@@ -31,11 +34,26 @@ const navigationItems: NavigationItem[] = [
icon: <DashboardIcon />, icon: <DashboardIcon />,
path: '/dashboard', path: '/dashboard',
}, },
{
text: 'Kalender',
icon: <CalendarMonth />,
path: '/kalender',
},
{
text: 'Veranstaltungen',
icon: <Event />,
path: '/veranstaltungen',
},
{ {
text: 'Fahrzeuge', text: 'Fahrzeuge',
icon: <DirectionsCar />, icon: <DirectionsCar />,
path: '/fahrzeuge', path: '/fahrzeuge',
}, },
{
text: 'Fahrzeugbuchungen',
icon: <BookOnline />,
path: '/fahrzeugbuchungen',
},
{ {
text: 'Ausrüstung', text: 'Ausrüstung',
icon: <Build />, icon: <Build />,

View File

@@ -44,6 +44,7 @@ import DashboardLayout from '../components/dashboard/DashboardLayout';
import { atemschutzApi } from '../services/atemschutz'; import { atemschutzApi } from '../services/atemschutz';
import { membersService } from '../services/members'; import { membersService } from '../services/members';
import { useNotification } from '../contexts/NotificationContext'; import { useNotification } from '../contexts/NotificationContext';
import { useAuth } from '../contexts/AuthContext';
import type { import type {
AtemschutzUebersicht, AtemschutzUebersicht,
AtemschutzStats, AtemschutzStats,
@@ -150,6 +151,8 @@ const StatCard: React.FC<StatCardProps> = ({ label, value, color, bgcolor }) =>
function Atemschutz() { function Atemschutz() {
const notification = useNotification(); const notification = useNotification();
const { user } = useAuth();
const canWrite = user?.groups?.some(g => ['dashboard_admin', 'dashboard_atemschutz'].includes(g)) ?? false;
// Data state // Data state
const [traeger, setTraeger] = useState<AtemschutzUebersicht[]>([]); const [traeger, setTraeger] = useState<AtemschutzUebersicht[]>([]);
@@ -543,6 +546,7 @@ function Atemschutz() {
/> />
</TableCell> </TableCell>
<TableCell align="right"> <TableCell align="right">
{canWrite && (
<Tooltip title="Bearbeiten"> <Tooltip title="Bearbeiten">
<Button <Button
size="small" size="small"
@@ -552,6 +556,8 @@ function Atemschutz() {
<Edit fontSize="small" /> <Edit fontSize="small" />
</Button> </Button>
</Tooltip> </Tooltip>
)}
{canWrite && (
<Tooltip title="Löschen"> <Tooltip title="Löschen">
<Button <Button
size="small" size="small"
@@ -562,6 +568,7 @@ function Atemschutz() {
<Delete fontSize="small" /> <Delete fontSize="small" />
</Button> </Button>
</Tooltip> </Tooltip>
)}
</TableCell> </TableCell>
</TableRow> </TableRow>
); );
@@ -572,6 +579,7 @@ function Atemschutz() {
)} )}
{/* FAB to create */} {/* FAB to create */}
{canWrite && (
<Fab <Fab
color="primary" color="primary"
aria-label="Atemschutzträger hinzufügen" aria-label="Atemschutzträger hinzufügen"
@@ -580,6 +588,7 @@ function Atemschutz() {
> >
<Add /> <Add />
</Fab> </Fab>
)}
{/* ── Add / Edit Dialog ───────────────────────────────────────────── */} {/* ── Add / Edit Dialog ───────────────────────────────────────────── */}
<Dialog <Dialog