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 e94bc0f..6e75e1d 100644 --- a/src/main/java/de/assecutor/votianlt/pages/view/AddJobView.java +++ b/src/main/java/de/assecutor/votianlt/pages/view/AddJobView.java @@ -125,6 +125,11 @@ public class AddJobView extends Main { private Span vatTotalLabel; private Span grossTotalLabel; + // Route distance display + private VerticalLayout routeInfoBox; + private Span routeDistanceLabel; + private Span routeDurationLabel; + // Date picker fields for appointments private DatePicker pickupDate; private DatePicker deliveryDate; @@ -603,6 +608,49 @@ public class AddJobView extends Main { content.setWidthFull(); content.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.STRETCH); + // Route Info Box (ganz oben) + routeInfoBox = new VerticalLayout(); + routeInfoBox.setPadding(true); + routeInfoBox.setSpacing(true); + routeInfoBox.getStyle().set("border", "1px solid var(--lumo-primary-color-50pct)"); + routeInfoBox.getStyle().set("border-radius", "var(--lumo-border-radius-m)"); + routeInfoBox.getStyle().set("background-color", "var(--lumo-primary-color-10pct)"); + routeInfoBox.setWidthFull(); + routeInfoBox.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.STRETCH); + routeInfoBox.setVisible(false); // Initial versteckt + + H3 routeTitle = new H3("Streckeninformation"); + routeTitle.getStyle().set("margin", "0"); + routeTitle.getStyle().set("color", "var(--lumo-primary-text-color)"); + + HorizontalLayout routeRow = new HorizontalLayout(); + routeRow.setWidthFull(); + routeRow.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN); + routeRow.setAlignItems(FlexComponent.Alignment.CENTER); + + Span distanceLabel = new Span("Entfernung:"); + routeDistanceLabel = new Span("-"); + routeDistanceLabel.getStyle().set("font-weight", "bold"); + routeDistanceLabel.getStyle().set("font-size", "var(--lumo-font-size-l)"); + routeDistanceLabel.getStyle().set("color", "var(--lumo-primary-text-color)"); + + routeRow.add(distanceLabel, routeDistanceLabel); + + HorizontalLayout durationRow = new HorizontalLayout(); + durationRow.setWidthFull(); + durationRow.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN); + durationRow.setAlignItems(FlexComponent.Alignment.CENTER); + + Span durationLabel = new Span("Fahrtzeit:"); + routeDurationLabel = new Span("-"); + routeDurationLabel.getStyle().set("font-weight", "bold"); + routeDurationLabel.getStyle().set("color", "var(--lumo-secondary-text-color)"); + + durationRow.add(durationLabel, routeDurationLabel); + + routeInfoBox.add(routeTitle, routeRow, durationRow); + content.add(routeInfoBox); + // Title H3 servicesTitle = new H3("Leistungen"); servicesTitle.getStyle().set("margin", "0"); @@ -2739,7 +2787,8 @@ public class AddJobView extends Main { } /** - * Zeigt den Adressvalidierungsdialog an. + * Zeigt den Adressvalidierungsdialog an. Die Prüfung erfolgt im Hintergrund und + * der Dialog wird aktualisiert, sobald die Ergebnisse vorliegen. */ private void showAddressValidationDialog(com.vaadin.flow.component.tabs.Tab targetTab) { final Dialog dialog = new Dialog(); @@ -2753,13 +2802,19 @@ public class AddJobView extends Main { content.setPadding(true); content.setSpacing(true); - // Status-Labels für die Validierung - final Span pickupStatusLabel = new Span("Abholadresse wird überprüft..."); - final Span deliveryStatusLabel = new Span("Lieferadresse wird überprüft..."); + // Initiale Meldung mit Progress + final Span loadingMessage = new Span("Adressen werden bei Google Maps überprüft..."); + loadingMessage.getStyle().set("font-style", "italic"); + loadingMessage.getStyle().set("color", "var(--lumo-secondary-text-color)"); - content.add(pickupStatusLabel, deliveryStatusLabel); + // Progress-Indikator + final com.vaadin.flow.component.progressbar.ProgressBar progressBar = new com.vaadin.flow.component.progressbar.ProgressBar(); + progressBar.setIndeterminate(true); + progressBar.setWidthFull(); - // Layout für die Ergebnisanzeige + content.add(loadingMessage, progressBar); + + // Layout für die Ergebnisanzeige (initial versteckt) final VerticalLayout resultLayout = new VerticalLayout(); resultLayout.setVisible(false); resultLayout.setPadding(false); @@ -2804,64 +2859,79 @@ public class AddJobView extends Main { dialog.add(content); dialog.open(); - // Asynchrone Validierung durchführen + // Adressdaten speichern für die Validierung + final String pickupStreetValue = getValueOrEmpty(pickupStreet); + final String pickupHouseNumberValue = getValueOrEmpty(pickupHouseNumber); + final String pickupZipValue = getValueOrEmpty(pickupZip); + final String pickupCityValue = getValueOrEmpty(pickupCity); + final boolean pickupChanged = hasPickupAddressChanged(); + + final String deliveryStreetValue = getValueOrEmpty(deliveryStreet); + final String deliveryHouseNumberValue = getValueOrEmpty(deliveryHouseNumber); + final String deliveryZipValue = getValueOrEmpty(deliveryZip); + final String deliveryCityValue = getValueOrEmpty(deliveryCity); + final boolean deliveryChanged = hasDeliveryAddressChanged(); + + // Asynchrone Validierung im Hintergrund durchführen getUI().ifPresent(ui -> { - // UI-Zugriff für Validierung - ui.access(() -> { + // CompletableFuture für Hintergrund-Verarbeitung + java.util.concurrent.CompletableFuture.runAsync(() -> { // Abholadresse validieren final AddressValidationResult[] pickupResultHolder = new AddressValidationResult[1]; - if (hasPickupAddressChanged()) { - pickupResultHolder[0] = addressValidationService.validateAddress("pickup", - getValueOrEmpty(pickupStreet), getValueOrEmpty(pickupHouseNumber), - getValueOrEmpty(pickupZip), getValueOrEmpty(pickupCity)); - addressValidationResults.put("pickup", pickupResultHolder[0]); + if (pickupChanged) { + pickupResultHolder[0] = addressValidationService.validateAddress("pickup", pickupStreetValue, + pickupHouseNumberValue, pickupZipValue, pickupCityValue); } // Lieferadresse validieren final AddressValidationResult[] deliveryResultHolder = new AddressValidationResult[1]; - if (hasDeliveryAddressChanged()) { - deliveryResultHolder[0] = addressValidationService.validateAddress("delivery", - getValueOrEmpty(deliveryStreet), getValueOrEmpty(deliveryHouseNumber), - getValueOrEmpty(deliveryZip), getValueOrEmpty(deliveryCity)); - addressValidationResults.put("delivery", deliveryResultHolder[0]); + if (deliveryChanged) { + deliveryResultHolder[0] = addressValidationService.validateAddress("delivery", deliveryStreetValue, + deliveryHouseNumberValue, deliveryZipValue, deliveryCityValue); } - // Route berechnen, wenn beide Adressen gültig sind - final RouteCalculationResult[] routeResultHolder = new RouteCalculationResult[1]; - AddressValidationResult pickup = pickupResultHolder[0]; - AddressValidationResult delivery = deliveryResultHolder[0]; - - if ((pickup != null && pickup.isValid()) && (delivery != null && delivery.isValid())) { - routeResultHolder[0] = addressValidationService.calculateRoute(pickup, delivery); - routeCalculationResult = routeResultHolder[0]; - } else if (pickup == null) { - // Bereits validierte Abholadresse verwenden - AddressValidationResult existingPickup = addressValidationResults.get("pickup"); - if (existingPickup != null && existingPickup.isValid() && delivery != null && delivery.isValid()) { - routeResultHolder[0] = addressValidationService.calculateRoute(existingPickup, delivery); - routeCalculationResult = routeResultHolder[0]; + // UI aktualisieren mit den Ergebnissen + ui.access(() -> { + // Ergebnisse speichern + if (pickupResultHolder[0] != null) { + addressValidationResults.put("pickup", pickupResultHolder[0]); } - } else if (delivery == null) { - // Bereits validierte Lieferadresse verwenden - AddressValidationResult existingDelivery = addressValidationResults.get("delivery"); - if (existingDelivery != null && existingDelivery.isValid() && pickup != null && pickup.isValid()) { - routeResultHolder[0] = addressValidationService.calculateRoute(pickup, existingDelivery); - routeCalculationResult = routeResultHolder[0]; + if (deliveryResultHolder[0] != null) { + addressValidationResults.put("delivery", deliveryResultHolder[0]); } - } - // UI aktualisieren - updateValidationDialogUI(pickup, delivery, pickupStatusLabel, deliveryStatusLabel, pickupResultLabel, - deliveryResultLabel, routeResultLabel, resultLayout, buttonLayout, continueButton, targetTab); + // Ergebnisse ermitteln + AddressValidationResult pickupResult = pickupResultHolder[0] != null ? pickupResultHolder[0] + : addressValidationResults.get("pickup"); + AddressValidationResult deliveryResult = deliveryResultHolder[0] != null ? deliveryResultHolder[0] + : addressValidationResults.get("delivery"); + + // Lade-Anzeige ausblenden + loadingMessage.setVisible(false); + progressBar.setVisible(false); + + // Prüfen ob beide Adressen gültig sind + boolean bothValid = (pickupResult != null && pickupResult.isValid()) + && (deliveryResult != null && deliveryResult.isValid()); + + // Route berechnen wenn beide gültig + if (bothValid) { + routeCalculationResult = addressValidationService.calculateRoute(pickupResult, deliveryResult); + } + + // Ergebnisse anzeigen + updateValidationDialogResults(pickupResult, deliveryResult, pickupResultLabel, deliveryResultLabel, + routeResultLabel, resultLayout, buttonLayout, continueButton, targetTab); + }); }); }); } /** - * Aktualisiert die UI des Validierungsdialogs mit den Ergebnissen. + * Aktualisiert die Ergebnisanzeige im Validierungsdialog. */ - private void updateValidationDialogUI(AddressValidationResult pickupResult, AddressValidationResult deliveryResult, - Span pickupStatusLabel, Span deliveryStatusLabel, Span pickupResultLabel, Span deliveryResultLabel, + private void updateValidationDialogResults(AddressValidationResult pickupResult, + AddressValidationResult deliveryResult, Span pickupResultLabel, Span deliveryResultLabel, Span routeResultLabel, VerticalLayout resultLayout, HorizontalLayout buttonLayout, Button continueButton, com.vaadin.flow.component.tabs.Tab targetTab) { @@ -2898,23 +2968,6 @@ public class AddJobView extends Main { deliveryResultLabel.setVisible(false); } - // Prüfen, ob beide Adressen insgesamt gültig sind (auch aus vorherigen - // Validierungen) - AddressValidationResult existingPickup = addressValidationResults.get("pickup"); - AddressValidationResult existingDelivery = addressValidationResults.get("delivery"); - - if (pickupResult != null && !pickupResult.isValid()) { - bothAddressesValid = false; - } else if (pickupResult == null && (existingPickup == null || !existingPickup.isValid())) { - bothAddressesValid = false; - } - - if (deliveryResult != null && !deliveryResult.isValid()) { - bothAddressesValid = false; - } else if (deliveryResult == null && (existingDelivery == null || !existingDelivery.isValid())) { - bothAddressesValid = false; - } - // Route anzeigen, wenn beide Adressen gültig sind if (bothAddressesValid && routeCalculationResult != null && routeCalculationResult.isValid()) { routeResultLabel.setText("🚛 Route: " + String.format("%.1f km", routeCalculationResult.getDistanceKm()) @@ -2925,14 +2978,11 @@ public class AddJobView extends Main { routeResultLabel.setVisible(false); } - // Status-Labels ausblenden, Ergebnisse anzeigen - pickupStatusLabel.setVisible(false); - deliveryStatusLabel.setVisible(false); + // Ergebnisse anzeigen resultLayout.setVisible(true); // Farbliche Markierung der Adressfelder - updateAddressFieldStyles(pickupResult != null ? pickupResult : existingPickup, - deliveryResult != null ? deliveryResult : existingDelivery); + updateAddressFieldStyles(pickupResult, deliveryResult); // Buttons anzeigen buttonLayout.setVisible(true); @@ -2943,6 +2993,26 @@ public class AddJobView extends Main { } else { continueButton.setText("Trotzdem wechseln"); } + + // Route-Info im Preis-Tab aktualisieren + updateRouteInfoBox(); + } + + /** + * Aktualisiert die Route-Info-Box im Preis-Tab mit den aktuellen Routendaten. + */ + private void updateRouteInfoBox() { + if (routeInfoBox == null || routeCalculationResult == null) { + return; + } + + if (routeCalculationResult.isValid()) { + routeDistanceLabel.setText(String.format("%.1f km", routeCalculationResult.getDistanceKm())); + routeDurationLabel.setText(routeCalculationResult.getFormattedDurationLong()); + routeInfoBox.setVisible(true); + } else { + routeInfoBox.setVisible(false); + } } /**