From 51be3b54f6931ef06e7e93560a774f08fcb7a83d Mon Sep 17 00:00:00 2001 From: Matthias Hochmeister Date: Sat, 28 Mar 2026 18:23:00 +0100 Subject: [PATCH] feat: add vehicle type assignment to vehicle edit/create form --- frontend/src/pages/FahrzeugForm.tsx | 37 ++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/FahrzeugForm.tsx b/frontend/src/pages/FahrzeugForm.tsx index 09aac5f..24383cd 100644 --- a/frontend/src/pages/FahrzeugForm.tsx +++ b/frontend/src/pages/FahrzeugForm.tsx @@ -1,8 +1,10 @@ import React, { useEffect, useState, useCallback } from 'react'; import { Alert, + Autocomplete, Box, Button, + Chip, CircularProgress, Container, Grid, @@ -15,6 +17,8 @@ import { useNavigate, useParams } from 'react-router-dom'; import DashboardLayout from '../components/dashboard/DashboardLayout'; import GermanDateField from '../components/shared/GermanDateField'; import { vehiclesApi } from '../services/vehicles'; +import { fahrzeugTypenApi } from '../services/fahrzeugTypen'; +import type { FahrzeugTyp } from '../types/checklist.types'; import { CreateFahrzeugPayload, UpdateFahrzeugPayload, @@ -78,12 +82,22 @@ function FahrzeugForm() { const [saveError, setSaveError] = useState(null); const [fieldErrors, setFieldErrors] = useState>>({}); + const [allTypes, setAllTypes] = useState([]); + const [selectedTypes, setSelectedTypes] = useState([]); + + useEffect(() => { + fahrzeugTypenApi.getAll().then(setAllTypes).catch(() => {}); + }, []); + const fetchVehicle = useCallback(async () => { if (!id) return; try { setLoading(true); setError(null); - const vehicle = await vehiclesApi.getById(id); + const [vehicle, types] = await Promise.all([ + vehiclesApi.getById(id), + fahrzeugTypenApi.getTypesForVehicle(id).catch(() => [] as FahrzeugTyp[]), + ]); setForm({ bezeichnung: vehicle.bezeichnung, kurzname: vehicle.kurzname ?? '', @@ -98,6 +112,7 @@ function FahrzeugForm() { paragraph57a_faellig_am: toDateInput(vehicle.paragraph57a_faellig_am), naechste_wartung_am: toDateInput(vehicle.naechste_wartung_am), }); + setSelectedTypes(types); } catch { setError('Fahrzeug konnte nicht geladen werden.'); } finally { @@ -162,6 +177,7 @@ function FahrzeugForm() { naechste_wartung_am: form.naechste_wartung_am || null, }; await vehiclesApi.update(id, payload); + await fahrzeugTypenApi.setTypesForVehicle(id, selectedTypes.map((t) => t.id)); navigate(`/fahrzeuge/${id}`); } else { const payload: CreateFahrzeugPayload = { @@ -179,6 +195,7 @@ function FahrzeugForm() { naechste_wartung_am: form.naechste_wartung_am || undefined, }; const newVehicle = await vehiclesApi.create(payload); + await fahrzeugTypenApi.setTypesForVehicle(newVehicle.id, selectedTypes.map((t) => t.id)); navigate(`/fahrzeuge/${newVehicle.id}`); } } catch { @@ -268,6 +285,24 @@ function FahrzeugForm() { placeholder="z.B. WN-FW 1" /> + + o.name} + value={selectedTypes} + onChange={(_e, val) => setSelectedTypes(val)} + isOptionEqualToValue={(a, b) => a.id === b.id} + renderTags={(value, getTagProps) => + value.map((option, index) => ( + + )) + } + renderInput={(params) => ( + + )} + /> + Prüf- und Wartungsfristen