28 KiB
28 KiB
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)
- P1: Remove info fields — Remove Fahrgestellnr., Standort, Besatzung, Typ, Hersteller, Baujahr from frontend
- P2: Delete vehicle UI — Add delete button + confirmation dialog to FahrzeugDetail.tsx
- P3: Permission guards — Hide restricted features from unauthorized user groups
Phase 2 — Equipment Backend
- P4: Database migration — Create equipment tables (ausruestung, ausruestung_kategorien, ausruestung_wartungslog)
- P5: Backend model + service + controller + routes — Full backend CRUD for equipment
Phase 3 — Equipment Frontend
- P6: Equipment list page — Replace placeholder with full equipment management page
- P7: Equipment create/edit form — AusruestungForm.tsx
- P8: Equipment detail page — AusruestungDetail.tsx with tabs
Phase 4 — Vehicle-Equipment Integration
- P9: Vehicle detail equipment tab — Show assigned equipment in vehicle detail
- 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 && <Component />}) 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 <Routes>, 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 <ProtectedRoute> 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
# Connect to your database and run: psql -U <user> -d <database> -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:
# Get categories curl -H "Authorization: Bearer <token>" http://localhost:3000/api/equipment/categories # Create equipment curl -X POST -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \ -d '{"bezeichnung":"Test Gerät","kategorie_id":"<uuid>"}' \ 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:
- Assign equipment to a vehicle (via equipment form, set fahrzeug_id)
- Open vehicle detail → verify "Ausrüstung" tab shows the items
- Set an important equipment item to "beschädigt"
- 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