import React, { useEffect, useState, useCallback } from 'react';
import {
Alert,
Box,
Button,
CircularProgress,
Container,
FormControl,
Grid,
InputLabel,
MenuItem,
Paper,
Select,
TextField,
Typography,
} from '@mui/material';
import { ArrowBack, Save } from '@mui/icons-material';
import { useNavigate, useParams } from 'react-router-dom';
import DashboardLayout from '../components/dashboard/DashboardLayout';
import { vehiclesApi } from '../services/vehicles';
import { toGermanDate, fromGermanDate } from '../utils/dateInput';
import {
FahrzeugStatus,
FahrzeugStatusLabel,
CreateFahrzeugPayload,
UpdateFahrzeugPayload,
} from '../types/vehicle.types';
import { usePermissions } from '../hooks/usePermissions';
// ── Form state shape ──────────────────────────────────────────────────────────
interface FormState {
bezeichnung: string;
kurzname: string;
amtliches_kennzeichen: string;
fahrgestellnummer: string;
baujahr: string; // kept as string for input, parsed on submit
hersteller: string;
typ_schluessel: string;
besatzung_soll: string;
status: FahrzeugStatus;
status_bemerkung: string;
standort: string;
bild_url: string;
paragraph57a_faellig_am: string; // ISO date 'YYYY-MM-DD' or ''
naechste_wartung_am: string; // ISO date 'YYYY-MM-DD' or ''
}
const EMPTY_FORM: FormState = {
bezeichnung: '',
kurzname: '',
amtliches_kennzeichen: '',
fahrgestellnummer: '',
baujahr: '',
hersteller: '',
typ_schluessel: '',
besatzung_soll: '',
status: FahrzeugStatus.Einsatzbereit,
status_bemerkung: '',
standort: 'Feuerwehrhaus',
bild_url: '',
paragraph57a_faellig_am: '',
naechste_wartung_am: '',
};
// ── Helpers ───────────────────────────────────────────────────────────────────
/** Convert a Date ISO string like '2026-03-15T00:00:00.000Z' to 'DD.MM.YYYY' */
function toDateInput(iso: string | null | undefined): string {
return toGermanDate(iso);
}
// ── Component ─────────────────────────────────────────────────────────────────
function FahrzeugForm() {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const { isAdmin } = usePermissions();
const isEditMode = Boolean(id);
// ── Permission guard: only admins may create or edit vehicles ──────────────
if (!isAdmin) {
return (
Keine Berechtigung
Sie haben nicht die erforderlichen Rechte, um Fahrzeuge zu bearbeiten.
);
}
const [form, setForm] = useState(EMPTY_FORM);
const [loading, setLoading] = useState(isEditMode);
const [saving, setSaving] = useState(false);
const [error, setError] = useState(null);
const [saveError, setSaveError] = useState(null);
const [fieldErrors, setFieldErrors] = useState>>({});
const fetchVehicle = useCallback(async () => {
if (!id) return;
try {
setLoading(true);
setError(null);
const vehicle = await vehiclesApi.getById(id);
setForm({
bezeichnung: vehicle.bezeichnung,
kurzname: vehicle.kurzname ?? '',
amtliches_kennzeichen: vehicle.amtliches_kennzeichen ?? '',
fahrgestellnummer: vehicle.fahrgestellnummer ?? '',
baujahr: vehicle.baujahr?.toString() ?? '',
hersteller: vehicle.hersteller ?? '',
typ_schluessel: vehicle.typ_schluessel ?? '',
besatzung_soll: vehicle.besatzung_soll ?? '',
status: vehicle.status,
status_bemerkung: vehicle.status_bemerkung ?? '',
standort: vehicle.standort,
bild_url: vehicle.bild_url ?? '',
paragraph57a_faellig_am: toDateInput(vehicle.paragraph57a_faellig_am),
naechste_wartung_am: toDateInput(vehicle.naechste_wartung_am),
});
} catch {
setError('Fahrzeug konnte nicht geladen werden.');
} finally {
setLoading(false);
}
}, [id]);
useEffect(() => {
if (isEditMode) fetchVehicle();
}, [isEditMode, fetchVehicle]);
const validate = (): boolean => {
const errors: Partial> = {};
if (!form.bezeichnung.trim()) {
errors.bezeichnung = 'Bezeichnung ist erforderlich.';
}
setFieldErrors(errors);
return Object.keys(errors).length === 0;
};
const handleSubmit = async () => {
if (!validate()) return;
try {
setSaving(true);
setSaveError(null);
if (isEditMode && id) {
const payload: UpdateFahrzeugPayload = {
bezeichnung: form.bezeichnung.trim() || undefined,
kurzname: form.kurzname.trim() || undefined,
amtliches_kennzeichen: form.amtliches_kennzeichen.trim() || undefined,
fahrgestellnummer: form.fahrgestellnummer.trim() || undefined,
baujahr: form.baujahr ? Number(form.baujahr) : undefined,
hersteller: form.hersteller.trim() || undefined,
typ_schluessel: form.typ_schluessel.trim() || undefined,
besatzung_soll: form.besatzung_soll.trim() || undefined,
status: form.status,
status_bemerkung: form.status_bemerkung.trim() || undefined,
standort: form.standort.trim() || 'Feuerwehrhaus',
bild_url: form.bild_url.trim() || undefined,
paragraph57a_faellig_am: form.paragraph57a_faellig_am ? fromGermanDate(form.paragraph57a_faellig_am) || undefined : undefined,
naechste_wartung_am: form.naechste_wartung_am ? fromGermanDate(form.naechste_wartung_am) || undefined : undefined,
};
await vehiclesApi.update(id, payload);
navigate(`/fahrzeuge/${id}`);
} else {
const payload: CreateFahrzeugPayload = {
bezeichnung: form.bezeichnung.trim(),
kurzname: form.kurzname.trim() || undefined,
amtliches_kennzeichen: form.amtliches_kennzeichen.trim() || undefined,
fahrgestellnummer: form.fahrgestellnummer.trim() || undefined,
baujahr: form.baujahr ? Number(form.baujahr) : undefined,
hersteller: form.hersteller.trim() || undefined,
typ_schluessel: form.typ_schluessel.trim() || undefined,
besatzung_soll: form.besatzung_soll.trim() || undefined,
status: form.status,
status_bemerkung: form.status_bemerkung.trim() || undefined,
standort: form.standort.trim() || 'Feuerwehrhaus',
bild_url: form.bild_url.trim() || undefined,
paragraph57a_faellig_am: form.paragraph57a_faellig_am ? fromGermanDate(form.paragraph57a_faellig_am) || undefined : undefined,
naechste_wartung_am: form.naechste_wartung_am ? fromGermanDate(form.naechste_wartung_am) || undefined : undefined,
};
const newVehicle = await vehiclesApi.create(payload);
navigate(`/fahrzeuge/${newVehicle.id}`);
}
} catch {
setSaveError(
isEditMode
? 'Fahrzeug konnte nicht gespeichert werden.'
: 'Fahrzeug konnte nicht erstellt werden.'
);
} finally {
setSaving(false);
}
};
const f = (field: keyof FormState) => ({
value: form[field] as string,
onChange: (e: React.ChangeEvent) =>
setForm((prev) => ({ ...prev, [field]: e.target.value })),
error: Boolean(fieldErrors[field]),
helperText: fieldErrors[field],
});
if (loading) {
return (
);
}
if (error) {
return (
{error}
} onClick={() => navigate('/fahrzeuge')} sx={{ mt: 2 }}>
Zurück
);
}
return (
}
onClick={() => (isEditMode && id ? navigate(`/fahrzeuge/${id}`) : navigate('/fahrzeuge'))}
sx={{ mb: 2 }}
size="small"
>
{isEditMode ? 'Zurück zur Detailansicht' : 'Fahrzeugübersicht'}
{isEditMode ? 'Fahrzeug bearbeiten' : 'Neues Fahrzeug erfassen'}
{saveError && {saveError}}
Stammdaten
Status
Status
Prüf- und Wartungsfristen
setForm((prev) => ({ ...prev, paragraph57a_faellig_am: e.target.value }))}
InputLabelProps={{ shrink: true }}
helperText="Periodische Begutachtung (§57a StVO)"
/>
setForm((prev) => ({ ...prev, naechste_wartung_am: e.target.value }))}
InputLabelProps={{ shrink: true }}
helperText="Nächster geplanter Servicetermin"
/>
Bild
: }
onClick={handleSubmit}
disabled={saving}
>
{isEditMode ? 'Änderungen speichern' : 'Fahrzeug erstellen'}
);
}
export default FahrzeugForm;