From d0619141bb423e4d27ae0bd4b64ce33721a162ba Mon Sep 17 00:00:00 2001 From: duffyduck Date: Wed, 12 Aug 2026 14:31:03 +0200 Subject: [PATCH] Fix: Modal-Formulare nach Abbrechen nicht mehr mit alten Daten vorbefuellt Die Modals in der Kundenakte (Bankkarte, Adresse, Ausweis, Zaehler, Zaehlerstand) bleiben dauerhaft gemountet und wurden nur ueber isOpen umgeschaltet. Der Reset-Effekt haengte an ?.id - bei Neuanlage immer undefined, also kein Reset beim erneuten Oeffnen: nach "Abbrechen" standen die vorher getippten Daten noch drin. Jetzt Reset beim Oeffnen (Guard if(!isOpen), Deps [isOpen, ?.id]), weiterhin kein Reset bei jedem Tastendruck. Ausserdem den fehlerhaften useState(()=>{})-Init-Missbrauch im Bankkarten-Modal entfernt. StressfreiEmail-/AdditionalForwards-Modal waren bereits korrekt. Co-Authored-By: Claude Opus 4.8 --- .../src/pages/customers/CustomerDetail.tsx | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/frontend/src/pages/customers/CustomerDetail.tsx b/frontend/src/pages/customers/CustomerDetail.tsx index 866cd880..93e0a2d1 100644 --- a/frontend/src/pages/customers/CustomerDetail.tsx +++ b/frontend/src/pages/customers/CustomerDetail.tsx @@ -2508,12 +2508,14 @@ function AddressModal({ const isPending = createMutation.isPending || updateMutation.isPending; // Beim Öffnen / Wechsel zwischen Adressen aus den Props re-initialisieren. - // Vorher als unbedingte if-setState im Render-Body → Reset bei jedem - // Tastendruck, Straße ließ sich nicht eintippen. + // Guard `if (!isOpen)`: Modal bleibt dauerhaft gemountet – ohne Reset beim + // Öffnen blieben nach „Abbrechen" die vorher getippten Daten stehen. + // Deps nur isOpen + Adress-ID → kein Reset bei jedem Tastendruck. useEffect(() => { + if (!isOpen) return; setFormData(getInitialFormData()); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [address?.id]); + }, [isOpen, address?.id]); return ( @@ -2695,11 +2697,6 @@ function BankCardModal({ const [ibanLookupLoading, setIbanLookupLoading] = useState(false); const [showIbanRequired, setShowIbanRequired] = useState(false); - // Reset form when bankCard changes - useState(() => { - setFormData(getInitialFormData()); - }); - // BIC + Bankname aus der IBAN ableiten (offline über Bundesbank-BLZ im // Backend). Ist das IBAN-Feld leer, kommt eine OK-Messagebox statt einer // Anfrage. Gleichzeitig prüft der Server die IBAN-Prüfziffer (Tippfehler). @@ -2772,12 +2769,19 @@ function BankCardModal({ const isPending = createMutation.isPending || updateMutation.isPending; - // Re-Init nur beim Wechsel zur anderen Karte – nicht bei jedem - // Tastendruck (das löste vorher Reset auf DB-Wert aus). + // Formular zurücksetzen, sobald die Modal geöffnet wird (Neuanlage: leer, + // Bearbeiten: Kartendaten). Nötig, weil beide Modal-Instanzen dauerhaft + // gemountet bleiben und nur per isOpen umgeschaltet werden – ohne diesen + // Reset blieben nach „Abbrechen" die vorher getippten Daten stehen. + // Läuft NICHT bei jedem Tastendruck (Deps nur isOpen + Karten-ID), sonst + // würde jede Eingabe wieder auf den DB-Wert zurückspringen. useEffect(() => { + if (!isOpen) return; setFormData(getInitialFormData()); + setIbanLookupLoading(false); + setShowIbanRequired(false); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [bankCard?.id]); + }, [isOpen, bankCard?.id]); return ( <> @@ -2968,12 +2972,14 @@ function DocumentModal({ const isPending = createMutation.isPending || updateMutation.isPending; - // Re-Init nur beim Wechsel zum anderen Ausweis – nicht bei jedem - // Tastendruck (das löste vorher Reset auf DB-Wert aus). + // Reset beim Öffnen (Guard `if (!isOpen)`): Modal bleibt gemountet, sonst + // blieben nach „Abbrechen" die vorher getippten Daten stehen. Deps nur + // isOpen + Ausweis-ID → kein Reset bei jedem Tastendruck. useEffect(() => { + if (!isOpen) return; setFormData(getInitialFormData()); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [document?.id]); + }, [isOpen, document?.id]); return ( @@ -3180,12 +3186,14 @@ function MeterModal({ const isPending = createMutation.isPending || updateMutation.isPending; - // Re-Init nur beim Wechsel zum anderen Zähler – nicht bei jedem - // Tastendruck (das löste vorher Reset auf DB-Wert aus). + // Reset beim Öffnen (Guard `if (!isOpen)`): Modal bleibt gemountet, sonst + // blieben nach „Abbrechen" die vorher getippten Daten stehen. Deps nur + // isOpen + Zähler-ID → kein Reset bei jedem Tastendruck. useEffect(() => { + if (!isOpen) return; setFormData(getInitialFormData()); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [meter?.id]); + }, [isOpen, meter?.id]); const noDeliveryAddresses = deliveryAddresses.length === 0; const successorLocked = !isEditing && formData.isSuccessor && !!predecessor; @@ -3419,12 +3427,14 @@ function MeterReadingModal({ const isPending = createMutation.isPending || updateMutation.isPending; - // Re-Init nur beim Wechsel zum anderen Zählerstand – nicht bei - // jedem Tastendruck (das löste vorher Reset auf DB-Wert aus). + // Reset beim Öffnen (Guard `if (!isOpen)`): Modal bleibt gemountet, sonst + // blieben nach „Abbrechen" die vorher getippten Daten stehen. Deps nur + // isOpen + Zählerstand-ID → kein Reset bei jedem Tastendruck. useEffect(() => { + if (!isOpen) return; setFormData(getInitialFormData()); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [reading?.id]); + }, [isOpen, reading?.id]); return (