From 60851450f67ed2f7e2cb4b65e21bd0122f8193bd Mon Sep 17 00:00:00 2001 From: duffyduck Date: Mon, 8 Jun 2026 20:54:40 +0200 Subject: [PATCH] =?UTF-8?q?Bugfixes:=20Z=C3=A4hler/Bankkarte/Ausweis/Z?= =?UTF-8?q?=C3=A4hlerstand-Modal=20editierbar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vier weitere Vorkommen desselben Anti-Patterns wie beim AddressModal-Fix vom 2026-06-03: setFormData(getInitialFormData()) unbedingt im Render-Body, getriggert durch formData.X !== prop.X. Jeder Tastendruck setzte den State zurück → kein Editieren möglich. Fix in MeterModal (meterNumber), BankCardModal (iban), IdentityDocumentModal (documentNumber), MeterReadingModal (value): nach useEffect mit [entity?.id]-Dependency umgezogen. --- docs/todo.md | 9 ++++++ .../src/pages/customers/CustomerDetail.tsx | 32 ++++++++++++------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/docs/todo.md b/docs/todo.md index c7e7729b..d4324030 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -97,6 +97,15 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung ## ✅ Erledigt +- [x] **🐞 Modal-Felder ließen sich nicht editieren (Zähler/Bankkarte/Ausweis/Zählerstand)** + - Vier identische Vorkommen desselben Anti-Patterns wie beim + AddressModal-Fix von 2026-06-03: `setFormData(getInitialFormData())` + im Render-Body, getriggert durch `formData.X !== prop.X`. Jeder + Tastendruck setzte den State zurück. + - Fix in allen vier Modals (MeterModal, BankCardModal, + IdentityDocumentModal, MeterReadingModal): nach `useEffect` mit + `[?.id]`-Dependency umgezogen. + - [x] **🐞 JpgToPdfModal: PDF blieb trotz vorherigem Fix bei 20+ MB** - Stage-Test: 2 Handy-JPGs → 23 MB PDF. Ursache: Smartphone-Fotos haben 4000-6000 px Kante (24 MP), das vergrößert die JPEG-Datei diff --git a/frontend/src/pages/customers/CustomerDetail.tsx b/frontend/src/pages/customers/CustomerDetail.tsx index fbc3532f..07a6c970 100644 --- a/frontend/src/pages/customers/CustomerDetail.tsx +++ b/frontend/src/pages/customers/CustomerDetail.tsx @@ -2679,10 +2679,12 @@ function BankCardModal({ const isPending = createMutation.isPending || updateMutation.isPending; - // Update form when bankCard prop changes - if (isEditing && formData.iban !== bankCard.iban) { + // Re-Init nur beim Wechsel zur anderen Karte – nicht bei jedem + // Tastendruck (das löste vorher Reset auf DB-Wert aus). + useEffect(() => { setFormData(getInitialFormData()); - } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [bankCard?.id]); return ( @@ -2829,10 +2831,12 @@ function DocumentModal({ const isPending = createMutation.isPending || updateMutation.isPending; - // Update form when document prop changes - if (isEditing && formData.documentNumber !== document.documentNumber) { + // Re-Init nur beim Wechsel zum anderen Ausweis – nicht bei jedem + // Tastendruck (das löste vorher Reset auf DB-Wert aus). + useEffect(() => { setFormData(getInitialFormData()); - } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [document?.id]); return ( @@ -3039,10 +3043,12 @@ function MeterModal({ const isPending = createMutation.isPending || updateMutation.isPending; - // Update form when meter prop changes - if (isEditing && formData.meterNumber !== meter.meterNumber) { + // Re-Init nur beim Wechsel zum anderen Zähler – nicht bei jedem + // Tastendruck (das löste vorher Reset auf DB-Wert aus). + useEffect(() => { setFormData(getInitialFormData()); - } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [meter?.id]); const noDeliveryAddresses = deliveryAddresses.length === 0; const successorLocked = !isEditing && formData.isSuccessor && !!predecessor; @@ -3276,10 +3282,12 @@ function MeterReadingModal({ const isPending = createMutation.isPending || updateMutation.isPending; - // Update form when reading prop changes - if (isEditing && formData.value !== reading.value.toString()) { + // Re-Init nur beim Wechsel zum anderen Zählerstand – nicht bei + // jedem Tastendruck (das löste vorher Reset auf DB-Wert aus). + useEffect(() => { setFormData(getInitialFormData()); - } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [reading?.id]); return (