Erweiterungen
This commit is contained in:
@@ -10,6 +10,7 @@ import org.springframework.data.mongodb.core.mapping.Field;
|
|||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@@ -115,9 +116,15 @@ public class Job {
|
|||||||
@Field("pickup_date")
|
@Field("pickup_date")
|
||||||
private LocalDate pickupDate;
|
private LocalDate pickupDate;
|
||||||
|
|
||||||
|
@Field("pickup_time")
|
||||||
|
private LocalTime pickupTime;
|
||||||
|
|
||||||
@Field("delivery_date")
|
@Field("delivery_date")
|
||||||
private LocalDate deliveryDate;
|
private LocalDate deliveryDate;
|
||||||
|
|
||||||
|
@Field("delivery_time")
|
||||||
|
private LocalTime deliveryTime;
|
||||||
|
|
||||||
// Bemerkung
|
// Bemerkung
|
||||||
@Field("remark")
|
@Field("remark")
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|||||||
@@ -112,6 +112,10 @@ public class AddJobView extends Main {
|
|||||||
private DatePicker pickupDate;
|
private DatePicker pickupDate;
|
||||||
private DatePicker deliveryDate;
|
private DatePicker deliveryDate;
|
||||||
|
|
||||||
|
// Time picker fields for appointments
|
||||||
|
private TimePicker pickupTime;
|
||||||
|
private TimePicker deliveryTime;
|
||||||
|
|
||||||
private com.vaadin.flow.component.tabs.Tab addressesTab;
|
private com.vaadin.flow.component.tabs.Tab addressesTab;
|
||||||
private com.vaadin.flow.component.tabs.Tab appointmentsTab;
|
private com.vaadin.flow.component.tabs.Tab appointmentsTab;
|
||||||
private com.vaadin.flow.component.tabs.Tab cargoTab;
|
private com.vaadin.flow.component.tabs.Tab cargoTab;
|
||||||
@@ -510,7 +514,7 @@ 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");
|
||||||
TimePicker pickupTime = new TimePicker("Uhrzeit");
|
pickupTime = new TimePicker("Uhrzeit");
|
||||||
HorizontalLayout pickupApptRow = new HorizontalLayout(pickupDate, pickupTime);
|
HorizontalLayout pickupApptRow = new HorizontalLayout(pickupDate, pickupTime);
|
||||||
pickupApptRow.setWidthFull();
|
pickupApptRow.setWidthFull();
|
||||||
pickupApptRow.setSpacing(true);
|
pickupApptRow.setSpacing(true);
|
||||||
@@ -521,7 +525,7 @@ 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");
|
||||||
TimePicker deliveryTime = new TimePicker("Uhrzeit");
|
deliveryTime = new TimePicker("Uhrzeit");
|
||||||
HorizontalLayout deliveryApptRow = new HorizontalLayout(deliveryDate, deliveryTime);
|
HorizontalLayout deliveryApptRow = new HorizontalLayout(deliveryDate, deliveryTime);
|
||||||
deliveryApptRow.setWidthFull();
|
deliveryApptRow.setWidthFull();
|
||||||
deliveryApptRow.setSpacing(true);
|
deliveryApptRow.setSpacing(true);
|
||||||
@@ -843,6 +847,10 @@ public class AddJobView extends Main {
|
|||||||
|
|
||||||
binder.forField(deliveryDate).asRequired("").bind(Job::getDeliveryDate, Job::setDeliveryDate);
|
binder.forField(deliveryDate).asRequired("").bind(Job::getDeliveryDate, Job::setDeliveryDate);
|
||||||
|
|
||||||
|
// Bind time picker fields (optional)
|
||||||
|
binder.bind(pickupTime, Job::getPickupTime, Job::setPickupTime);
|
||||||
|
binder.bind(deliveryTime, Job::getDeliveryTime, Job::setDeliveryTime);
|
||||||
|
|
||||||
// Bind customerSelection field with validation
|
// Bind customerSelection field with validation
|
||||||
binder.forField(customerSelection).asRequired("").bind(Job::getCustomerSelection, Job::setCustomerSelection);
|
binder.forField(customerSelection).asRequired("").bind(Job::getCustomerSelection, Job::setCustomerSelection);
|
||||||
|
|
||||||
@@ -1082,12 +1090,16 @@ public class AddJobView extends Main {
|
|||||||
|
|
||||||
private boolean hasTasksValidationErrors() {
|
private boolean hasTasksValidationErrors() {
|
||||||
for (BaseTask task : tasksState) {
|
for (BaseTask task : tasksState) {
|
||||||
// Check if any ConfirmationTask has an empty description (required field)
|
// Check if any ConfirmationTask has an empty description or buttonText (required fields)
|
||||||
if (task instanceof ConfirmationTask) {
|
if (task instanceof ConfirmationTask confirmationTask) {
|
||||||
String description = task.getDescription();
|
String description = task.getDescription();
|
||||||
if (description == null || description.trim().isEmpty()) {
|
if (description == null || description.trim().isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
String buttonText = confirmationTask.getButtonText();
|
||||||
|
if (buttonText == null || buttonText.trim().isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Check if any TodoListTask has at least one non-empty todo item
|
// Check if any TodoListTask has at least one non-empty todo item
|
||||||
if (task instanceof TodoListTask todoListTask) {
|
if (task instanceof TodoListTask todoListTask) {
|
||||||
@@ -1120,7 +1132,9 @@ public class AddJobView extends Main {
|
|||||||
|
|
||||||
// Zusätzliche Felder, die nicht über den Binder gebunden sind, manuell setzen
|
// Zusätzliche Felder, die nicht über den Binder gebunden sind, manuell setzen
|
||||||
job.setPickupDate(pickupDate.getValue());
|
job.setPickupDate(pickupDate.getValue());
|
||||||
|
job.setPickupTime(pickupTime.getValue());
|
||||||
job.setDeliveryDate(deliveryDate.getValue());
|
job.setDeliveryDate(deliveryDate.getValue());
|
||||||
|
job.setDeliveryTime(deliveryTime.getValue());
|
||||||
if (remarkArea != null)
|
if (remarkArea != null)
|
||||||
job.setRemark(remarkArea.getValue());
|
job.setRemark(remarkArea.getValue());
|
||||||
|
|
||||||
@@ -1815,10 +1829,11 @@ public class AddJobView extends Main {
|
|||||||
descriptionField.getStyle().set("--vaadin-input-field-border-color", "rgba(255, 0, 0, 0.3)");
|
descriptionField.getStyle().set("--vaadin-input-field-border-color", "rgba(255, 0, 0, 0.3)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button text field
|
// Button text field (required)
|
||||||
TextField buttonTextField = new TextField("Button-Text");
|
TextField buttonTextField = new TextField("Button-Text");
|
||||||
buttonTextField.setPlaceholder("z.B. 'Bestätigen', 'Abgeschlossen'");
|
buttonTextField.setPlaceholder("z.B. 'Bestätigen', 'Abgeschlossen'");
|
||||||
buttonTextField.setWidthFull();
|
buttonTextField.setWidthFull();
|
||||||
|
buttonTextField.setRequiredIndicatorVisible(true);
|
||||||
ConfirmationTask confirmationTask = (ConfirmationTask) task;
|
ConfirmationTask confirmationTask = (ConfirmationTask) task;
|
||||||
buttonTextField.setValue(confirmationTask.getButtonText() != null ? confirmationTask.getButtonText() : "");
|
buttonTextField.setValue(confirmationTask.getButtonText() != null ? confirmationTask.getButtonText() : "");
|
||||||
buttonTextField.addValueChangeListener(ev -> {
|
buttonTextField.addValueChangeListener(ev -> {
|
||||||
@@ -1828,7 +1843,23 @@ public class AddJobView extends Main {
|
|||||||
((ConfirmationTask) stateTask).setButtonText(ev.getValue());
|
((ConfirmationTask) stateTask).setButtonText(ev.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Update field styling based on value
|
||||||
|
boolean isEmpty = ev.getValue() == null || ev.getValue().trim().isEmpty();
|
||||||
|
if (isEmpty) {
|
||||||
|
buttonTextField.getStyle().set("--vaadin-input-field-background", "rgba(255, 0, 0, 0.1)");
|
||||||
|
buttonTextField.getStyle().set("--vaadin-input-field-border-color", "rgba(255, 0, 0, 0.3)");
|
||||||
|
} else {
|
||||||
|
buttonTextField.getStyle().remove("--vaadin-input-field-background");
|
||||||
|
buttonTextField.getStyle().remove("--vaadin-input-field-border-color");
|
||||||
|
}
|
||||||
|
triggerValidation();
|
||||||
|
updateTabLabels();
|
||||||
});
|
});
|
||||||
|
// Initial styling for empty field
|
||||||
|
if (confirmationTask.getButtonText() == null || confirmationTask.getButtonText().trim().isEmpty()) {
|
||||||
|
buttonTextField.getStyle().set("--vaadin-input-field-background", "rgba(255, 0, 0, 0.1)");
|
||||||
|
buttonTextField.getStyle().set("--vaadin-input-field-border-color", "rgba(255, 0, 0, 0.3)");
|
||||||
|
}
|
||||||
configContainer.add(descriptionField, buttonTextField);
|
configContainer.add(descriptionField, buttonTextField);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ public class JobSummaryView extends Main implements HasUrlParameter<String> {
|
|||||||
topRow.setSpacing(true);
|
topRow.setSpacing(true);
|
||||||
|
|
||||||
VerticalLayout pickupBox = borderedBox();
|
VerticalLayout pickupBox = borderedBox();
|
||||||
pickupBox.add(new H3("Abholung " + (job.getPickupDate() != null ? formatLocalDate(job.getPickupDate()) : "")));
|
pickupBox.add(new H3("Abholung " + formatDateWithTime(job.getPickupDate(), job.getPickupTime())));
|
||||||
pickupBox.add(new Span(valueOrEmpty(job.getPickupCompany())));
|
pickupBox.add(new Span(valueOrEmpty(job.getPickupCompany())));
|
||||||
pickupBox.add(new Span(valueOrEmpty(job.getPickupSalutation()) + (job.getPickupSalutation() != null ? " " : "")
|
pickupBox.add(new Span(valueOrEmpty(job.getPickupSalutation()) + (job.getPickupSalutation() != null ? " " : "")
|
||||||
+ valueOrEmpty(job.getPickupFirstName()) + (job.getPickupFirstName() != null ? " " : "")
|
+ valueOrEmpty(job.getPickupFirstName()) + (job.getPickupFirstName() != null ? " " : "")
|
||||||
@@ -189,8 +189,7 @@ public class JobSummaryView extends Main implements HasUrlParameter<String> {
|
|||||||
pickupBox.add(new Span(concatZipCity(job.getPickupZip(), job.getPickupCity())));
|
pickupBox.add(new Span(concatZipCity(job.getPickupZip(), job.getPickupCity())));
|
||||||
|
|
||||||
VerticalLayout deliveryBox = borderedBox();
|
VerticalLayout deliveryBox = borderedBox();
|
||||||
deliveryBox.add(
|
deliveryBox.add(new H3("Lieferung " + formatDateWithTime(job.getDeliveryDate(), job.getDeliveryTime())));
|
||||||
new H3("Lieferung " + (job.getDeliveryDate() != null ? formatLocalDate(job.getDeliveryDate()) : "")));
|
|
||||||
deliveryBox.add(new Span(valueOrEmpty(job.getDeliveryCompany())));
|
deliveryBox.add(new Span(valueOrEmpty(job.getDeliveryCompany())));
|
||||||
deliveryBox.add(new Span(valueOrEmpty(job.getDeliverySalutation())
|
deliveryBox.add(new Span(valueOrEmpty(job.getDeliverySalutation())
|
||||||
+ (job.getDeliverySalutation() != null ? " " : "") + valueOrEmpty(job.getDeliveryFirstName())
|
+ (job.getDeliverySalutation() != null ? " " : "") + valueOrEmpty(job.getDeliveryFirstName())
|
||||||
@@ -340,6 +339,25 @@ public class JobSummaryView extends Main implements HasUrlParameter<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String formatLocalTime(java.time.LocalTime time) {
|
||||||
|
try {
|
||||||
|
return DateTimeFormatUtil.formatTime(time);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatDateWithTime(java.time.LocalDate date, java.time.LocalTime time) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (date != null) {
|
||||||
|
sb.append(formatLocalDate(date));
|
||||||
|
if (time != null) {
|
||||||
|
sb.append(", ").append(formatLocalTime(time));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private String valueOrEmpty(String v) {
|
private String valueOrEmpty(String v) {
|
||||||
return v == null ? "" : v;
|
return v == null ? "" : v;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.vaadin.flow.router.Route;
|
|||||||
import de.assecutor.votianlt.model.Job;
|
import de.assecutor.votianlt.model.Job;
|
||||||
import de.assecutor.votianlt.model.JobStatus;
|
import de.assecutor.votianlt.model.JobStatus;
|
||||||
import de.assecutor.votianlt.mqtt.MqttPublisher;
|
import de.assecutor.votianlt.mqtt.MqttPublisher;
|
||||||
|
import de.assecutor.votianlt.util.DateTimeFormatUtil;
|
||||||
import de.assecutor.votianlt.repository.JobRepository;
|
import de.assecutor.votianlt.repository.JobRepository;
|
||||||
import de.assecutor.votianlt.security.SecurityService;
|
import de.assecutor.votianlt.security.SecurityService;
|
||||||
import de.assecutor.votianlt.service.ClientConnectionService;
|
import de.assecutor.votianlt.service.ClientConnectionService;
|
||||||
@@ -106,7 +107,7 @@ public class ShowJobsView extends VerticalLayout {
|
|||||||
grid.addColumn(job -> extractCompanyName(job.getCustomerSelection())).setHeader("Auftraggeber")
|
grid.addColumn(job -> extractCompanyName(job.getCustomerSelection())).setHeader("Auftraggeber")
|
||||||
.setAutoWidth(true).setFlexGrow(1).setSortable(true);
|
.setAutoWidth(true).setFlexGrow(1).setSortable(true);
|
||||||
grid.addColumn(Job::getJobNumber).setHeader("Auftragsnummer").setAutoWidth(true).setSortable(true);
|
grid.addColumn(Job::getJobNumber).setHeader("Auftragsnummer").setAutoWidth(true).setSortable(true);
|
||||||
grid.addColumn(Job::getCreatedAt).setHeader("Auftragsdatum").setAutoWidth(true).setSortable(true);
|
grid.addColumn(job -> DateTimeFormatUtil.formatDateTime(job.getCreatedAt())).setHeader("Auftragsdatum").setAutoWidth(true).setSortable(true);
|
||||||
grid.addColumn(Job::getDeliveryCity).setHeader("Zielort").setAutoWidth(true).setFlexGrow(1).setSortable(true);
|
grid.addColumn(Job::getDeliveryCity).setHeader("Zielort").setAutoWidth(true).setFlexGrow(1).setSortable(true);
|
||||||
|
|
||||||
// Action column: manual completion for jobs without digital processing
|
// Action column: manual completion for jobs without digital processing
|
||||||
@@ -299,7 +300,7 @@ public class ShowJobsView extends VerticalLayout {
|
|||||||
for (Job job : jobs) {
|
for (Job job : jobs) {
|
||||||
csv.append(escapeCsv(extractCompanyName(job.getCustomerSelection()))).append(",");
|
csv.append(escapeCsv(extractCompanyName(job.getCustomerSelection()))).append(",");
|
||||||
csv.append(escapeCsv(job.getJobNumber())).append(",");
|
csv.append(escapeCsv(job.getJobNumber())).append(",");
|
||||||
csv.append(job.getCreatedAt() != null ? job.getCreatedAt().toString() : "").append(",");
|
csv.append(DateTimeFormatUtil.formatDateTime(job.getCreatedAt())).append(",");
|
||||||
csv.append(escapeCsv(job.getDeliveryCity())).append("\n");
|
csv.append(escapeCsv(job.getDeliveryCity())).append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package de.assecutor.votianlt.util;
|
|||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,6 +61,20 @@ public class DateTimeFormatUtil {
|
|||||||
return dateTime.format(TIME_FORMATTER);
|
return dateTime.format(TIME_FORMATTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a LocalTime to German format: "HH:MM Uhr"
|
||||||
|
*
|
||||||
|
* @param time
|
||||||
|
* the LocalTime to format
|
||||||
|
* @return formatted time string or empty string if time is null
|
||||||
|
*/
|
||||||
|
public static String formatTime(LocalTime time) {
|
||||||
|
if (time == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return time.format(TIME_FORMATTER);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the date time formatter for direct use
|
* Returns the date time formatter for direct use
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user