refine vehicle freatures
This commit is contained in:
688
plans/2026-02-28-vehicle-equipment-features.md
Normal file
688
plans/2026-02-28-vehicle-equipment-features.md
Normal file
@@ -0,0 +1,688 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user