689 lines
28 KiB
Markdown
689 lines
28 KiB
Markdown
# 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 && <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
|
|
```bash
|
|
# 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:
|
|
```bash
|
|
# 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:
|
|
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
|