From e0b687988b9705c4c3ff568301aef09456bfc578 Mon Sep 17 00:00:00 2001 From: Matthias Hochmeister Date: Sun, 1 Mar 2026 17:27:39 +0100 Subject: [PATCH] bug fix for atemschutz --- .../src/controllers/atemschutz.controller.ts | 3 - frontend/src/pages/Atemschutz.tsx | 58 ++++++++++++------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/backend/src/controllers/atemschutz.controller.ts b/backend/src/controllers/atemschutz.controller.ts index 39e1d1e..d349e24 100644 --- a/backend/src/controllers/atemschutz.controller.ts +++ b/backend/src/controllers/atemschutz.controller.ts @@ -59,10 +59,8 @@ class AtemschutzController { async create(req: Request, res: Response): Promise { try { - logger.info('Atemschutz create - raw body:', { body: req.body }); const parsed = CreateAtemschutzSchema.safeParse(req.body); if (!parsed.success) { - logger.warn('Atemschutz create - validation failed:', { errors: parsed.error.flatten() }); res.status(400).json({ success: false, message: 'Validierungsfehler', @@ -70,7 +68,6 @@ class AtemschutzController { }); return; } - logger.info('Atemschutz create - parsed data:', { data: parsed.data }); const record = await atemschutzService.create(parsed.data, getUserId(req)); res.status(201).json({ success: true, data: record }); } catch (error: any) { diff --git a/frontend/src/pages/Atemschutz.tsx b/frontend/src/pages/Atemschutz.tsx index 2c75fcb..70b2083 100644 --- a/frontend/src/pages/Atemschutz.tsx +++ b/frontend/src/pages/Atemschutz.tsx @@ -255,6 +255,29 @@ function Atemschutz() { setForm((prev) => ({ ...prev, [field]: value })); }; + /** Safari workaround: capture date value on blur since onChange may not fire */ + const handleDateBlur = (field: keyof AtemschutzFormState) => ( + e: React.FocusEvent + ) => { + const val = e.target.value; + if (val && val !== form[field]) { + setForm((prev) => ({ ...prev, [field]: val })); + } + }; + + /** Normalize dates before submit: ensure 4-digit years, drop invalid values */ + const normalizeDate = (val: string | undefined): string | undefined => { + if (!val) return undefined; + // Match YYYY-MM-DD but with potentially short year + const m = val.match(/^(\d{1,4})-(\d{2})-(\d{2})$/); + if (!m) return undefined; + const year = m[1].padStart(4, '0'); + // Reject obviously wrong years (< 1900 or > 2100) + const y = parseInt(year, 10); + if (y < 1900 || y > 2100) return undefined; + return `${year}-${m[2]}-${m[3]}`; + }; + const handleSubmit = async () => { setDialogError(null); @@ -263,27 +286,17 @@ function Atemschutz() { return; } - // Debug: show form state in alert so we can see exactly what's being sent - const debugPayload = { - lehrgang_datum: form.lehrgang_datum || '(empty)', - untersuchung_datum: form.untersuchung_datum || '(empty)', - untersuchung_gueltig_bis: form.untersuchung_gueltig_bis || '(empty)', - leistungstest_datum: form.leistungstest_datum || '(empty)', - leistungstest_gueltig_bis: form.leistungstest_gueltig_bis || '(empty)', - }; - alert('DEBUG form dates:\n' + JSON.stringify(debugPayload, null, 2)); - setDialogLoading(true); try { if (editingId) { const payload: UpdateAtemschutzPayload = { atemschutz_lehrgang: form.atemschutz_lehrgang, - lehrgang_datum: form.lehrgang_datum || undefined, - untersuchung_datum: form.untersuchung_datum || undefined, - untersuchung_gueltig_bis: form.untersuchung_gueltig_bis || undefined, + lehrgang_datum: normalizeDate(form.lehrgang_datum), + untersuchung_datum: normalizeDate(form.untersuchung_datum), + untersuchung_gueltig_bis: normalizeDate(form.untersuchung_gueltig_bis), untersuchung_ergebnis: (form.untersuchung_ergebnis as UntersuchungErgebnis) || undefined, - leistungstest_datum: form.leistungstest_datum || undefined, - leistungstest_gueltig_bis: form.leistungstest_gueltig_bis || undefined, + leistungstest_datum: normalizeDate(form.leistungstest_datum), + leistungstest_gueltig_bis: normalizeDate(form.leistungstest_gueltig_bis), leistungstest_bestanden: form.leistungstest_bestanden, bemerkung: form.bemerkung || undefined, }; @@ -293,12 +306,12 @@ function Atemschutz() { const payload: CreateAtemschutzPayload = { user_id: form.user_id, atemschutz_lehrgang: form.atemschutz_lehrgang, - lehrgang_datum: form.lehrgang_datum || undefined, - untersuchung_datum: form.untersuchung_datum || undefined, - untersuchung_gueltig_bis: form.untersuchung_gueltig_bis || undefined, + lehrgang_datum: normalizeDate(form.lehrgang_datum), + untersuchung_datum: normalizeDate(form.untersuchung_datum), + untersuchung_gueltig_bis: normalizeDate(form.untersuchung_gueltig_bis), untersuchung_ergebnis: (form.untersuchung_ergebnis as UntersuchungErgebnis) || undefined, - leistungstest_datum: form.leistungstest_datum || undefined, - leistungstest_gueltig_bis: form.leistungstest_gueltig_bis || undefined, + leistungstest_datum: normalizeDate(form.leistungstest_datum), + leistungstest_gueltig_bis: normalizeDate(form.leistungstest_gueltig_bis), leistungstest_bestanden: form.leistungstest_bestanden, bemerkung: form.bemerkung || undefined, }; @@ -643,6 +656,7 @@ function Atemschutz() { fullWidth value={form.lehrgang_datum} onChange={(e) => handleFormChange('lehrgang_datum', e.target.value)} + onBlur={handleDateBlur('lehrgang_datum')} InputLabelProps={{ shrink: true }} /> @@ -661,6 +675,7 @@ function Atemschutz() { fullWidth value={form.untersuchung_datum} onChange={(e) => handleFormChange('untersuchung_datum', e.target.value)} + onBlur={handleDateBlur('untersuchung_datum')} InputLabelProps={{ shrink: true }} /> @@ -672,6 +687,7 @@ function Atemschutz() { fullWidth value={form.untersuchung_gueltig_bis} onChange={(e) => handleFormChange('untersuchung_gueltig_bis', e.target.value)} + onBlur={handleDateBlur('untersuchung_gueltig_bis')} InputLabelProps={{ shrink: true }} /> @@ -709,6 +725,7 @@ function Atemschutz() { fullWidth value={form.leistungstest_datum} onChange={(e) => handleFormChange('leistungstest_datum', e.target.value)} + onBlur={handleDateBlur('leistungstest_datum')} InputLabelProps={{ shrink: true }} /> @@ -720,6 +737,7 @@ function Atemschutz() { fullWidth value={form.leistungstest_gueltig_bis} onChange={(e) => handleFormChange('leistungstest_gueltig_bis', e.target.value)} + onBlur={handleDateBlur('leistungstest_gueltig_bis')} InputLabelProps={{ shrink: true }} />