Erweiterungen

This commit is contained in:
2026-02-17 16:01:50 +01:00
parent b114c115d7
commit 6181f53854

View File

@@ -125,6 +125,11 @@ public class AddJobView extends Main {
private Span vatTotalLabel; private Span vatTotalLabel;
private Span grossTotalLabel; private Span grossTotalLabel;
// Route distance display
private VerticalLayout routeInfoBox;
private Span routeDistanceLabel;
private Span routeDurationLabel;
// Date picker fields for appointments // Date picker fields for appointments
private DatePicker pickupDate; private DatePicker pickupDate;
private DatePicker deliveryDate; private DatePicker deliveryDate;
@@ -603,6 +608,49 @@ public class AddJobView extends Main {
content.setWidthFull(); content.setWidthFull();
content.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.STRETCH); 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 // Title
H3 servicesTitle = new H3("Leistungen"); H3 servicesTitle = new H3("Leistungen");
servicesTitle.getStyle().set("margin", "0"); 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) { private void showAddressValidationDialog(com.vaadin.flow.component.tabs.Tab targetTab) {
final Dialog dialog = new Dialog(); final Dialog dialog = new Dialog();
@@ -2753,13 +2802,19 @@ public class AddJobView extends Main {
content.setPadding(true); content.setPadding(true);
content.setSpacing(true); content.setSpacing(true);
// Status-Labels für die Validierung // Initiale Meldung mit Progress
final Span pickupStatusLabel = new Span("Abholadresse wird überprüft..."); final Span loadingMessage = new Span("Adressen werden bei Google Maps überprüft...");
final Span deliveryStatusLabel = new Span("Lieferadresse wird ü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(); final VerticalLayout resultLayout = new VerticalLayout();
resultLayout.setVisible(false); resultLayout.setVisible(false);
resultLayout.setPadding(false); resultLayout.setPadding(false);
@@ -2804,64 +2859,79 @@ public class AddJobView extends Main {
dialog.add(content); dialog.add(content);
dialog.open(); 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 -> { getUI().ifPresent(ui -> {
// UI-Zugriff für Validierung // CompletableFuture für Hintergrund-Verarbeitung
ui.access(() -> { java.util.concurrent.CompletableFuture.runAsync(() -> {
// Abholadresse validieren // Abholadresse validieren
final AddressValidationResult[] pickupResultHolder = new AddressValidationResult[1]; final AddressValidationResult[] pickupResultHolder = new AddressValidationResult[1];
if (hasPickupAddressChanged()) { if (pickupChanged) {
pickupResultHolder[0] = addressValidationService.validateAddress("pickup", pickupResultHolder[0] = addressValidationService.validateAddress("pickup", pickupStreetValue,
getValueOrEmpty(pickupStreet), getValueOrEmpty(pickupHouseNumber), pickupHouseNumberValue, pickupZipValue, pickupCityValue);
getValueOrEmpty(pickupZip), getValueOrEmpty(pickupCity));
addressValidationResults.put("pickup", pickupResultHolder[0]);
} }
// Lieferadresse validieren // Lieferadresse validieren
final AddressValidationResult[] deliveryResultHolder = new AddressValidationResult[1]; final AddressValidationResult[] deliveryResultHolder = new AddressValidationResult[1];
if (hasDeliveryAddressChanged()) { if (deliveryChanged) {
deliveryResultHolder[0] = addressValidationService.validateAddress("delivery", deliveryResultHolder[0] = addressValidationService.validateAddress("delivery", deliveryStreetValue,
getValueOrEmpty(deliveryStreet), getValueOrEmpty(deliveryHouseNumber), deliveryHouseNumberValue, deliveryZipValue, deliveryCityValue);
getValueOrEmpty(deliveryZip), getValueOrEmpty(deliveryCity));
addressValidationResults.put("delivery", deliveryResultHolder[0]);
} }
// Route berechnen, wenn beide Adressen gültig sind // UI aktualisieren mit den Ergebnissen
final RouteCalculationResult[] routeResultHolder = new RouteCalculationResult[1]; ui.access(() -> {
AddressValidationResult pickup = pickupResultHolder[0]; // Ergebnisse speichern
AddressValidationResult delivery = deliveryResultHolder[0]; if (pickupResultHolder[0] != null) {
addressValidationResults.put("pickup", pickupResultHolder[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];
} }
} else if (delivery == null) { if (deliveryResultHolder[0] != null) {
// Bereits validierte Lieferadresse verwenden addressValidationResults.put("delivery", deliveryResultHolder[0]);
AddressValidationResult existingDelivery = addressValidationResults.get("delivery");
if (existingDelivery != null && existingDelivery.isValid() && pickup != null && pickup.isValid()) {
routeResultHolder[0] = addressValidationService.calculateRoute(pickup, existingDelivery);
routeCalculationResult = routeResultHolder[0];
} }
}
// UI aktualisieren // Ergebnisse ermitteln
updateValidationDialogUI(pickup, delivery, pickupStatusLabel, deliveryStatusLabel, pickupResultLabel, AddressValidationResult pickupResult = pickupResultHolder[0] != null ? pickupResultHolder[0]
deliveryResultLabel, routeResultLabel, resultLayout, buttonLayout, continueButton, targetTab); : 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, private void updateValidationDialogResults(AddressValidationResult pickupResult,
Span pickupStatusLabel, Span deliveryStatusLabel, Span pickupResultLabel, Span deliveryResultLabel, AddressValidationResult deliveryResult, Span pickupResultLabel, Span deliveryResultLabel,
Span routeResultLabel, VerticalLayout resultLayout, HorizontalLayout buttonLayout, Button continueButton, Span routeResultLabel, VerticalLayout resultLayout, HorizontalLayout buttonLayout, Button continueButton,
com.vaadin.flow.component.tabs.Tab targetTab) { com.vaadin.flow.component.tabs.Tab targetTab) {
@@ -2898,23 +2968,6 @@ public class AddJobView extends Main {
deliveryResultLabel.setVisible(false); 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 // Route anzeigen, wenn beide Adressen gültig sind
if (bothAddressesValid && routeCalculationResult != null && routeCalculationResult.isValid()) { if (bothAddressesValid && routeCalculationResult != null && routeCalculationResult.isValid()) {
routeResultLabel.setText("🚛 Route: " + String.format("%.1f km", routeCalculationResult.getDistanceKm()) routeResultLabel.setText("🚛 Route: " + String.format("%.1f km", routeCalculationResult.getDistanceKm())
@@ -2925,14 +2978,11 @@ public class AddJobView extends Main {
routeResultLabel.setVisible(false); routeResultLabel.setVisible(false);
} }
// Status-Labels ausblenden, Ergebnisse anzeigen // Ergebnisse anzeigen
pickupStatusLabel.setVisible(false);
deliveryStatusLabel.setVisible(false);
resultLayout.setVisible(true); resultLayout.setVisible(true);
// Farbliche Markierung der Adressfelder // Farbliche Markierung der Adressfelder
updateAddressFieldStyles(pickupResult != null ? pickupResult : existingPickup, updateAddressFieldStyles(pickupResult, deliveryResult);
deliveryResult != null ? deliveryResult : existingDelivery);
// Buttons anzeigen // Buttons anzeigen
buttonLayout.setVisible(true); buttonLayout.setVisible(true);
@@ -2943,6 +2993,26 @@ public class AddJobView extends Main {
} else { } else {
continueButton.setText("Trotzdem wechseln"); 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);
}
} }
/** /**