# Feuerwehr Dashboard — Vehicle & Equipment Feature Plan **Date:** 2026-02-28 **Author:** Claude (brainstorm + analysis) --- ## Feature Status Summary | # | Feature | Status | Work Needed | |---|---------|--------|-------------| | 1 | Add vehicle | DONE | None | | 2 | Edit vehicle | DONE | None | | 3 | Remove vehicle | BACKEND ONLY | Frontend UI (delete button + confirmation dialog) | | 4 | Permission visibility | PARTIAL | Hide restricted UI elements + frontend route guards | | 5 | Remove info fields | NOT DONE | Remove 6 fields from form, detail, list view | | 6 | Equipment system | NOT IMPLEMENTED | Full-stack (DB, backend, frontend) | | 7 | Equipment on vehicle detail | NOT IMPLEMENTED | New tab on vehicle detail page | | 8 | Equipment warnings on vehicle cards | NOT IMPLEMENTED | Warning badges on vehicle overview | --- ## Priority Order ### Phase 1 — Quick Wins (vehicle cleanup) 1. **P1: Remove info fields** — Remove Fahrgestellnr., Standort, Besatzung, Typ, Hersteller, Baujahr from frontend 2. **P2: Delete vehicle UI** — Add delete button + confirmation dialog to FahrzeugDetail.tsx 3. **P3: Permission guards** — Hide restricted features from unauthorized user groups ### Phase 2 — Equipment Backend 4. **P4: Database migration** — Create equipment tables (ausruestung, ausruestung_kategorien, ausruestung_wartungslog) 5. **P5: Backend model + service + controller + routes** — Full backend CRUD for equipment ### Phase 3 — Equipment Frontend 6. **P6: Equipment list page** — Replace placeholder with full equipment management page 7. **P7: Equipment create/edit form** — AusruestungForm.tsx 8. **P8: Equipment detail page** — AusruestungDetail.tsx with tabs ### Phase 4 — Vehicle-Equipment Integration 9. **P9: Vehicle detail equipment tab** — Show assigned equipment in vehicle detail 10. **P10: Vehicle card warning badges** — Show warnings when important equipment is not ready --- ## Subagent Prompts ### PROMPT 1: Remove Info Fields (P1) ``` You are a senior React/TypeScript developer working on a Feuerwehr (fire department) Dashboard. TASK: Remove these 6 info fields from the frontend display: - Fahrgestellnr. (fahrgestellnummer) - Standort (standort) - Besatzung (besatzung_soll) - Typ (typ_schluessel) - Hersteller (hersteller) - Baujahr (baujahr) FILES TO MODIFY: 1. /Users/matthias/work/feuerwehr_dashboard/frontend/src/pages/FahrzeugForm.tsx - Remove the TextField inputs for all 6 fields from the form - Remove them from the form state (formData) and any related onChange handlers - Keep the fields in the TypeScript types and backend — only remove from UI 2. /Users/matthias/work/feuerwehr_dashboard/frontend/src/pages/FahrzeugDetail.tsx - Remove the display rows for these 6 fields from the "Übersicht" tab data grid - They appear in the info section showing vehicle details 3. /Users/matthias/work/feuerwehr_dashboard/frontend/src/pages/Fahrzeuge.tsx - Remove besatzung_soll and baujahr from the VehicleCard component display - Remove hersteller from the search filter if it's included - Keep the TypeScript types intact — only remove visual display IMPORTANT: - Do NOT modify backend code, database, or TypeScript type definitions - Do NOT remove the fields from API payloads — just stop displaying them - Clean up any unused imports after removing the fields - Verify the layout still looks good after removal (no empty gaps) - Read each file first before making changes ``` ### PROMPT 2: Delete Vehicle UI (P2) ``` You are a senior React/TypeScript developer working on a Feuerwehr Dashboard. TASK: Add a delete button with confirmation dialog to the vehicle detail page. CONTEXT: - Backend soft-delete endpoint already exists: DELETE /api/vehicles/:id (admin only) - Frontend API method exists: vehiclesApi.delete(id) in /frontend/src/services/vehicles.ts - Permission hook: usePermissions() returns { isAdmin, canChangeStatus } - Delete should only be visible to admin users (isAdmin === true) FILE TO MODIFY: /Users/matthias/work/feuerwehr_dashboard/frontend/src/pages/FahrzeugDetail.tsx REQUIREMENTS: 1. Add a DELETE button (red/error color) next to the existing EDIT button in the header area - Only visible when isAdmin is true (same guard as edit button) - Use MUI DeleteOutline or Delete icon - Button variant: outlined, color: error 2. Add a CONFIRMATION DIALOG (MUI Dialog component): - Title: "Fahrzeug löschen" - Body: "Möchten Sie das Fahrzeug '{vehicle.bezeichnung}' wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden." - Cancel button: "Abbrechen" (default, autofocus) - Confirm button: "Löschen" (red/error color) 3. On confirm: - Call vehiclesApi.delete(id) - Show success notification (use the existing notification system/context) - Navigate to /fahrzeuge after successful deletion - Handle errors: show error notification if delete fails 4. State management: - useState for dialog open/close - useState for loading state during delete (disable buttons) PATTERNS TO FOLLOW: - Look at how the status change dialog works in the same file for patterns - Use the existing useNotification() or similar notification hook - Follow existing import patterns and code style - Read the file first to understand the existing structure ``` ### PROMPT 3: Permission Guards (P3) ``` You are a senior React/TypeScript developer working on a Feuerwehr Dashboard. TASK: Ensure features that require specific user groups are NOT VISIBLE to unauthorized users. CONTEXT: - usePermissions() hook at /frontend/src/hooks/usePermissions.ts returns { isAdmin, canChangeStatus, groups } - Groups: dashboard_admin (full access), dashboard_fahrmeister (status + wartung) - Backend already enforces permissions via requireGroups() middleware - The goal is to also HIDE the UI elements so users don't see options they can't use FILES TO CHECK AND MODIFY: 1. /Users/matthias/work/feuerwehr_dashboard/frontend/src/pages/Fahrzeuge.tsx - Verify: FAB "+" button only shows for isAdmin ✓ (already done) 2. /Users/matthias/work/feuerwehr_dashboard/frontend/src/pages/FahrzeugDetail.tsx - Verify: Edit button only shows for isAdmin ✓ (already done) - Verify: Status change controls only show for canChangeStatus - Verify: Wartungslog add form only shows for canChangeStatus - ADD: Delete button guard (if prompt P2 has been applied) 3. /Users/matthias/work/feuerwehr_dashboard/frontend/src/pages/FahrzeugForm.tsx - ADD: If a non-admin navigates directly to /fahrzeuge/neu or /fahrzeuge/:id/bearbeiten, show an "access denied" message or redirect to /fahrzeuge - Use usePermissions() to check isAdmin - Show a simple Card with "Keine Berechtigung" message and a back button 4. /Users/matthias/work/feuerwehr_dashboard/frontend/src/App.tsx - OPTIONAL: Consider wrapping admin-only routes with a permission-aware ProtectedRoute - If ProtectedRoute already supports group checks, use it - If not, the per-component check in FahrzeugForm.tsx is sufficient 5. Navigation / sidebar: - Check if there are navigation links that should be hidden for certain groups - If a sidebar/drawer component exists, check visibility of menu items REQUIREMENTS: - Read each file before modifying - Do NOT change backend code - Do NOT change the usePermissions hook signature (but you can add new computed properties) - Use conditional rendering ({isAdmin && }) pattern consistently - For route protection, prefer showing "Keine Berechtigung" over redirecting (less confusing UX) ``` ### PROMPT 4: Equipment Database Migration (P4) ``` You are a senior PostgreSQL developer working on a Feuerwehr Dashboard backend. TASK: Create the database migration for the equipment management system. CONTEXT: - Existing migrations are at /Users/matthias/work/feuerwehr_dashboard/backend/src/database/migrations/ - Latest migration is 010_simplify_wartungslog_art.sql - New migration should be 011_create_ausruestung.sql - The database uses uuid_generate_v4() for PKs (uuid-ossp extension already enabled) - Existing pattern: update_updated_at_column() trigger function already exists - Vehicles table: fahrzeuge (with soft-delete via deleted_at) CREATE FILE: /Users/matthias/work/feuerwehr_dashboard/backend/src/database/migrations/011_create_ausruestung.sql SCHEMA: 1. TABLE ausruestung_kategorien: - id UUID PK DEFAULT uuid_generate_v4() - name VARCHAR(100) NOT NULL UNIQUE - kurzname VARCHAR(30) NOT NULL UNIQUE - sortierung INTEGER NOT NULL DEFAULT 0 - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() 2. TABLE ausruestung: - id UUID PK DEFAULT uuid_generate_v4() - bezeichnung VARCHAR(200) NOT NULL - kategorie_id UUID NOT NULL FK → ausruestung_kategorien(id) - seriennummer VARCHAR(100) - inventarnummer VARCHAR(50) - hersteller VARCHAR(150) - baujahr INTEGER CHECK (1950-2100) - status VARCHAR(30) NOT NULL DEFAULT 'einsatzbereit' CHECK IN ('einsatzbereit','beschaedigt','in_wartung','ausser_dienst') - status_bemerkung TEXT - ist_wichtig BOOLEAN NOT NULL DEFAULT FALSE - fahrzeug_id UUID FK → fahrzeuge(id) ON DELETE SET NULL (nullable) - standort VARCHAR(150) NOT NULL DEFAULT 'Lager' - pruef_intervall_monate INTEGER CHECK > 0 - letzte_pruefung_am DATE - naechste_pruefung_am DATE - bemerkung TEXT - deleted_at TIMESTAMPTZ - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() 3. TABLE ausruestung_wartungslog: - id UUID PK DEFAULT uuid_generate_v4() - ausruestung_id UUID NOT NULL FK → ausruestung(id) ON DELETE CASCADE - datum DATE NOT NULL - art VARCHAR(30) NOT NULL CHECK IN ('Prüfung','Reparatur','Sonstiges') - beschreibung TEXT NOT NULL - ergebnis VARCHAR(30) CHECK IN ('bestanden','bestanden_mit_maengeln','nicht_bestanden') - kosten DECIMAL(8,2) CHECK >= 0 - pruefende_stelle VARCHAR(150) - dokument_url VARCHAR(500) - erfasst_von UUID FK → users(id) ON DELETE SET NULL - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() 4. VIEW ausruestung_mit_pruefstatus: - Join ausruestung + kategorien + fahrzeuge (LEFT JOIN) - Compute pruefung_tage_bis_faelligkeit - Filter WHERE deleted_at IS NULL 5. INDEXES: status, kategorie, fahrzeug, active (partial WHERE deleted_at IS NULL), pruefung, wichtig (partial composite) 6. TRIGGER: update_updated_at_column on ausruestung 7. SEED DATA for categories: Atemschutzgeräte (PA), Pumpen (Pumpe), Schläuche (SL), Leitern (Leiter), Rettungsgeräte (RG), Messgeräte (MG), PSA (PSA), Kommunikation (Funk), Beleuchtung (Licht), Sonstige (Sonst.) Follow the exact SQL style of existing migrations (read 005_create_fahrzeuge.sql for reference). ``` ### PROMPT 5: Equipment Backend (P5) ``` You are a senior Node.js/TypeScript developer working on a Feuerwehr Dashboard backend. TASK: Create the complete backend for equipment management (model, service, controller, routes). CONTEXT: - Express 5 + TypeScript + PostgreSQL (raw SQL via pg pool, no ORM) - Read existing vehicle implementation as the pattern to follow: - Model: /backend/src/models/vehicle.model.ts - Service: /backend/src/services/vehicle.service.ts - Controller: /backend/src/controllers/vehicle.controller.ts - Routes: /backend/src/routes/vehicle.routes.ts - Database tables: ausruestung, ausruestung_kategorien, ausruestung_wartungslog (created by migration 011) - View: ausruestung_mit_pruefstatus FILES TO CREATE: 1. /backend/src/models/equipment.model.ts - Enums: AusruestungStatus, AusruestungWartungslogArt - Interfaces: AusruestungKategorie, Ausruestung, AusruestungListItem, AusruestungDetail, AusruestungWartungslog, EquipmentStats, VehicleEquipmentWarning - DTOs: CreateAusruestungData, UpdateAusruestungData, CreateAusruestungWartungslogData 2. /backend/src/services/equipment.service.ts Methods: - getAllEquipment() → SELECT from view ausruestung_mit_pruefstatus - getEquipmentById(id) → detail + wartungslog - getEquipmentByVehicle(fahrzeugId) → equipment assigned to vehicle - getCategories() → all categories ordered by sortierung - createEquipment(data, createdBy) → INSERT into ausruestung - updateEquipment(id, data, updatedBy) → dynamic PATCH - deleteEquipment(id, deletedBy) → SET deleted_at - updateStatus(id, status, bemerkung, updatedBy) - addWartungslog(equipmentId, data, createdBy) - getEquipmentStats() → counts by status + inspection alerts - getVehicleWarnings() → important items not einsatzbereit, grouped by fahrzeug - getUpcomingInspections(daysAhead) 3. /backend/src/controllers/equipment.controller.ts - Zod validation schemas (CreateAusruestungSchema, UpdateAusruestungSchema, etc.) - Request handlers matching service methods - Standard { success: true, data: ... } response envelope - Error handling with try/catch and appropriate HTTP status codes 4. /backend/src/routes/equipment.routes.ts - GET / (list), GET /stats, GET /alerts, GET /categories - GET /vehicle-warnings, GET /vehicle/:fahrzeugId - GET /:id (detail) - POST / (create, requireGroups admin+fahrmeister) - PATCH /:id (update, requireGroups admin+fahrmeister) - PATCH /:id/status (status change, requireGroups admin+fahrmeister) - POST /:id/wartung (add log, requireGroups admin+fahrmeister) - DELETE /:id (soft-delete, requireGroups admin only) 5. MODIFY /backend/src/app.ts - Add: import equipmentRoutes from './routes/equipment.routes' - Add: app.use('/api/equipment', equipmentRoutes) IMPORTANT: - Follow EXACT patterns from vehicle implementation (pool.query, error handling, logging) - Use the database pool import from existing config - Use authenticate and requireGroups middleware from existing middleware - Read the vehicle files first to understand all patterns before writing ``` ### PROMPT 6: Equipment Frontend Types + API Service (P6a) ``` You are a senior React/TypeScript developer working on a Feuerwehr Dashboard. TASK: Create the frontend TypeScript types and API service for equipment management. CONTEXT: - Follow the exact patterns from vehicle types and service: - Types: /frontend/src/types/vehicle.types.ts - Service: /frontend/src/services/vehicles.ts - API client: /frontend/src/services/api.ts (Axios instance) FILES TO CREATE: 1. /frontend/src/types/equipment.types.ts - AusruestungStatus enum (einsatzbereit, beschaedigt, in_wartung, ausser_dienst) - AusruestungKategorie interface - AusruestungListItem interface (from view, includes kategorie_name, fahrzeug_bezeichnung, pruefung_tage_bis_faelligkeit) - AusruestungDetail interface (extends with wartungslog array) - AusruestungWartungslog interface - EquipmentStats interface - VehicleEquipmentWarning interface - Create/Update payload types - All Date fields as string (JSON serialization) 2. /frontend/src/services/equipment.ts Methods (using api instance and unwrap pattern from vehicles.ts): - getAll() → AusruestungListItem[] - getById(id) → AusruestungDetail - getByVehicle(fahrzeugId) → AusruestungListItem[] - getCategories() → AusruestungKategorie[] - getStats() → EquipmentStats - getVehicleWarnings() → VehicleEquipmentWarning[] - getAlerts(daysAhead) → InspectionAlert-like array - create(payload) → AusruestungDetail - update(id, payload) → AusruestungDetail - delete(id) → void - updateStatus(id, payload) → void - addWartungslog(id, payload) → AusruestungWartungslog Read the vehicle files first to match patterns exactly. ``` ### PROMPT 7: Equipment List Page (P6b) ``` You are a senior React/TypeScript developer building a Feuerwehr Dashboard with React 18 + MUI 5 + TypeScript. TASK: Replace the placeholder Ausruestung.tsx with a full equipment list page. CONTEXT: - Existing placeholder: /frontend/src/pages/Ausruestung.tsx (just shows "coming soon") - Follow the pattern of /frontend/src/pages/Fahrzeuge.tsx (vehicle list with cards, search, filters) - API service: equipmentApi from /frontend/src/services/equipment.ts - Types: from /frontend/src/types/equipment.types.ts - Permissions: usePermissions() → { isAdmin, canChangeStatus, canManageEquipment } - Layout: DashboardLayout wrapper - Routing: clicking an item navigates to /ausruestung/:id REPLACE FILE: /frontend/src/pages/Ausruestung.tsx REQUIREMENTS: 1. Stats bar at top: - Total equipment count, einsatzbereit count, beschädigt count, prüfung fällig count - Use Chip or small stat cards 2. Filters: - Search field (search across bezeichnung, seriennummer, inventarnummer, hersteller) - Category dropdown (populated from equipmentApi.getCategories()) - Status dropdown (all 4 statuses) - Checkbox: "Nur wichtige" (filter ist_wichtig) - Checkbox: "Prüfung fällig" (filter pruefung_tage_bis_faelligkeit <= 30) 3. Table/List view (use MUI Table or Card grid matching Fahrzeuge.tsx pattern): - Columns: Bezeichnung, Kategorie, Seriennr., Fahrzeug/Standort, Status (chip), Nächste Prüfung - Status chips with color coding: - einsatzbereit → success (green) - beschaedigt → error (red) - in_wartung → warning (orange) - ausser_dienst → default (grey) - Prüfung overdue → red text/chip - Click row → navigate to /ausruestung/:id - Important items: show star/flag icon 4. FAB button to add new equipment: - Only visible to canManageEquipment users - Navigates to /ausruestung/neu 5. Loading state with Skeleton/CircularProgress 6. Error state with retry button 7. Empty state message Read Fahrzeuge.tsx first to match the exact code style, imports, and patterns. ``` ### PROMPT 8: Equipment Form Page (P7) ``` You are a senior React/TypeScript developer building a Feuerwehr Dashboard. TASK: Create the equipment create/edit form page. CONTEXT: - Follow the exact pattern of /frontend/src/pages/FahrzeugForm.tsx - Route: /ausruestung/neu (create) and /ausruestung/:id/bearbeiten (edit) - API: equipmentApi from /frontend/src/services/equipment.ts - Types from /frontend/src/types/equipment.types.ts - Permission: only canManageEquipment users should see this CREATE FILE: /frontend/src/pages/AusruestungForm.tsx FORM FIELDS: - bezeichnung (required, TextField) - kategorie_id (required, Select dropdown from equipmentApi.getCategories()) - seriennummer (TextField) - inventarnummer (TextField) - hersteller (TextField) - baujahr (number input, 1950-2100) - status (Select: einsatzbereit, beschaedigt, in_wartung, ausser_dienst) - status_bemerkung (TextField multiline) - ist_wichtig (Checkbox/Switch with label "Wichtiges Gerät (Warnung auf Fahrzeugkarte)") - fahrzeug_id (Select dropdown, populated from vehiclesApi.getAll(), show "Kein Fahrzeug" option) - standort (TextField, shown when no fahrzeug_id selected) - pruef_intervall_monate (number input) - letzte_pruefung_am (date input) - naechste_pruefung_am (date input) - bemerkung (TextField multiline) BEHAVIOR: - Create mode: empty form, POST on submit - Edit mode: fetch equipment by id, pre-populate all fields, PATCH on submit - Permission check: show "Keine Berechtigung" if not canManageEquipment - Navigate back to /ausruestung or /ausruestung/:id on success - Validation: bezeichnung required, kategorie_id required - Loading states during fetch and submit Read FahrzeugForm.tsx first to match patterns exactly. ``` ### PROMPT 9: Equipment Detail Page (P8) ``` You are a senior React/TypeScript developer building a Feuerwehr Dashboard. TASK: Create the equipment detail page with tabs. CONTEXT: - Follow the pattern of /frontend/src/pages/FahrzeugDetail.tsx - Route: /ausruestung/:id - API: equipmentApi from /frontend/src/services/equipment.ts CREATE FILE: /frontend/src/pages/AusruestungDetail.tsx STRUCTURE (2 tabs): Tab 1 — Übersicht: - Header with bezeichnung, edit button (canManageEquipment), delete button (isAdmin) - Status panel with current status chip + change button (canManageEquipment) - Status change dialog (select new status + bemerkung) - Data grid showing: Kategorie, Seriennummer, Inventarnummer, Hersteller, Baujahr, Fahrzeug (link to /fahrzeuge/:fahrzeug_id), Standort, Wichtig flag, Prüfintervall, Letzte Prüfung, Nächste Prüfung (with days-until color coding) - Delete confirmation dialog (same pattern as vehicle delete from P2) Tab 2 — Wartung: - Timeline/list of wartungslog entries - Each entry shows: datum, art (chip), beschreibung, ergebnis (chip), kosten, pruefende_stelle - Add wartungslog form (canManageEquipment only): - datum (date), art (select), beschreibung (text), ergebnis (select optional), kosten (number optional), pruefende_stelle (text optional) - Sorted by date DESC PATTERNS: - Read FahrzeugDetail.tsx first and follow its exact structure - Use same notification pattern for success/error - Use useParams() for id, useNavigate() for navigation - Loading/error states ``` ### PROMPT 10: Vehicle-Equipment Integration (P9 + P10) ``` You are a senior React/TypeScript developer working on a Feuerwehr Dashboard. TASK: Integrate equipment into the vehicle pages. CONTEXT: - Equipment API: equipmentApi from /frontend/src/services/equipment.ts - Equipment types from /frontend/src/types/equipment.types.ts - Vehicle pages to modify: - /frontend/src/pages/FahrzeugDetail.tsx (add equipment tab) - /frontend/src/pages/Fahrzeuge.tsx (add warning badges on cards) PART A — Vehicle Detail Equipment Tab: MODIFY: /frontend/src/pages/FahrzeugDetail.tsx 1. Add a new tab "Ausrüstung" between existing tabs (after the overview/maintenance tabs) 2. Tab label: "Ausrüstung" with a count badge showing number of assigned items 3. Tab content: - Fetch equipment via equipmentApi.getByVehicle(vehicleId) - Show table/list of assigned equipment: - Bezeichnung, Kategorie, Status (chip), Nächste Prüfung - Status chips with color coding (green/red/orange/grey) - Important items marked with star icon - Click navigates to /ausruestung/:id - Empty state: "Keine Ausrüstung zugewiesen" - Link to /ausruestung page PART B — Vehicle Card Warning Badges: MODIFY: /frontend/src/pages/Fahrzeuge.tsx 1. On mount, fetch equipmentApi.getVehicleWarnings() alongside the vehicle list 2. Group warnings by fahrzeug_id into a Map 3. In VehicleCard component, below existing inspection badges: - If vehicle has warnings, show a Chip: - "1 Ausrüstung beschädigt" (red/error color) or - "2 Ausrüstung nicht bereit" (orange/warning color) - Tooltip showing individual item names 4. Only show if warnings array for that vehicle is non-empty IMPORTANT: - Read both files completely before making changes - Don't break existing tab indexing in FahrzeugDetail - Handle loading states gracefully (don't block vehicle loading) - Equipment fetch failures should not break the vehicle page (catch errors silently) ``` ### PROMPT 11: Routing Updates (included in P6b-P9) ``` You are a senior React/TypeScript developer. TASK: Add equipment routes to the React Router configuration. MODIFY: /Users/matthias/work/feuerwehr_dashboard/frontend/src/App.tsx ADD these routes inside the existing , near the existing /ausruestung route: - /ausruestung → Ausruestung (already exists, will use new component) - /ausruestung/neu → AusruestungForm (new) - /ausruestung/:id/bearbeiten → AusruestungForm (new) - /ausruestung/:id → AusruestungDetail (new) ALSO ADD: - /ausruestung/neu BEFORE /ausruestung/:id (so "neu" isn't matched as an :id) Add imports for AusruestungDetail and AusruestungForm at the top of the file. Wrap each route in following the existing pattern. ALSO MODIFY: /frontend/src/hooks/usePermissions.ts - Add: canManageEquipment: groups.includes('dashboard_admin') || groups.includes('dashboard_fahrmeister') ``` --- ## Step-by-Step Instructions for Matthias ### Phase 1: Vehicle Cleanup (no backend changes, no Docker needed) **Step 1.1 — Remove info fields** - Run subagent with Prompt 1 - Files changed: FahrzeugForm.tsx, FahrzeugDetail.tsx, Fahrzeuge.tsx - Test: Open vehicle form/detail in browser, verify fields are gone - Commit: `feat: remove Fahrgestellnr, Standort, Besatzung, Typ, Hersteller, Baujahr from vehicle UI` **Step 1.2 — Add delete vehicle UI** - Run subagent with Prompt 2 - Files changed: FahrzeugDetail.tsx - Test: Log in as admin, open vehicle detail, click delete, verify dialog, cancel, then test actual delete - Commit: `feat: add delete button with confirmation dialog to vehicle detail page` **Step 1.3 — Permission guards** - Run subagent with Prompt 3 - Files changed: FahrzeugDetail.tsx, FahrzeugForm.tsx, possibly App.tsx - Test: Log in as non-admin user, verify add/edit/delete buttons are hidden, try direct URL to /fahrzeuge/neu - Commit: `feat: hide restricted vehicle features from unauthorized user groups` ### Phase 2: Equipment Backend (requires Docker/PostgreSQL for migration) **Step 2.1 — Create database migration** - Run subagent with Prompt 4 - File created: backend/src/database/migrations/011_create_ausruestung.sql - Action needed: Run migration against your PostgreSQL database ```bash # Connect to your database and run: psql -U -d -f backend/src/database/migrations/011_create_ausruestung.sql ``` - Verify: Check that tables ausruestung, ausruestung_kategorien, ausruestung_wartungslog exist - Verify: Check that view ausruestung_mit_pruefstatus works - Verify: Check that seed categories were inserted - Commit: `feat: add equipment management database schema (migration 011)` **Step 2.2 — Create backend model + service + controller + routes** - Run subagent with Prompt 5 - Files created: equipment.model.ts, equipment.service.ts, equipment.controller.ts, equipment.routes.ts - File modified: app.ts (add route registration) - Test: Start backend, test endpoints with curl/Postman: ```bash # Get categories curl -H "Authorization: Bearer " http://localhost:3000/api/equipment/categories # Create equipment curl -X POST -H "Authorization: Bearer " -H "Content-Type: application/json" \ -d '{"bezeichnung":"Test Gerät","kategorie_id":""}' \ http://localhost:3000/api/equipment ``` - Commit: `feat: add equipment management backend (model, service, controller, routes)` ### Phase 3: Equipment Frontend (no backend changes) **Step 3.1 — Create frontend types + API service** - Run subagent with Prompt 6 - Files created: equipment.types.ts, equipment.ts (service) - Commit: `feat: add equipment TypeScript types and API service` **Step 3.2 — Create equipment list page** - Run subagent with Prompt 7 - File replaced: Ausruestung.tsx - Test: Navigate to /ausruestung, verify list loads (empty state initially) - Commit: `feat: replace equipment placeholder with full list page` **Step 3.3 — Create equipment form** - Run subagent with Prompt 8 - File created: AusruestungForm.tsx - Test: Navigate to /ausruestung/neu, fill form, submit - Commit: `feat: add equipment create/edit form page` **Step 3.4 — Create equipment detail page** - Run subagent with Prompt 9 - File created: AusruestungDetail.tsx - Test: Click on equipment in list, verify detail page with tabs - Commit: `feat: add equipment detail page with tabs` **Step 3.5 — Update routing + permissions** - Run subagent with Prompt 11 - Files modified: App.tsx, usePermissions.ts - Test: Navigate between equipment pages, verify routing works - Commit: `feat: add equipment routes and canManageEquipment permission` ### Phase 4: Integration (modifies vehicle pages) **Step 4.1 — Vehicle-equipment integration** - Run subagent with Prompt 10 - Files modified: FahrzeugDetail.tsx, Fahrzeuge.tsx - Test: 1. Assign equipment to a vehicle (via equipment form, set fahrzeug_id) 2. Open vehicle detail → verify "Ausrüstung" tab shows the items 3. Set an important equipment item to "beschädigt" 4. Open vehicle list → verify warning badge appears on that vehicle's card - Commit: `feat: add equipment tab to vehicle detail and warning badges to vehicle cards` ### Final Verification Checklist - [ ] Vehicle add works (admin only) - [ ] Vehicle edit works (admin only) - [ ] Vehicle delete works with confirmation (admin only) - [ ] Non-admin users cannot see add/edit/delete buttons - [ ] Non-admin users get "Keine Berechtigung" when accessing restricted routes directly - [ ] Removed fields (Fahrgestellnr, Standort, Besatzung, Typ, Hersteller, Baujahr) not visible - [ ] Equipment categories load correctly - [ ] Equipment CRUD works (create, read, update, soft-delete) - [ ] Equipment list page with filters works - [ ] Equipment detail page with tabs works - [ ] Equipment wartungslog can be added - [ ] Vehicle detail shows equipment tab with assigned items - [ ] Vehicle cards show warning badges for non-ready important equipment - [ ] Permission guards work: equipment management restricted to admin + fahrmeister