From 09798efcf1404abdf72c29cef88008109e70c2da Mon Sep 17 00:00:00 2001 From: Sven Carstensen Date: Thu, 5 Mar 2026 10:14:11 +0100 Subject: [PATCH] =?UTF-8?q?Stationen=20=C3=BCbernehmen:=20Button=20erst=20?= =?UTF-8?q?bei=20vollst=C3=A4ndigen=20Stationsdaten=20aktiv,=20Reset=20bei?= =?UTF-8?q?=20=C3=84nderungen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Button initial deaktiviert, wird erst aktiviert wenn Abholstation und mindestens eine Lieferstation korrekt gefüllt sind - Bei Änderungen an Stationsdaten (Dialog-Speichern, Hinzufügen, Löschen) wird der Bereich unter dem Grid ausgeblendet und der Button wieder angezeigt Co-Authored-By: Claude Opus 4.6 --- .../votianlt/pages/view/AddJobView.java | 50 ++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/assecutor/votianlt/pages/view/AddJobView.java b/src/main/java/de/assecutor/votianlt/pages/view/AddJobView.java index ae33aed..6604f77 100644 --- a/src/main/java/de/assecutor/votianlt/pages/view/AddJobView.java +++ b/src/main/java/de/assecutor/votianlt/pages/view/AddJobView.java @@ -140,6 +140,10 @@ public class AddJobView extends Main implements HasDynamicTitle { private Button submitButton; private HorizontalLayout submitButtonLayout; + // Stationen übernehmen Button und Bereich darunter + private Button applyStationsButton; + private VerticalLayout priceAndDetailsSection; + // Backing list for cargo items to mirror UI rows private final List cargoItemsState = new ArrayList<>(); // Backing list for tasks per delivery station (stationIndex -> tasks) @@ -339,16 +343,17 @@ public class AddJobView extends Main implements HasDynamicTitle { tabContent.add(stationsGridContainer); // Wrapper für alle Elemente nach Stationen (initial versteckt) - VerticalLayout priceAndDetailsSection = new VerticalLayout(); + priceAndDetailsSection = new VerticalLayout(); priceAndDetailsSection.setWidthFull(); priceAndDetailsSection.setPadding(false); priceAndDetailsSection.setSpacing(true); priceAndDetailsSection.setVisible(false); // "Stationen übernehmen" Button - Button applyStationsButton = new Button(getTranslation("addjob.stations.apply")); + applyStationsButton = new Button(getTranslation("addjob.stations.apply")); applyStationsButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); applyStationsButton.setWidthFull(); + applyStationsButton.setEnabled(false); applyStationsButton.addClickListener(e -> { applyStationsButton.setVisible(false); priceAndDetailsSection.setVisible(true); @@ -642,6 +647,7 @@ public class AddJobView extends Main implements HasDynamicTitle { stationsGridContainer.add(addStationButton); } + resetStationsAppliedState(); triggerValidation(); updateTabLabels(); } @@ -697,6 +703,7 @@ public class AddJobView extends Main implements HasDynamicTitle { } resetRouteInformation(); + resetStationsAppliedState(); triggerValidation(); updateTabLabels(); }); @@ -755,6 +762,7 @@ public class AddJobView extends Main implements HasDynamicTitle { pickupTile.setAddressValidated(data.isAddressValidatedByGoogle()); resetRouteInformation(); + resetStationsAppliedState(); triggerValidation(); updateTabLabels(); }, availableAppUsers, addressValidationService); @@ -825,6 +833,7 @@ public class AddJobView extends Main implements HasDynamicTitle { tile.setAddressValidated(data.isAddressValidatedByGoogle()); resetRouteInformation(); + resetStationsAppliedState(); triggerValidation(); updateTabLabels(); }, templates, (templateName, tasks) -> { @@ -1210,6 +1219,9 @@ public class AddJobView extends Main implements HasDynamicTitle { || hasCargoValidationErrors() || hasPriceValidationErrors() || hasTasksValidationErrors(); submitButton.setEnabled(!hasErrors); } + + // Update "Stationen übernehmen" button state + updateApplyStationsButtonState(); } private void updateFieldStyling(TextField field) { @@ -1724,6 +1736,40 @@ public class AddJobView extends Main implements HasDynamicTitle { * Setzt alle Streckeninformationen zurück, wenn sich Adressdaten ändern. Dies * bewirkt, dass der Validierungsdialog beim Tab-Wechsel erneut angezeigt wird. */ + private void resetStationsAppliedState() { + if (applyStationsButton != null) { + applyStationsButton.setVisible(true); + } + if (priceAndDetailsSection != null) { + priceAndDetailsSection.setVisible(false); + } + if (submitButtonLayout != null) { + submitButtonLayout.setVisible(false); + } + updateApplyStationsButtonState(); + } + + /** + * Aktiviert den "Stationen übernehmen"-Button nur, wenn die Abholstation und + * mindestens eine Lieferstation korrekt mit Daten gefüllt sind. + */ + private void updateApplyStationsButtonState() { + if (applyStationsButton == null) { + return; + } + // Pickup-Adresse prüfen + boolean pickupValid = !isFieldEmpty(pickupFirstName) && !isFieldEmpty(pickupLastName) + && !isFieldEmpty(pickupStreet) && !isFieldEmpty(pickupHouseNumber) && !isFieldEmpty(pickupZip) + && !isFieldEmpty(pickupCity) && pickupDate.getValue() != null + && !pickupDate.getValue().isBefore(LocalDate.now()); + + // Mindestens eine Lieferstation muss korrekt gefüllt sein + boolean atLeastOneDeliveryValid = deliveryStationsState.stream() + .anyMatch(station -> !hasDeliveryStationValidationErrors(station)); + + applyStationsButton.setEnabled(pickupValid && atLeastOneDeliveryValid); + } + private void resetRouteInformation() { // Routenberechnung zurücksetzen routeCalculationResult = null;