This commit is contained in:
2025-09-25 17:06:42 +02:00
parent cafb72bb5e
commit 5992f07b9d
7 changed files with 404 additions and 71 deletions

View File

@@ -56,4 +56,8 @@ public class User {
private LocalDateTime createdAt; private LocalDateTime createdAt;
private LocalDateTime updatedAt; private LocalDateTime updatedAt;
private Set<String> roles; private Set<String> roles;
// Digitale Abwicklung und App-Nutzer Ortung
private boolean digitalProcessingEnabled = true; // Digitale Abwicklung per App
private boolean locationTrackingEnabled = true; // App-Nutzer orten
} }

View File

@@ -38,8 +38,10 @@ public class AddAppDeviceView extends VerticalLayout {
// Formularfelder erstellen // Formularfelder erstellen
nameField = new TextField("Gerätename"); nameField = new TextField("Gerätename");
nameField.setRequired(true); nameField.setRequired(true);
nameField.setRequiredIndicatorVisible(true);
nameField.setPlaceholder("z.B. iPhone 15, Samsung Galaxy S24"); nameField.setPlaceholder("z.B. iPhone 15, Samsung Galaxy S24");
nameField.setWidth("100%"); nameField.setWidth("100%");
nameField.addBlurListener(e -> validateNameField());
// Layout konfigurieren // Layout konfigurieren
setSizeFull(); setSizeFull();
@@ -103,10 +105,18 @@ public class AddAppDeviceView extends VerticalLayout {
} }
private void populateTestData() { private void populateTestData() {
nameField.setValue("iPhone 15 Pro"); // No default values - field starts empty
} }
private void createAppDevice() { private void createAppDevice() {
// Validate field first
validateNameField();
if (nameField.isInvalid()) {
Notification.show("Bitte füllen Sie das Pflichtfeld korrekt aus", 3000, Notification.Position.MIDDLE);
return;
}
if (binder.validate().isOk()) { if (binder.validate().isOk()) {
try { try {
AppDevice appDevice = new AppDevice(); AppDevice appDevice = new AppDevice();
@@ -135,4 +145,15 @@ public class AddAppDeviceView extends VerticalLayout {
private void navigateBack() { private void navigateBack() {
getUI().ifPresent(ui -> ui.navigate("app-devices")); getUI().ifPresent(ui -> ui.navigate("app-devices"));
} }
private void validateNameField() {
String value = nameField.getValue();
if (value == null || value.trim().isEmpty()) {
nameField.setInvalid(true);
nameField.setErrorMessage("Gerätename ist ein Pflichtfeld");
} else {
nameField.setInvalid(false);
nameField.setErrorMessage("");
}
}
} }

View File

@@ -89,9 +89,16 @@ public class AddAppUserView extends VerticalLayout {
// Configure fields // Configure fields
designationField.setPlaceholder("(HH H 000)"); designationField.setPlaceholder("(HH H 000)");
designationField.setWidthFull(); designationField.setWidthFull();
designationField.setRequiredIndicatorVisible(true);
designationField.addBlurListener(e -> validateField(designationField, "Kennung ist ein Pflichtfeld"));
firstnameField.setWidthFull(); firstnameField.setWidthFull();
firstnameField.setRequiredIndicatorVisible(true);
firstnameField.addBlurListener(e -> validateField(firstnameField, "Vorname ist ein Pflichtfeld"));
lastnameField.setWidthFull(); lastnameField.setWidthFull();
lastnameField.setRequiredIndicatorVisible(true);
lastnameField.addBlurListener(e -> validateField(lastnameField, "Nachname ist ein Pflichtfeld"));
// Create horizontal layout for firstname and lastname // Create horizontal layout for firstname and lastname
HorizontalLayout nameLayout = new HorizontalLayout(); HorizontalLayout nameLayout = new HorizontalLayout();
@@ -100,20 +107,41 @@ public class AddAppUserView extends VerticalLayout {
nameLayout.add(firstnameField, lastnameField); nameLayout.add(firstnameField, lastnameField);
phoneField.setWidthFull(); phoneField.setWidthFull();
phoneField.setRequiredIndicatorVisible(true);
phoneField.addBlurListener(e -> validateField(phoneField, "Telefonnummer ist ein Pflichtfeld"));
appCodeField.setWidthFull(); appCodeField.setWidthFull();
appCodeField.setRequiredIndicatorVisible(true);
appCodeField.addBlurListener(e -> validateField(appCodeField, "App-Code ist ein Pflichtfeld"));
emailField.setWidthFull(); emailField.setWidthFull();
emailField.setRequiredIndicatorVisible(true);
emailField.addBlurListener(e -> validateEmailField());
// Clear error message when user types a new email
emailField.addValueChangeListener(e -> {
emailField.setInvalid(false);
emailField.setErrorMessage("");
});
passwordField.setWidthFull(); passwordField.setWidthFull();
passwordField.setRequired(true); passwordField.setRequired(true);
passwordField.setRequiredIndicatorVisible(true);
passwordField.addBlurListener(e -> validatePasswordField());
confirmPasswordField.setWidthFull(); confirmPasswordField.setWidthFull();
confirmPasswordField.setRequired(true); confirmPasswordField.setRequired(true);
confirmPasswordField.setRequiredIndicatorVisible(true);
confirmPasswordField.addBlurListener(e -> validateConfirmPasswordField());
// Configure device dropdown // Configure device dropdown
// Geräteauswahl vorbereiten // Geräteauswahl vorbereiten
deviceComboBox.setWidthFull(); deviceComboBox.setWidthFull();
deviceComboBox.setItemLabelGenerator(device -> device.getName()); deviceComboBox.setItemLabelGenerator(device -> device.getName());
deviceComboBox.setRequired(true); deviceComboBox.setRequired(true);
deviceComboBox.setRequiredIndicatorVisible(true);
deviceComboBox.setPlaceholder("Bitte wählen..."); deviceComboBox.setPlaceholder("Bitte wählen...");
deviceComboBox.setItems(appDeviceService.findUnassignedDevices()); deviceComboBox.setItems(appDeviceService.findUnassignedDevices());
deviceComboBox.addBlurListener(e -> validateDeviceField());
// Add fields to form // Add fields to form
formLayout.add(designationField); formLayout.add(designationField);
@@ -170,6 +198,12 @@ public class AddAppUserView extends VerticalLayout {
} }
private void createAppUser() { private void createAppUser() {
// Validate all fields first
if (!validateAllFields()) {
Notification.show("Bitte füllen Sie alle Pflichtfelder korrekt aus", 3000, Notification.Position.MIDDLE);
return;
}
try { try {
// Create new AppUser object // Create new AppUser object
AppUser newAppUser = new AppUser(); AppUser newAppUser = new AppUser();
@@ -193,38 +227,106 @@ public class AddAppUserView extends VerticalLayout {
} catch (ValidationException e) { } catch (ValidationException e) {
Notification.show("Bitte überprüfen Sie die Eingaben", 3000, Notification.Position.MIDDLE); Notification.show("Bitte überprüfen Sie die Eingaben", 3000, Notification.Position.MIDDLE);
} catch (org.springframework.dao.DuplicateKeyException e) {
// Handle duplicate email error
if (e.getMessage().contains("email")) {
Notification.show("Diese E-Mail-Adresse ist bereits vergeben", 5000, Notification.Position.MIDDLE);
emailField.focus();
emailField.setInvalid(true);
emailField.setErrorMessage("E-Mail-Adresse bereits vorhanden");
} else {
Notification.show("Ein Fehler ist aufgetreten: Doppelter Wert gefunden", 5000, Notification.Position.MIDDLE);
}
} catch (Exception e) {
Notification.show("Fehler beim Anlegen des App-Nutzers: " + e.getMessage(), 5000, Notification.Position.MIDDLE);
} }
} }
private void populateTestData() { private void populateTestData() {
// Fill designation field // No default values - all fields start empty
designationField.setValue("HH H 001");
// Fill name fields
firstnameField.setValue("Max");
lastnameField.setValue("Mustermann");
// Fill phone field
phoneField.setValue("+49 123 456789");
// Fill app code field
appCodeField.setValue("APP001");
// Fill email field
emailField.setValue("max.mustermann@example.com");
// Fill password field
passwordField.setValue("testpassword123");
// Fill confirm password field
confirmPasswordField.setValue("testpassword123");
// Set device to iPhone
// deviceComboBox.setValue("iPhone"); // This line is removed as deviceComboBox
// is now a ComboBox<AppDevice>
} }
private void navigateBack() { private void navigateBack() {
getUI().ifPresent(ui -> ui.navigate("app-user")); getUI().ifPresent(ui -> ui.navigate("app-user"));
} }
private void validateField(TextField field, String errorMessage) {
String value = field.getValue();
if (value == null || value.trim().isEmpty()) {
field.setInvalid(true);
field.setErrorMessage(errorMessage);
} else {
field.setInvalid(false);
field.setErrorMessage("");
}
}
private void validateEmailField() {
String value = emailField.getValue();
if (value == null || value.trim().isEmpty()) {
emailField.setInvalid(true);
emailField.setErrorMessage("E-Mail-Adresse ist ein Pflichtfeld");
} else if (!value.contains("@") || !value.contains(".")) {
emailField.setInvalid(true);
emailField.setErrorMessage("Bitte geben Sie eine gültige E-Mail-Adresse ein");
} else {
emailField.setInvalid(false);
emailField.setErrorMessage("");
}
}
private void validatePasswordField() {
String value = passwordField.getValue();
if (value == null || value.trim().isEmpty()) {
passwordField.setInvalid(true);
passwordField.setErrorMessage("Passwort ist ein Pflichtfeld");
} else if (value.length() < 6) {
passwordField.setInvalid(true);
passwordField.setErrorMessage("Passwort muss mindestens 6 Zeichen lang sein");
} else {
passwordField.setInvalid(false);
passwordField.setErrorMessage("");
}
}
private void validateConfirmPasswordField() {
String password = passwordField.getValue();
String confirmPassword = confirmPasswordField.getValue();
if (confirmPassword == null || confirmPassword.trim().isEmpty()) {
confirmPasswordField.setInvalid(true);
confirmPasswordField.setErrorMessage("Bitte bestätigen Sie das Passwort");
} else if (!confirmPassword.equals(password)) {
confirmPasswordField.setInvalid(true);
confirmPasswordField.setErrorMessage("Passwörter stimmen nicht überein");
} else {
confirmPasswordField.setInvalid(false);
confirmPasswordField.setErrorMessage("");
}
}
private void validateDeviceField() {
if (deviceComboBox.getValue() == null) {
deviceComboBox.setInvalid(true);
deviceComboBox.setErrorMessage("Bitte wählen Sie ein Gerät aus");
} else {
deviceComboBox.setInvalid(false);
deviceComboBox.setErrorMessage("");
}
}
private boolean validateAllFields() {
validateField(designationField, "Kennung ist ein Pflichtfeld");
validateField(firstnameField, "Vorname ist ein Pflichtfeld");
validateField(lastnameField, "Nachname ist ein Pflichtfeld");
validateField(phoneField, "Telefonnummer ist ein Pflichtfeld");
validateField(appCodeField, "App-Code ist ein Pflichtfeld");
validateEmailField();
validatePasswordField();
validateConfirmPasswordField();
validateDeviceField();
return !designationField.isInvalid() && !firstnameField.isInvalid() && !lastnameField.isInvalid()
&& !phoneField.isInvalid() && !appCodeField.isInvalid() && !emailField.isInvalid()
&& !passwordField.isInvalid() && !confirmPasswordField.isInvalid() && !deviceComboBox.isInvalid();
}
} }

View File

@@ -51,6 +51,7 @@ public class AddCustomerView extends Main {
companyName = new TextField("Firma"); companyName = new TextField("Firma");
companyName.setRequiredIndicatorVisible(true); companyName.setRequiredIndicatorVisible(true);
companyName.setWidthFull(); companyName.setWidthFull();
companyName.addBlurListener(e -> validateField(companyName));
// Anrede (Dropdown) // Anrede (Dropdown)
title = new ComboBox<>("Anrede"); title = new ComboBox<>("Anrede");
@@ -62,16 +63,19 @@ public class AddCustomerView extends Main {
firstName = new TextField("Vorname"); firstName = new TextField("Vorname");
firstName.setRequiredIndicatorVisible(true); firstName.setRequiredIndicatorVisible(true);
firstName.setWidthFull(); firstName.setWidthFull();
firstName.addBlurListener(e -> validateField(firstName));
// Nachname (Pflichtfeld) // Nachname (Pflichtfeld)
lastName = new TextField("Nachname"); lastName = new TextField("Nachname");
lastName.setRequiredIndicatorVisible(true); lastName.setRequiredIndicatorVisible(true);
lastName.setWidthFull(); lastName.setWidthFull();
lastName.addBlurListener(e -> validateField(lastName));
// Telefonnummer (Pflichtfeld) // Telefonnummer (Pflichtfeld)
telephone = new TextField("Telefonnummer"); telephone = new TextField("Telefonnummer");
telephone.setRequiredIndicatorVisible(true); telephone.setRequiredIndicatorVisible(true);
telephone.setWidthFull(); telephone.setWidthFull();
telephone.addBlurListener(e -> validateField(telephone));
// Fax (optional) // Fax (optional)
fax = new TextField("Fax"); fax = new TextField("Fax");
@@ -81,14 +85,17 @@ public class AddCustomerView extends Main {
mail = new TextField("E-Mail-Adresse"); mail = new TextField("E-Mail-Adresse");
mail.setRequiredIndicatorVisible(true); mail.setRequiredIndicatorVisible(true);
mail.setWidthFull(); mail.setWidthFull();
mail.addBlurListener(e -> validateEmail());
// Straße (Pflichtfeld) // Straße (Pflichtfeld)
street = new TextField("Straße"); street = new TextField("Straße");
street.setRequiredIndicatorVisible(true); street.setRequiredIndicatorVisible(true);
street.addBlurListener(e -> validateField(street));
// Hausnummer (Pflichtfeld) // Hausnummer (Pflichtfeld)
houseNumber = new TextField("Hausnr."); houseNumber = new TextField("Hausnr.");
houseNumber.setRequiredIndicatorVisible(true); houseNumber.setRequiredIndicatorVisible(true);
houseNumber.addBlurListener(e -> validateField(houseNumber));
// Adresszusatz (optional) // Adresszusatz (optional)
addressAddition = new TextField("Adresszusatz"); addressAddition = new TextField("Adresszusatz");
@@ -97,10 +104,12 @@ public class AddCustomerView extends Main {
// PLZ (Pflichtfeld) // PLZ (Pflichtfeld)
zip = new TextField("Postleitzahl"); zip = new TextField("Postleitzahl");
zip.setRequiredIndicatorVisible(true); zip.setRequiredIndicatorVisible(true);
zip.addBlurListener(e -> validateField(zip));
// Ort (Pflichtfeld) // Ort (Pflichtfeld)
city = new TextField("Ort"); city = new TextField("Ort");
city.setRequiredIndicatorVisible(true); city.setRequiredIndicatorVisible(true);
city.addBlurListener(e -> validateField(city));
// Binder-Konfiguration // Binder-Konfiguration
configureBinder(); configureBinder();
@@ -185,21 +194,19 @@ public class AddCustomerView extends Main {
} }
private void setTestData() { private void setTestData() {
companyName.setValue("Mustermann Transport GmbH"); // No default values - all fields start empty
title.setValue("Herr");
firstName.setValue("Max");
lastName.setValue("Mustermann");
telephone.setValue("+49 40 123456789");
fax.setValue("+49 40 123456790");
mail.setValue("max.mustermann@mustermann-transport.de");
street.setValue("Musterstraße");
houseNumber.setValue("123");
addressAddition.setValue("2. OG");
zip.setValue("20095");
city.setValue("Hamburg");
} }
private void submit() { private void submit() {
// First validate all fields
boolean isValid = validateAllFields();
if (!isValid) {
com.vaadin.flow.component.notification.Notification.show("Bitte füllen Sie alle Pflichtfelder aus", 3000,
com.vaadin.flow.component.notification.Notification.Position.TOP_CENTER);
return;
}
try { try {
Customer customer = new Customer(); Customer customer = new Customer();
binder.writeBean(customer); binder.writeBean(customer);
@@ -220,4 +227,45 @@ public class AddCustomerView extends Main {
com.vaadin.flow.component.notification.Notification.Position.TOP_CENTER); com.vaadin.flow.component.notification.Notification.Position.TOP_CENTER);
} }
} }
private void validateField(TextField field) {
String value = field.getValue();
if (value == null || value.trim().isEmpty()) {
field.setInvalid(true);
field.setErrorMessage("Dieses Feld ist ein Pflichtfeld");
} else {
field.setInvalid(false);
field.setErrorMessage("");
}
}
private void validateEmail() {
String value = mail.getValue();
if (value == null || value.trim().isEmpty()) {
mail.setInvalid(true);
mail.setErrorMessage("E-Mail-Adresse ist ein Pflichtfeld");
} else if (!value.contains("@")) {
mail.setInvalid(true);
mail.setErrorMessage("Bitte geben Sie eine gültige E-Mail-Adresse ein");
} else {
mail.setInvalid(false);
mail.setErrorMessage("");
}
}
private boolean validateAllFields() {
validateField(companyName);
validateField(firstName);
validateField(lastName);
validateField(telephone);
validateField(street);
validateField(houseNumber);
validateField(zip);
validateField(city);
validateEmail();
return !companyName.isInvalid() && !firstName.isInvalid() && !lastName.isInvalid()
&& !telephone.isInvalid() && !mail.isInvalid() && !street.isInvalid()
&& !houseNumber.isInvalid() && !zip.isInvalid() && !city.isInvalid();
}
} }

View File

@@ -48,6 +48,7 @@ import de.assecutor.votianlt.pages.service.AppUserService;
import de.assecutor.votianlt.model.AppUser; import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.pages.service.TaskTemplateService; import de.assecutor.votianlt.pages.service.TaskTemplateService;
import de.assecutor.votianlt.model.TaskTemplate; import de.assecutor.votianlt.model.TaskTemplate;
import de.assecutor.votianlt.model.User;
import de.assecutor.votianlt.security.SecurityService; import de.assecutor.votianlt.security.SecurityService;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
@@ -331,9 +332,15 @@ public class AddJobView extends Main {
saveDeliveryAddress = new Checkbox("Die Adresse für zukünftige Aufträge speichern."); saveDeliveryAddress = new Checkbox("Die Adresse für zukünftige Aufträge speichern.");
saveDeliveryAddress.setValue(true); saveDeliveryAddress.setValue(true);
// Digital processing // Digital processing - set value based on user's profile setting
digitalProcessing = new Checkbox("Digitale Abwicklung per App"); digitalProcessing = new Checkbox("Digitale Abwicklung per App");
digitalProcessing.setValue(true); // Get current user's digital processing preference from profile
try {
User currentUser = securityService.getCurrentDatabaseUser();
digitalProcessing.setValue(currentUser.isDigitalProcessingEnabled());
} catch (Exception e) {
digitalProcessing.setValue(true); // Default to true if user not found
}
appUser = new ComboBox<>("App-Nutzer"); appUser = new ComboBox<>("App-Nutzer");
// Load app users for current user and set up the ComboBox // Load app users for current user and set up the ComboBox
@@ -1224,25 +1231,31 @@ public class AddJobView extends Main {
desc.setAllowCustomValue(true); desc.setAllowCustomValue(true);
desc.setPlaceholder("Wählen Sie eine Option oder geben Sie eigenen Text ein..."); desc.setPlaceholder("Wählen Sie eine Option oder geben Sie eigenen Text ein...");
desc.setWidth("40%"); desc.setWidth("40%");
desc.setRequiredIndicatorVisible(true);
IntegerField qty = new IntegerField("Anzahl"); IntegerField qty = new IntegerField("Anzahl");
qty.setMin(1); qty.setMin(1);
qty.setValue(1); qty.setValue(1);
qty.setWidth("10%"); qty.setWidth("10%");
qty.setRequiredIndicatorVisible(true);
NumberField weight = new NumberField("Gewicht"); NumberField weight = new NumberField("Gewicht");
weight.setSuffixComponent(new Span("kg")); weight.setSuffixComponent(new Span("kg"));
weight.setWidth("15%"); weight.setWidth("15%");
weight.setRequiredIndicatorVisible(true);
NumberField len = new NumberField("Länge"); NumberField len = new NumberField("Länge");
len.setSuffixComponent(new Span("mm")); len.setSuffixComponent(new Span("mm"));
len.setWidth("12%"); len.setWidth("12%");
len.setRequiredIndicatorVisible(true);
NumberField wid = new NumberField("Breite"); NumberField wid = new NumberField("Breite");
wid.setSuffixComponent(new Span("mm")); wid.setSuffixComponent(new Span("mm"));
wid.setWidth("12%"); wid.setWidth("12%");
wid.setRequiredIndicatorVisible(true);
NumberField hei = new NumberField("Höhe"); NumberField hei = new NumberField("Höhe");
hei.setSuffixComponent(new Span("mm")); hei.setSuffixComponent(new Span("mm"));
hei.setWidth("12%"); hei.setWidth("12%");
hei.setRequiredIndicatorVisible(true);
Button remove = new Button(new Icon(VaadinIcon.CLOSE_SMALL)); Button remove = new Button(new Icon(VaadinIcon.CLOSE_SMALL));
remove.addThemeVariants(ButtonVariant.LUMO_ERROR, ButtonVariant.LUMO_TERTIARY); remove.addThemeVariants(ButtonVariant.LUMO_ERROR, ButtonVariant.LUMO_TERTIARY);
@@ -1270,31 +1283,59 @@ public class AddJobView extends Main {
item.setWidthMm(wid.getValue()); item.setWidthMm(wid.getValue());
item.setHeightMm(hei.getValue()); item.setHeightMm(hei.getValue());
// Validation helper to update field styling
java.util.function.Consumer<com.vaadin.flow.component.HasValue<?, ?>> validateField = field -> {
if (field instanceof ComboBox) {
ComboBox<?> combo = (ComboBox<?>) field;
String value = combo.getValue() != null ? combo.getValue().toString() : "";
combo.setInvalid(value.trim().isEmpty());
} else if (field instanceof NumberField) {
NumberField numField = (NumberField) field;
numField.setInvalid(numField.getValue() == null || numField.getValue() <= 0);
} else if (field instanceof IntegerField) {
IntegerField intField = (IntegerField) field;
intField.setInvalid(intField.getValue() == null || intField.getValue() <= 0);
}
};
desc.addValueChangeListener(ev -> { desc.addValueChangeListener(ev -> {
item.setDescription(ev.getValue()); item.setDescription(ev.getValue());
validateField.accept(desc);
updateTabLabels(); // Update tab validation when cargo description changes updateTabLabels(); // Update tab validation when cargo description changes
}); });
qty.addValueChangeListener(ev -> { qty.addValueChangeListener(ev -> {
item.setQuantity(ev.getValue()); item.setQuantity(ev.getValue());
validateField.accept(qty);
updateTabLabels(); // Update tab validation when cargo quantity changes updateTabLabels(); // Update tab validation when cargo quantity changes
}); });
weight.addValueChangeListener(ev -> { weight.addValueChangeListener(ev -> {
item.setWeightKg(ev.getValue()); item.setWeightKg(ev.getValue());
validateField.accept(weight);
updateTabLabels(); // Update tab validation when cargo weight changes updateTabLabels(); // Update tab validation when cargo weight changes
}); });
len.addValueChangeListener(ev -> { len.addValueChangeListener(ev -> {
item.setLengthMm(ev.getValue()); item.setLengthMm(ev.getValue());
validateField.accept(len);
updateTabLabels(); // Update tab validation when cargo length changes updateTabLabels(); // Update tab validation when cargo length changes
}); });
wid.addValueChangeListener(ev -> { wid.addValueChangeListener(ev -> {
item.setWidthMm(ev.getValue()); item.setWidthMm(ev.getValue());
validateField.accept(wid);
updateTabLabels(); // Update tab validation when cargo width changes updateTabLabels(); // Update tab validation when cargo width changes
}); });
hei.addValueChangeListener(ev -> { hei.addValueChangeListener(ev -> {
item.setHeightMm(ev.getValue()); item.setHeightMm(ev.getValue());
validateField.accept(hei);
updateTabLabels(); // Update tab validation when cargo height changes updateTabLabels(); // Update tab validation when cargo height changes
}); });
// Initial validation
validateField.accept(desc);
validateField.accept(weight);
validateField.accept(len);
validateField.accept(wid);
validateField.accept(hei);
if (afterCreate != null) if (afterCreate != null)
afterCreate.accept(row); afterCreate.accept(row);
}; };

View File

@@ -2,7 +2,7 @@ package de.assecutor.votianlt.pages.view;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant; import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.confirmdialog.ConfirmDialog; import com.vaadin.flow.component.confirmdialog.ConfirmDialog;
import com.vaadin.flow.component.formlayout.FormLayout; import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.html.H2; import com.vaadin.flow.component.html.H2;
@@ -34,7 +34,7 @@ public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter
// Formularfelder // Formularfelder
private final TextField nameField; private final TextField nameField;
private final ComboBox<AppUser> appUserComboBox; private final Span appUserDisplay;
// Aktuelles Endgerät // Aktuelles Endgerät
private AppDevice currentAppDevice; private AppDevice currentAppDevice;
@@ -53,20 +53,15 @@ public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter
nameField.setPlaceholder("z.B. iPhone 15, Samsung Galaxy S24"); nameField.setPlaceholder("z.B. iPhone 15, Samsung Galaxy S24");
nameField.setWidth("100%"); nameField.setWidth("100%");
// AppUser ComboBox // App-Nutzer Anzeige (nur lesend)
appUserComboBox = new ComboBox<>("App-Nutzer zuordnen"); appUserDisplay = new Span();
appUserComboBox.setPlaceholder("App-Nutzer auswählen (optional)"); appUserDisplay.getStyle().set("font-weight", "bold")
appUserComboBox.setWidth("100%"); .set("padding", "var(--lumo-space-s)")
appUserComboBox.setItemLabelGenerator( .set("border", "1px solid var(--lumo-contrast-20pct)")
appUser -> appUser.getVorname() + " " + appUser.getNachname() + " (" + appUser.getEmail() + ")"); .set("border-radius", "var(--lumo-border-radius-m)")
.set("background-color", "var(--lumo-contrast-5pct)")
// Lade verfügbare App-Nutzer .set("display", "block")
try { .set("width", "100%");
appUserComboBox.setItems(appUserService.findByCurrentUser());
} catch (Exception e) {
Notification.show("Fehler beim Laden der App-Nutzer: " + e.getMessage(), 3000,
Notification.Position.MIDDLE);
}
// Layout konfigurieren // Layout konfigurieren
setSizeFull(); setSizeFull();
@@ -96,7 +91,15 @@ public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter
// Formular // Formular
FormLayout formLayout = new FormLayout(); FormLayout formLayout = new FormLayout();
formLayout.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 1)); formLayout.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 1));
formLayout.add(nameField, appUserComboBox); // Label für App-Nutzer
Span appUserLabel = new Span("Zugeordneter App-Nutzer:");
appUserLabel.getStyle().set("font-weight", "500")
.set("color", "var(--lumo-secondary-text-color)")
.set("font-size", "var(--lumo-font-size-s)");
formLayout.add(nameField);
formLayout.add(appUserLabel);
formLayout.add(appUserDisplay);
contentContainer.add(formLayout); contentContainer.add(formLayout);
// Buttons // Buttons
@@ -142,6 +145,9 @@ public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter
if (currentAppDevice != null) { if (currentAppDevice != null) {
// Formular mit aktuellen Daten füllen // Formular mit aktuellen Daten füllen
binder.readBean(currentAppDevice); binder.readBean(currentAppDevice);
// App-Nutzer Anzeige aktualisieren
updateAppUserDisplay();
} else { } else {
Notification.show("Endgerät nicht gefunden", 3000, Notification.Position.MIDDLE); Notification.show("Endgerät nicht gefunden", 3000, Notification.Position.MIDDLE);
navigateBack(); navigateBack();
@@ -151,20 +157,35 @@ public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter
private void setupBinder() { private void setupBinder() {
binder.forField(nameField).asRequired("Gerätename ist erforderlich").bind(AppDevice::getName, binder.forField(nameField).asRequired("Gerätename ist erforderlich").bind(AppDevice::getName,
AppDevice::setName); AppDevice::setName);
}
binder.forField(appUserComboBox).bind(appDevice -> { private void updateAppUserDisplay() {
if (appDevice.getAppUserId() != null) { if (currentAppDevice != null && currentAppDevice.getAppUserId() != null) {
return appUserService.findByCurrentUser().stream() try {
.filter(user -> user.getId().equals(appDevice.getAppUserId())).findFirst().orElse(null); // Finde den zugeordneten App-Nutzer
AppUser assignedUser = appUserService.findByCurrentUser().stream()
.filter(user -> user.getId().equals(currentAppDevice.getAppUserId()))
.findFirst()
.orElse(null);
if (assignedUser != null) {
String displayText = assignedUser.getVorname() + " " + assignedUser.getNachname() +
" (" + assignedUser.getEmail() + ")";
appUserDisplay.setText(displayText);
appUserDisplay.getStyle().set("color", "var(--lumo-body-text-color)");
} else {
appUserDisplay.setText("App-Nutzer nicht gefunden (ID: " + currentAppDevice.getAppUserId() + ")");
appUserDisplay.getStyle().set("color", "var(--lumo-error-text-color)");
}
} catch (Exception e) {
appUserDisplay.setText("Fehler beim Laden des App-Nutzers");
appUserDisplay.getStyle().set("color", "var(--lumo-error-text-color)");
} }
return null; } else {
}, (appDevice, appUser) -> { appUserDisplay.setText("Kein App-Nutzer zugeordnet");
if (appUser != null) { appUserDisplay.getStyle().set("color", "var(--lumo-secondary-text-color)");
appDevice.setAppUserId(appUser.getId()); appUserDisplay.getStyle().set("font-style", "italic");
} else { }
appDevice.setAppUserId(null);
}
});
} }
private void saveAppDevice() { private void saveAppDevice() {

View File

@@ -94,18 +94,38 @@ public class EditProfileView extends HorizontalLayout {
// Firmenfelder // Firmenfelder
TextField companyField = new TextField("Firma"); TextField companyField = new TextField("Firma");
companyField.addBlurListener(e -> validateField(companyField, "Firma ist ein Pflichtfeld"));
TextField companyAddField = new TextField("Firmenzusatz"); TextField companyAddField = new TextField("Firmenzusatz");
TextField firstnameField = new TextField("Vorname"); TextField firstnameField = new TextField("Vorname");
firstnameField.addBlurListener(e -> validateField(firstnameField, "Vorname ist ein Pflichtfeld"));
TextField lastnameField = new TextField("Nachname"); TextField lastnameField = new TextField("Nachname");
lastnameField.addBlurListener(e -> validateField(lastnameField, "Nachname ist ein Pflichtfeld"));
TextField phoneField = new TextField("Telefonnummer"); TextField phoneField = new TextField("Telefonnummer");
phoneField.addBlurListener(e -> validateField(phoneField, "Telefonnummer ist ein Pflichtfeld"));
TextField faxField = new TextField("Telefon (Fax)"); TextField faxField = new TextField("Telefon (Fax)");
TextField mobileField = new TextField("Telefon (Mobil)"); TextField mobileField = new TextField("Telefon (Mobil)");
EmailField emailField = new EmailField("E-Mail-Adresse (Login)*"); EmailField emailField = new EmailField("E-Mail-Adresse (Login)*");
emailField.addBlurListener(e -> validateEmailField(emailField));
TextField streetField = new TextField("Straße"); TextField streetField = new TextField("Straße");
streetField.addBlurListener(e -> validateField(streetField, "Straße ist ein Pflichtfeld"));
TextField houseNumberField = new TextField("Hausnr"); TextField houseNumberField = new TextField("Hausnr");
houseNumberField.addBlurListener(e -> validateField(houseNumberField, "Hausnummer ist ein Pflichtfeld"));
TextField addressAddField = new TextField("Adresszusatz"); TextField addressAddField = new TextField("Adresszusatz");
TextField zipField = new TextField("Postleitzahl"); TextField zipField = new TextField("Postleitzahl");
zipField.addBlurListener(e -> validateField(zipField, "Postleitzahl ist ein Pflichtfeld"));
TextField cityField = new TextField("Stadt"); TextField cityField = new TextField("Stadt");
cityField.addBlurListener(e -> validateField(cityField, "Stadt ist ein Pflichtfeld"));
// Abweichende Rechnungsadresse // Abweichende Rechnungsadresse
Checkbox diffInvoiceAddress = new Checkbox("Abweichende Rechnungsadresse"); Checkbox diffInvoiceAddress = new Checkbox("Abweichende Rechnungsadresse");
@@ -337,9 +357,33 @@ public class EditProfileView extends HorizontalLayout {
VerticalLayout switches = new VerticalLayout(); VerticalLayout switches = new VerticalLayout();
switches.setPadding(false); switches.setPadding(false);
switches.setSpacing(true); switches.setSpacing(true);
Checkbox digitalProcess = new Checkbox("Digitale Abwicklung per App");
digitalProcess.setValue(currentUser.isDigitalProcessingEnabled());
Span digitalProcessInfo = new Span("Aktiviert die digitale Auftragsabwicklung über die mobile App");
digitalProcessInfo.getStyle().set("font-size", "var(--lumo-font-size-s)")
.set("color", "var(--lumo-secondary-text-color)")
.set("margin-left", "var(--lumo-space-xl)");
Checkbox locateAppUser = new Checkbox("App-Nutzer orten"); Checkbox locateAppUser = new Checkbox("App-Nutzer orten");
Checkbox digitalProcess = new Checkbox("Digitale Abwicklung"); locateAppUser.setValue(currentUser.isLocationTrackingEnabled());
switches.add(locateAppUser, digitalProcess);
Span locateAppUserInfo = new Span("Ermöglicht die Ortung von App-Nutzern während der Auftragsausführung");
locateAppUserInfo.getStyle().set("font-size", "var(--lumo-font-size-s)")
.set("color", "var(--lumo-secondary-text-color)")
.set("margin-left", "var(--lumo-space-xl)");
// Save checkbox states when changed
digitalProcess.addValueChangeListener(e -> {
currentUser.setDigitalProcessingEnabled(e.getValue());
});
locateAppUser.addValueChangeListener(e -> {
currentUser.setLocationTrackingEnabled(e.getValue());
});
switches.add(digitalProcess, digitalProcessInfo, locateAppUser, locateAppUserInfo);
tabSheet.add("Einstellungen", switches); tabSheet.add("Einstellungen", switches);
// Sicherheit-Tab (2FA, Passwort, Konto) // Sicherheit-Tab (2FA, Passwort, Konto)
@@ -371,6 +415,15 @@ public class EditProfileView extends HorizontalLayout {
Button saveProfile = new Button("Profiländerungen speichern"); Button saveProfile = new Button("Profiländerungen speichern");
saveProfile.addThemeVariants(ButtonVariant.LUMO_PRIMARY); saveProfile.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
saveProfile.addClickListener(e -> { saveProfile.addClickListener(e -> {
// Validate all required fields first
boolean isValid = validateAllProfileFields(companyField, firstnameField, lastnameField, phoneField,
emailField, streetField, houseNumberField, zipField, cityField);
if (!isValid) {
Notification.show("Bitte füllen Sie alle Pflichtfelder korrekt aus", 3000, Notification.Position.MIDDLE);
return;
}
if (binder.validate().isOk()) { if (binder.validate().isOk()) {
try { try {
// Check if billing status changed // Check if billing status changed
@@ -620,4 +673,47 @@ public class EditProfileView extends HorizontalLayout {
return value != null ? value : ""; return value != null ? value : "";
} }
private void validateField(TextField field, String errorMessage) {
String value = field.getValue();
if (value == null || value.trim().isEmpty()) {
field.setInvalid(true);
field.setErrorMessage(errorMessage);
} else {
field.setInvalid(false);
field.setErrorMessage("");
}
}
private void validateEmailField(EmailField emailField) {
String value = emailField.getValue();
if (value == null || value.trim().isEmpty()) {
emailField.setInvalid(true);
emailField.setErrorMessage("E-Mail-Adresse ist ein Pflichtfeld");
} else if (!value.contains("@") || !value.contains(".")) {
emailField.setInvalid(true);
emailField.setErrorMessage("Bitte geben Sie eine gültige E-Mail-Adresse ein");
} else {
emailField.setInvalid(false);
emailField.setErrorMessage("");
}
}
private boolean validateAllProfileFields(TextField companyField, TextField firstnameField, TextField lastnameField,
TextField phoneField, EmailField emailField, TextField streetField,
TextField houseNumberField, TextField zipField, TextField cityField) {
validateField(companyField, "Firma ist ein Pflichtfeld");
validateField(firstnameField, "Vorname ist ein Pflichtfeld");
validateField(lastnameField, "Nachname ist ein Pflichtfeld");
validateField(phoneField, "Telefonnummer ist ein Pflichtfeld");
validateEmailField(emailField);
validateField(streetField, "Straße ist ein Pflichtfeld");
validateField(houseNumberField, "Hausnummer ist ein Pflichtfeld");
validateField(zipField, "Postleitzahl ist ein Pflichtfeld");
validateField(cityField, "Stadt ist ein Pflichtfeld");
return !companyField.isInvalid() && !firstnameField.isInvalid() && !lastnameField.isInvalid()
&& !phoneField.isInvalid() && !emailField.isInvalid() && !streetField.isInvalid()
&& !houseNumberField.isInvalid() && !zipField.isInvalid() && !cityField.isInvalid();
}
} }