Erweiterungen
This commit is contained in:
@@ -111,4 +111,8 @@ public class Job {
|
||||
|
||||
@Field("app_user")
|
||||
private String appUser;
|
||||
|
||||
// Preis (netto)
|
||||
@Field("price")
|
||||
private String price;
|
||||
}
|
||||
|
||||
@@ -86,6 +86,20 @@ public class AddJobView extends Main {
|
||||
private Checkbox digitalProcessing;
|
||||
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
|
||||
private Button submitButton;
|
||||
|
||||
@@ -182,6 +196,17 @@ public class AddJobView extends Main {
|
||||
appUser.setItems("App-Nutzer");
|
||||
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
|
||||
submitButton = new Button("Auftrag anlegen", event -> submit());
|
||||
submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
@@ -196,20 +221,20 @@ public class AddJobView extends Main {
|
||||
add(new ViewToolbar("Neuen Auftrag anlegen"));
|
||||
|
||||
// Create TabSheet for organizing the form
|
||||
TabSheet tabSheet = new TabSheet();
|
||||
tabSheet = new TabSheet();
|
||||
tabSheet.setSizeFull();
|
||||
|
||||
// Tab 1: Customer & Addresses
|
||||
tabSheet.add("Auftraggeber & Adressen", createCustomerAndAddressesTab());
|
||||
addressesTab = tabSheet.add("Auftraggeber & Adressen", createCustomerAndAddressesTab());
|
||||
|
||||
// Tab 2: Appointments & Processing
|
||||
tabSheet.add("Termine & Verarbeitung", createAppointmentsAndProcessingTab());
|
||||
appointmentsTab = tabSheet.add("Termine & Verarbeitung", createAppointmentsAndProcessingTab());
|
||||
|
||||
// Tab 3: Cargo & Tasks
|
||||
tabSheet.add("Ladung & Aufgaben", createCargoAndTasksTab());
|
||||
cargoTab = tabSheet.add("Ladung & Aufgaben", createCargoAndTasksTab());
|
||||
|
||||
// Tab 4: Price & Submit
|
||||
tabSheet.add("Preis & Abschluss", createPriceAndSubmitTab());
|
||||
priceTab = tabSheet.add("Preis & Abschluss", createPriceAndSubmitTab());
|
||||
|
||||
add(tabSheet);
|
||||
|
||||
@@ -294,8 +319,6 @@ public class AddJobView extends Main {
|
||||
// Appointment (Pickup)
|
||||
H3 pickupApptTitle = new H3("Termin (Abholung)");
|
||||
pickupApptTitle.getStyle().set("margin", "0");
|
||||
DatePicker pickupDate = new DatePicker("Datum");
|
||||
pickupDate.setRequiredIndicatorVisible(true);
|
||||
TimePicker pickupTime = new TimePicker("Uhrzeit");
|
||||
HorizontalLayout pickupApptRow = new HorizontalLayout(pickupDate, pickupTime);
|
||||
pickupApptRow.setWidthFull();
|
||||
@@ -307,8 +330,6 @@ public class AddJobView extends Main {
|
||||
// Appointment (Delivery)
|
||||
H3 deliveryApptTitle = new H3("Termin (Lieferung)");
|
||||
deliveryApptTitle.getStyle().set("margin", "0");
|
||||
DatePicker deliveryDate = new DatePicker("Datum");
|
||||
deliveryDate.setRequiredIndicatorVisible(true);
|
||||
TimePicker deliveryTime = new TimePicker("Uhrzeit");
|
||||
HorizontalLayout deliveryApptRow = new HorizontalLayout(deliveryDate, deliveryTime);
|
||||
deliveryApptRow.setWidthFull();
|
||||
@@ -353,8 +374,6 @@ public class AddJobView extends Main {
|
||||
// Preis (netto) - moved from createTasksAndNotesSection
|
||||
H3 priceTitle = new H3("Preis (netto)");
|
||||
priceTitle.getStyle().set("margin", "0");
|
||||
TextField price = new TextField("Preis");
|
||||
price.setRequiredIndicatorVisible(true);
|
||||
content.add(priceTitle, price);
|
||||
|
||||
tabContent.add(content);
|
||||
@@ -527,6 +546,16 @@ public class AddJobView extends Main {
|
||||
.asRequired("")
|
||||
.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
|
||||
binder.bind(customerSelection, Job::getCustomerSelection, Job::setCustomerSelection);
|
||||
binder.bind(pickupCompany, Job::getPickupCompany, Job::setPickupCompany);
|
||||
@@ -549,20 +578,30 @@ public class AddJobView extends Main {
|
||||
|
||||
// Trigger initial validation when view is displayed
|
||||
triggerValidation();
|
||||
|
||||
// Update tab labels with initial validation state
|
||||
updateTabLabels();
|
||||
}
|
||||
|
||||
private void setupValidationTriggers() {
|
||||
// List of all required fields
|
||||
TextField[] requiredFields = {
|
||||
TextField[] requiredTextFields = {
|
||||
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
|
||||
for (TextField field : requiredFields) {
|
||||
// List of required date fields
|
||||
DatePicker[] requiredDateFields = {
|
||||
pickupDate, deliveryDate
|
||||
};
|
||||
|
||||
// Add value change listeners to trigger validation on every change for text fields
|
||||
for (TextField field : requiredTextFields) {
|
||||
field.addValueChangeListener(event -> {
|
||||
triggerValidation();
|
||||
updateFieldStyling(field);
|
||||
updateTabLabels();
|
||||
});
|
||||
|
||||
// Add focus listeners for immediate visual feedback
|
||||
@@ -572,6 +611,22 @@ public class AddJobView extends Main {
|
||||
// Set initial styling
|
||||
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() {
|
||||
@@ -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() {
|
||||
try {
|
||||
Job job = new Job();
|
||||
@@ -979,6 +1091,9 @@ public class AddJobView extends Main {
|
||||
digitalProcessing.setValue(false);
|
||||
appUser.clear();
|
||||
|
||||
// Price field
|
||||
price.clear();
|
||||
|
||||
// Benutzer-Feedback
|
||||
Notification.show("Alle Felder wurden geleert", 2000, Notification.Position.BOTTOM_CENTER);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user