Erweiterungen
This commit is contained in:
@@ -111,4 +111,8 @@ public class Job {
|
|||||||
|
|
||||||
@Field("app_user")
|
@Field("app_user")
|
||||||
private String appUser;
|
private String appUser;
|
||||||
|
|
||||||
|
// Preis (netto)
|
||||||
|
@Field("price")
|
||||||
|
private String price;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,20 @@ public class AddJobView extends Main {
|
|||||||
private Checkbox digitalProcessing;
|
private Checkbox digitalProcessing;
|
||||||
private ComboBox<String> appUser;
|
private ComboBox<String> appUser;
|
||||||
|
|
||||||
|
// Price field
|
||||||
|
private TextField price;
|
||||||
|
|
||||||
|
// Date picker fields for appointments
|
||||||
|
private DatePicker pickupDate;
|
||||||
|
private DatePicker deliveryDate;
|
||||||
|
|
||||||
|
// TabSheet and Tab references for dynamic label updates
|
||||||
|
private TabSheet tabSheet;
|
||||||
|
private com.vaadin.flow.component.tabs.Tab addressesTab;
|
||||||
|
private com.vaadin.flow.component.tabs.Tab appointmentsTab;
|
||||||
|
private com.vaadin.flow.component.tabs.Tab cargoTab;
|
||||||
|
private com.vaadin.flow.component.tabs.Tab priceTab;
|
||||||
|
|
||||||
// Submit button
|
// Submit button
|
||||||
private Button submitButton;
|
private Button submitButton;
|
||||||
|
|
||||||
@@ -182,6 +196,17 @@ public class AddJobView extends Main {
|
|||||||
appUser.setItems("App-Nutzer");
|
appUser.setItems("App-Nutzer");
|
||||||
appUser.setPlaceholder("App-Nutzer auswählen...");
|
appUser.setPlaceholder("App-Nutzer auswählen...");
|
||||||
|
|
||||||
|
// Price field
|
||||||
|
price = new TextField("Preis");
|
||||||
|
price.setPlaceholder("z.B. 150.00");
|
||||||
|
price.setRequiredIndicatorVisible(true);
|
||||||
|
|
||||||
|
// Date picker fields for appointments
|
||||||
|
pickupDate = new DatePicker("Datum");
|
||||||
|
pickupDate.setRequiredIndicatorVisible(true);
|
||||||
|
deliveryDate = new DatePicker("Datum");
|
||||||
|
deliveryDate.setRequiredIndicatorVisible(true);
|
||||||
|
|
||||||
// Submit button
|
// Submit button
|
||||||
submitButton = new Button("Auftrag anlegen", event -> submit());
|
submitButton = new Button("Auftrag anlegen", event -> submit());
|
||||||
submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
@@ -196,20 +221,20 @@ public class AddJobView extends Main {
|
|||||||
add(new ViewToolbar("Neuen Auftrag anlegen"));
|
add(new ViewToolbar("Neuen Auftrag anlegen"));
|
||||||
|
|
||||||
// Create TabSheet for organizing the form
|
// Create TabSheet for organizing the form
|
||||||
TabSheet tabSheet = new TabSheet();
|
tabSheet = new TabSheet();
|
||||||
tabSheet.setSizeFull();
|
tabSheet.setSizeFull();
|
||||||
|
|
||||||
// Tab 1: Customer & Addresses
|
// Tab 1: Customer & Addresses
|
||||||
tabSheet.add("Auftraggeber & Adressen", createCustomerAndAddressesTab());
|
addressesTab = tabSheet.add("Auftraggeber & Adressen", createCustomerAndAddressesTab());
|
||||||
|
|
||||||
// Tab 2: Appointments & Processing
|
// Tab 2: Appointments & Processing
|
||||||
tabSheet.add("Termine & Verarbeitung", createAppointmentsAndProcessingTab());
|
appointmentsTab = tabSheet.add("Termine & Verarbeitung", createAppointmentsAndProcessingTab());
|
||||||
|
|
||||||
// Tab 3: Cargo & Tasks
|
// Tab 3: Cargo & Tasks
|
||||||
tabSheet.add("Ladung & Aufgaben", createCargoAndTasksTab());
|
cargoTab = tabSheet.add("Ladung & Aufgaben", createCargoAndTasksTab());
|
||||||
|
|
||||||
// Tab 4: Price & Submit
|
// Tab 4: Price & Submit
|
||||||
tabSheet.add("Preis & Abschluss", createPriceAndSubmitTab());
|
priceTab = tabSheet.add("Preis & Abschluss", createPriceAndSubmitTab());
|
||||||
|
|
||||||
add(tabSheet);
|
add(tabSheet);
|
||||||
|
|
||||||
@@ -294,8 +319,6 @@ public class AddJobView extends Main {
|
|||||||
// Appointment (Pickup)
|
// Appointment (Pickup)
|
||||||
H3 pickupApptTitle = new H3("Termin (Abholung)");
|
H3 pickupApptTitle = new H3("Termin (Abholung)");
|
||||||
pickupApptTitle.getStyle().set("margin", "0");
|
pickupApptTitle.getStyle().set("margin", "0");
|
||||||
DatePicker pickupDate = new DatePicker("Datum");
|
|
||||||
pickupDate.setRequiredIndicatorVisible(true);
|
|
||||||
TimePicker pickupTime = new TimePicker("Uhrzeit");
|
TimePicker pickupTime = new TimePicker("Uhrzeit");
|
||||||
HorizontalLayout pickupApptRow = new HorizontalLayout(pickupDate, pickupTime);
|
HorizontalLayout pickupApptRow = new HorizontalLayout(pickupDate, pickupTime);
|
||||||
pickupApptRow.setWidthFull();
|
pickupApptRow.setWidthFull();
|
||||||
@@ -307,8 +330,6 @@ public class AddJobView extends Main {
|
|||||||
// Appointment (Delivery)
|
// Appointment (Delivery)
|
||||||
H3 deliveryApptTitle = new H3("Termin (Lieferung)");
|
H3 deliveryApptTitle = new H3("Termin (Lieferung)");
|
||||||
deliveryApptTitle.getStyle().set("margin", "0");
|
deliveryApptTitle.getStyle().set("margin", "0");
|
||||||
DatePicker deliveryDate = new DatePicker("Datum");
|
|
||||||
deliveryDate.setRequiredIndicatorVisible(true);
|
|
||||||
TimePicker deliveryTime = new TimePicker("Uhrzeit");
|
TimePicker deliveryTime = new TimePicker("Uhrzeit");
|
||||||
HorizontalLayout deliveryApptRow = new HorizontalLayout(deliveryDate, deliveryTime);
|
HorizontalLayout deliveryApptRow = new HorizontalLayout(deliveryDate, deliveryTime);
|
||||||
deliveryApptRow.setWidthFull();
|
deliveryApptRow.setWidthFull();
|
||||||
@@ -353,8 +374,6 @@ public class AddJobView extends Main {
|
|||||||
// Preis (netto) - moved from createTasksAndNotesSection
|
// Preis (netto) - moved from createTasksAndNotesSection
|
||||||
H3 priceTitle = new H3("Preis (netto)");
|
H3 priceTitle = new H3("Preis (netto)");
|
||||||
priceTitle.getStyle().set("margin", "0");
|
priceTitle.getStyle().set("margin", "0");
|
||||||
TextField price = new TextField("Preis");
|
|
||||||
price.setRequiredIndicatorVisible(true);
|
|
||||||
content.add(priceTitle, price);
|
content.add(priceTitle, price);
|
||||||
|
|
||||||
tabContent.add(content);
|
tabContent.add(content);
|
||||||
@@ -527,6 +546,16 @@ public class AddJobView extends Main {
|
|||||||
.asRequired("")
|
.asRequired("")
|
||||||
.bind(Job::getDeliveryCity, Job::setDeliveryCity);
|
.bind(Job::getDeliveryCity, Job::setDeliveryCity);
|
||||||
|
|
||||||
|
// Bind price field with validation
|
||||||
|
binder.forField(price)
|
||||||
|
.asRequired("")
|
||||||
|
.bind(Job::getPrice, Job::setPrice);
|
||||||
|
|
||||||
|
// Bind date picker fields with validation (we'll need to add these to Job model later)
|
||||||
|
// For now, we'll just set up the validation without binding to the model
|
||||||
|
binder.forField(pickupDate).asRequired("");
|
||||||
|
binder.forField(deliveryDate).asRequired("");
|
||||||
|
|
||||||
// Bind optional fields without validation
|
// Bind optional fields without validation
|
||||||
binder.bind(customerSelection, Job::getCustomerSelection, Job::setCustomerSelection);
|
binder.bind(customerSelection, Job::getCustomerSelection, Job::setCustomerSelection);
|
||||||
binder.bind(pickupCompany, Job::getPickupCompany, Job::setPickupCompany);
|
binder.bind(pickupCompany, Job::getPickupCompany, Job::setPickupCompany);
|
||||||
@@ -549,20 +578,30 @@ public class AddJobView extends Main {
|
|||||||
|
|
||||||
// Trigger initial validation when view is displayed
|
// Trigger initial validation when view is displayed
|
||||||
triggerValidation();
|
triggerValidation();
|
||||||
|
|
||||||
|
// Update tab labels with initial validation state
|
||||||
|
updateTabLabels();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupValidationTriggers() {
|
private void setupValidationTriggers() {
|
||||||
// List of all required fields
|
// List of all required fields
|
||||||
TextField[] requiredFields = {
|
TextField[] requiredTextFields = {
|
||||||
pickupFirstName, pickupLastName, pickupStreet, pickupHouseNumber, pickupZip, pickupCity,
|
pickupFirstName, pickupLastName, pickupStreet, pickupHouseNumber, pickupZip, pickupCity,
|
||||||
deliveryFirstName, deliveryLastName, deliveryStreet, deliveryHouseNumber, deliveryZip, deliveryCity
|
deliveryFirstName, deliveryLastName, deliveryStreet, deliveryHouseNumber, deliveryZip, deliveryCity,
|
||||||
|
price
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add value change listeners to trigger validation on every change
|
// List of required date fields
|
||||||
for (TextField field : requiredFields) {
|
DatePicker[] requiredDateFields = {
|
||||||
|
pickupDate, deliveryDate
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add value change listeners to trigger validation on every change for text fields
|
||||||
|
for (TextField field : requiredTextFields) {
|
||||||
field.addValueChangeListener(event -> {
|
field.addValueChangeListener(event -> {
|
||||||
triggerValidation();
|
triggerValidation();
|
||||||
updateFieldStyling(field);
|
updateFieldStyling(field);
|
||||||
|
updateTabLabels();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add focus listeners for immediate visual feedback
|
// Add focus listeners for immediate visual feedback
|
||||||
@@ -572,6 +611,22 @@ public class AddJobView extends Main {
|
|||||||
// Set initial styling
|
// Set initial styling
|
||||||
updateFieldStyling(field);
|
updateFieldStyling(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add value change listeners for date fields
|
||||||
|
for (DatePicker field : requiredDateFields) {
|
||||||
|
field.addValueChangeListener(event -> {
|
||||||
|
triggerValidation();
|
||||||
|
updateDateFieldStyling(field);
|
||||||
|
updateTabLabels();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add focus listeners for immediate visual feedback
|
||||||
|
field.addFocusListener(event -> updateDateFieldStyling(field));
|
||||||
|
field.addBlurListener(event -> updateDateFieldStyling(field));
|
||||||
|
|
||||||
|
// Set initial styling
|
||||||
|
updateDateFieldStyling(field);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void triggerValidation() {
|
private void triggerValidation() {
|
||||||
@@ -595,6 +650,63 @@ public class AddJobView extends Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateDateFieldStyling(DatePicker field) {
|
||||||
|
boolean isEmpty = field.getValue() == null;
|
||||||
|
|
||||||
|
if (isEmpty) {
|
||||||
|
// Apply transparent red background only to the input field, not the label
|
||||||
|
field.getStyle().set("--vaadin-input-field-background", "rgba(255, 0, 0, 0.1)");
|
||||||
|
field.getStyle().set("--vaadin-input-field-border-color", "rgba(255, 0, 0, 0.3)");
|
||||||
|
} else {
|
||||||
|
// Remove styling when field is filled
|
||||||
|
field.getStyle().remove("--vaadin-input-field-background");
|
||||||
|
field.getStyle().remove("--vaadin-input-field-border-color");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTabLabels() {
|
||||||
|
// Check validation state for each tab and update labels with exclamation marks
|
||||||
|
updateTabLabel(addressesTab, "Auftraggeber & Adressen", hasAddressValidationErrors());
|
||||||
|
updateTabLabel(appointmentsTab, "Termine & Verarbeitung", hasAppointmentValidationErrors());
|
||||||
|
updateTabLabel(cargoTab, "Ladung & Aufgaben", false); // No required fields in cargo tab
|
||||||
|
updateTabLabel(priceTab, "Preis & Abschluss", hasPriceValidationErrors());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTabLabel(com.vaadin.flow.component.tabs.Tab tab, String baseLabel, boolean hasErrors) {
|
||||||
|
if (hasErrors) {
|
||||||
|
tab.setLabel(baseLabel + " ⚠️");
|
||||||
|
} else {
|
||||||
|
tab.setLabel(baseLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasAddressValidationErrors() {
|
||||||
|
// Check pickup address fields
|
||||||
|
boolean pickupErrors = isFieldEmpty(pickupFirstName) || isFieldEmpty(pickupLastName) ||
|
||||||
|
isFieldEmpty(pickupStreet) || isFieldEmpty(pickupHouseNumber) ||
|
||||||
|
isFieldEmpty(pickupZip) || isFieldEmpty(pickupCity);
|
||||||
|
|
||||||
|
// Check delivery address fields
|
||||||
|
boolean deliveryErrors = isFieldEmpty(deliveryFirstName) || isFieldEmpty(deliveryLastName) ||
|
||||||
|
isFieldEmpty(deliveryStreet) || isFieldEmpty(deliveryHouseNumber) ||
|
||||||
|
isFieldEmpty(deliveryZip) || isFieldEmpty(deliveryCity);
|
||||||
|
|
||||||
|
return pickupErrors || deliveryErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasAppointmentValidationErrors() {
|
||||||
|
return pickupDate.getValue() == null || deliveryDate.getValue() == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasPriceValidationErrors() {
|
||||||
|
return isFieldEmpty(price);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isFieldEmpty(TextField field) {
|
||||||
|
String value = field.getValue();
|
||||||
|
return value == null || value.trim().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
private void submit() {
|
private void submit() {
|
||||||
try {
|
try {
|
||||||
Job job = new Job();
|
Job job = new Job();
|
||||||
@@ -979,6 +1091,9 @@ public class AddJobView extends Main {
|
|||||||
digitalProcessing.setValue(false);
|
digitalProcessing.setValue(false);
|
||||||
appUser.clear();
|
appUser.clear();
|
||||||
|
|
||||||
|
// Price field
|
||||||
|
price.clear();
|
||||||
|
|
||||||
// Benutzer-Feedback
|
// Benutzer-Feedback
|
||||||
Notification.show("Alle Felder wurden geleert", 2000, Notification.Position.BOTTOM_CENTER);
|
Notification.show("Alle Felder wurden geleert", 2000, Notification.Position.BOTTOM_CENTER);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user