Compare commits

...

3 Commits

Author SHA1 Message Date
Melina Gutierrez
9b3fed87a9 #4 Perfil de Empleado-Registro, Guardado y Modificacion de Informacion Personal con las mejoras implementadas 2024-09-07 17:33:54 -04:00
Melina Gutierrez
94ea2393c4 Merge branch 'main' into #4-Registro-de-Información-Personal
# Conflicts:
#	src/main/java/com/primefactorsolutions/views/EmployeeView.java
2024-09-06 17:12:47 -04:00
c91e4ea1a5 #4-Registrar-empleado (#15)
Reviewed-on: #15
Reviewed-by: alex <alex@primefactorsolutions.com>
Co-authored-by: ricardo051199 <jesus.pelaez@primefactorsolutions.com>
Co-committed-by: ricardo051199 <jesus.pelaez@primefactorsolutions.com>
2024-09-06 00:59:20 +00:00
3 changed files with 244 additions and 231 deletions

View File

@ -28,9 +28,8 @@
private String emergencyCAddress; private String emergencyCAddress;
private String emergencyCPhone; private String emergencyCPhone;
private String emergencyCEmail; private String emergencyCEmail;
@Lob @Column(columnDefinition = "TEXT")
private byte[] profilePicture; private String profileImage;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
private Status status; private Status status;
public enum Status { public enum Status {

View File

@ -16,19 +16,16 @@ import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.component.upload.Upload; import com.vaadin.flow.component.upload.Upload;
import com.vaadin.flow.component.upload.receivers.MemoryBuffer; import com.vaadin.flow.component.upload.receivers.MemoryBuffer;
import com.vaadin.flow.data.value.ValueChangeMode; import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.BeforeEvent; import com.vaadin.flow.router.*;
import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.annotation.SpringComponent;
import jakarta.annotation.security.PermitAll; import jakarta.annotation.security.PermitAll;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.vaadin.firitin.components.datepicker.VDatePicker; import org.vaadin.firitin.components.datepicker.VDatePicker;
import org.vaadin.firitin.form.BeanValidationForm; import org.vaadin.firitin.form.BeanValidationForm;
import java.io.InputStream; import java.io.ByteArrayOutputStream;
import java.util.ArrayList; import java.io.IOException;
import java.util.Base64;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -36,239 +33,94 @@ import java.util.UUID;
@PermitAll @PermitAll
@Scope("prototype") @Scope("prototype")
@PageTitle("Employee") @PageTitle("Employee")
@Route(value = "/employees", layout = MainLayout.class) @Route(value = "/employees/:employeeId?/:action?", layout = MainLayout.class)
public class EmployeeView extends BeanValidationForm<Employee> implements HasUrlParameter<String> { public class EmployeeView extends BeanValidationForm<Employee> implements HasUrlParameter<String> {
private static final String SAVE_BUTTON_TEXT = "Save";
private static final String EDIT_BUTTON_TEXT = "Edit";
private static final String NOTIFICATION_SAVE_SUCCESS = "Employee saved successfully.";
private static final String NOTIFICATION_VALIDATE_ERROR = "Please complete the required fields correctly.";
private static final String PHONE_NUMBER_ERROR_MESSAGE = "El teléfono debe contener solo números.";
private final EmployeeService employeeService; private final EmployeeService employeeService;
private final TextField firstName; private final TextField firstName = createTextField("Nombres: ", 30, true);
private final TextField lastName; private final TextField lastName = createTextField("Apellidos", 30, true);
private final ComboBox<String> status; private final ComboBox<Employee.Status> status = createStatusComboBox();
private final VDatePicker birthday; private final VDatePicker birthday = new VDatePicker("Fecha de Nacimiento");
private final TextField birthCity; private final TextField birthCity = createTextField("Ciudad y País de Nacimiento", 20, false);
private final ComboBox<String> maritalStatus; private final ComboBox<Employee.MaritalStatus> maritalStatus = createMaritalStatusComboBox();
private final TextField residenceAddress; private final TextField residenceAddress = createTextField("Dirección de Residencia", 50, false);
private final TextField phoneNumber; private final TextField phoneNumber = createTextField("Teléfono", 8, false);
private final EmailField personalEmail; private final EmailField personalEmail = createEmailField("E-mail");
private final TextField position; private final TextField position = createTextField("Cargo", 30, false);
private final TextField team; private final TextField team = createTextField("Equipo", 30, false);
private final TextField emergencyCName = createTextField("Nombres y Apellidos de Contacto", 50, false);
private final TextField emergencyCAddress = createTextField("Dirección de Contacto", 50, false);
private final TextField emergencyCPhone = createTextField("Teléfono de Contacto", 8, false);
private final EmailField emergencyCEmail = createEmailField("Email de Contacto");
private final TextField emergencyCName; private final MemoryBuffer buffer = new MemoryBuffer();
private final TextField emergencyCAddress; private final Upload upload = new Upload(buffer);
private final TextField emergencyCPhone; private final Image profileImagePreview = new Image();
private final EmailField emergencyCEmail;
private final H2 mt; private final Button saveButton = new Button(SAVE_BUTTON_TEXT, e -> saveEmployee());
private final H3 fs; private final Button editButton = new Button(EDIT_BUTTON_TEXT, e -> enableEditMode());
private final H3 ss;
private final Upload imageUpload; private final H2 mt = new H2("Información General del Empleado");
private final Image employeeImage; private final H3 fs = new H3("Información Personal");
private byte[] imageBytes; private final H3 ss = new H3("Datos de Contacto de Emergencia");
private final Button saveButton;
private final Button editButton;
private final List<TextField> formFields = new ArrayList<>();
public EmployeeView(final EmployeeService employeeService) { public EmployeeView(final EmployeeService employeeService) {
super(Employee.class); super(Employee.class);
this.employeeService = employeeService; this.employeeService = employeeService;
mt = new H2("Información General del Empleado"); configureComponents();
fs = new H3("Información Personal"); assembleLayout();
ss = new H3("Datos de Contacto de Emergencia"); }
final HorizontalLayout mainLayout = new HorizontalLayout(); private void configureComponents() {
final VerticalLayout sidebar = createSidebar();
final VerticalLayout contentLayout = createContentLayout();
final VerticalLayout contentLayout2 = createContentLayout();
firstName = new TextField("Nombres: ");
firstName.setWidthFull();
firstName.setMaxLength(30);
firstName.setRequired(true);
lastName = new TextField("Apellidos");
lastName.setWidthFull();
lastName.setMaxLength(30);
lastName.setRequired(true);
status = new ComboBox<>("Estado");
status.setItems(List.of("ACTIVE", "INACTIVE"));
lastName.setWidthFull();
lastName.setMaxLength(30);
status.setRequired(true);
birthday = new VDatePicker("Fecha de Nacimiento");
birthday.setWidthFull();
birthCity = new TextField("Ciudad y País de Nacimiento");
birthCity.setWidthFull();
birthCity.setMaxLength(20);
maritalStatus = new ComboBox<>("Estado Civil");
maritalStatus.setItems(List.of("Soltero", "Casado", "Viudo", "Divorciado"));
maritalStatus.setWidthFull();
residenceAddress = new TextField("Dirección de Residencia");
residenceAddress.setWidthFull();
residenceAddress.setMaxLength(50);
phoneNumber = new TextField("Teléfono");
phoneNumber.setWidthFull();
phoneNumber.setMaxLength(8);
phoneNumber.setValueChangeMode(ValueChangeMode.EAGER); phoneNumber.setValueChangeMode(ValueChangeMode.EAGER);
phoneNumber.addValueChangeListener(e -> { phoneNumber.addValueChangeListener(e -> validatePhoneNumber(phoneNumber, e.getValue()));
if (!e.getValue().matches("\\d*")) {
phoneNumber.setErrorMessage("El teléfono debe contener solo números.");
}
});
personalEmail = new EmailField("E-mail");
personalEmail.setWidthFull();
personalEmail.setMaxLength(30);
position = new TextField("Cargo");
position.setWidthFull();
position.setMaxLength(30);
team = new TextField("Equipo");
team.setWidthFull();
team.setMaxLength(30);
emergencyCName = new TextField("Nombres y Apellidos de Contacto");
emergencyCName.setWidthFull();
emergencyCName.setMaxLength(50);
emergencyCAddress = new TextField("Dirección de Contacto");
emergencyCAddress.setWidthFull();
emergencyCAddress.setMaxLength(50);
emergencyCPhone = new TextField("Teléfono de Contacto");
emergencyCPhone.setWidthFull();
emergencyCPhone.setMaxLength(8);
emergencyCPhone.setValueChangeMode(ValueChangeMode.EAGER); emergencyCPhone.setValueChangeMode(ValueChangeMode.EAGER);
emergencyCPhone.addValueChangeListener(e -> { emergencyCPhone.addValueChangeListener(e -> validatePhoneNumber(emergencyCPhone, e.getValue()));
if (!e.getValue().matches("\\d*")) { configureUpload();
emergencyCPhone.setErrorMessage("El teléfono debe contener solo números."); saveButton.setVisible(true);
editButton.setVisible(true);
}
private void configureUpload() {
upload.setAcceptedFileTypes("image/jpeg", "image/png");
upload.setMaxFileSize(1024 * 1024);
upload.addSucceededListener(event -> {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
buffer.getInputStream().transferTo(outputStream);
byte[] imageBytes = outputStream.toByteArray();
String base64Image = Base64.getEncoder().encodeToString(imageBytes);
getEntity().setProfileImage(base64Image);
profileImagePreview.setSrc("data:image/jpeg;base64," + base64Image);
profileImagePreview.setMaxWidth("150px");
profileImagePreview.setMaxHeight("150px");
} catch (IOException e) {
Notification.show("Error al subir la imagen.");
} }
}); });
emergencyCEmail = new EmailField("Email de Contacto");
emergencyCEmail.setWidthFull();
emergencyCEmail.setMaxLength(30);
MemoryBuffer buffer = new MemoryBuffer();
imageUpload = new Upload(buffer);
imageUpload.setAcceptedFileTypes("image/jpeg", "image/png", "image/gif");
imageUpload.setMaxFileSize(1024 * 1024);
employeeImage = new Image();
employeeImage.setMaxHeight("150px");
employeeImage.setMaxWidth("150px");
imageUpload.addSucceededListener(event -> {
try {
InputStream inputStream = buffer.getInputStream();
imageBytes = inputStream.readAllBytes();
employeeImage.setSrc(
"data:image/png;base64," + java.util.Base64.getEncoder().encodeToString(imageBytes));
Notification.show("Imagen subida correctamente.");
} catch (Exception ex) {
Notification.show(
"Error al subir la imagen: " + ex.getMessage(), 3000, Notification.Position.MIDDLE);
}
});
editButton = new Button("Editar");
saveButton = new Button("Guardar");
setFormFieldsEnabled(false);
editButton.addClickListener(event -> setFormFieldsEnabled(true));
contentLayout.add(
mt, fs, firstName, lastName, status, birthday, birthCity, maritalStatus,
residenceAddress, phoneNumber, personalEmail, position, team, imageUpload, employeeImage);
contentLayout2.add(
ss, emergencyCName, emergencyCAddress, emergencyCPhone, emergencyCEmail);
setSavedHandler((SavedHandler<Employee>) employee -> {
if (validateForm()) {
employee.setProfilePicture(imageBytes);
employee.setStatus(Employee.Status.valueOf(status.getValue()));
final Employee saved = employeeService.createOrUpdate(employee);
Notification.show("Employee saved successfully.");
getUI().ifPresent(ui -> ui.navigate(EmployeesListView.class));
setEntityWithEnabledSave(saved);
setFormFieldsEnabled(false);
} else {
Notification.show("Please complete the required fields correctly.", 3000, Notification.Position.MIDDLE);
}
});
mainLayout.add(sidebar, contentLayout, contentLayout2);
addClassName("main-layout");
} }
private void setFormFieldsEnabled(final boolean enabled) { private void validatePhoneNumber(final TextField textField, final String value) {
firstName.setEnabled(enabled); if (!value.matches("\\d*")) {
lastName.setEnabled(enabled); textField.setErrorMessage(PHONE_NUMBER_ERROR_MESSAGE);
status.setEnabled(enabled);
birthday.setEnabled(enabled);
birthCity.setEnabled(enabled);
maritalStatus.setEnabled(enabled);
residenceAddress.setEnabled(enabled);
phoneNumber.setEnabled(enabled);
personalEmail.setEnabled(enabled);
position.setEnabled(enabled);
team.setEnabled(enabled);
emergencyCName.setEnabled(enabled);
emergencyCAddress.setEnabled(enabled);
emergencyCPhone.setEnabled(enabled);
emergencyCEmail.setEnabled(enabled);
}
private boolean validateForm() {
return !firstName.isEmpty() && !lastName.isEmpty() && status.getValue() != null;
}
private VerticalLayout createSidebar() {
VerticalLayout sidebar = new VerticalLayout();
sidebar.setWidth("250px");
sidebar.add(new Button("Información General", e -> navigateToSection("Información General")));
sidebar.add(new Button("Detalles Profesionales", e -> navigateToSection("Detalles Profesionales")));
return sidebar;
}
private void navigateToSection(final String section) {
Notification.show("Navigating to " + section);
}
private VerticalLayout createContentLayout() {
VerticalLayout contentLayout = new VerticalLayout();
contentLayout.setWidth("100%");
return contentLayout;
}
@Override
public void setParameter(final BeforeEvent beforeEvent, final String s) {
if (StringUtils.isNotBlank(s) && !"new".equals(s)) {
var employee = employeeService.getEmployee(UUID.fromString(s));
setEntityWithEnabledSave(employee);
setFormFieldsEnabled(true);
} else {
setEntityWithEnabledSave(new Employee());
setFormFieldsEnabled(true);
} }
} }
@Override private void assembleLayout() {
protected List<Component> getFormComponents() { HorizontalLayout mainLayout = new HorizontalLayout();
return List.of( VerticalLayout contentLayout1 = createContentLayout();
VerticalLayout contentLayout2 = createContentLayout();
contentLayout1.add(
mt, mt,
fs, fs,
firstName, firstName,
@ -281,15 +133,172 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
phoneNumber, phoneNumber,
personalEmail, personalEmail,
position, position,
team, team);
imageUpload, contentLayout2.add(
employeeImage, ss, emergencyCName, emergencyCAddress,
ss, emergencyCPhone, emergencyCEmail, upload,
emergencyCName, profileImagePreview, saveButton, editButton);
emergencyCAddress,
emergencyCPhone, mainLayout.add(contentLayout1, contentLayout2);
emergencyCEmail, addClassName("main-layout");
editButton }
private ComboBox<Employee.MaritalStatus> createMaritalStatusComboBox() {
ComboBox<Employee.MaritalStatus> comboBox = new ComboBox<>("Estado Civil");
comboBox.setItems(Employee.MaritalStatus.values());
comboBox.setItemLabelGenerator(Employee.MaritalStatus::name);
return comboBox;
}
private ComboBox<Employee.Status> createStatusComboBox() {
ComboBox<Employee.Status> comboBox = new ComboBox<>("Estado");
comboBox.setItems(Employee.Status.values());
comboBox.setItemLabelGenerator(Employee.Status::name);
comboBox.setRequiredIndicatorVisible(true); // Indicador de campo requerido
return comboBox;
}
private VerticalLayout createContentLayout() {
VerticalLayout contentLayout = new VerticalLayout();
contentLayout.setWidth("100%");
return contentLayout;
}
private TextField createTextField(final String label, final int maxLength, final boolean required) {
TextField textField = new TextField(label);
textField.setWidthFull();
textField.setMaxLength(maxLength);
textField.setRequired(required);
return textField;
}
private EmailField createEmailField(final String label) {
EmailField emailField = new EmailField(label);
emailField.setWidthFull();
emailField.setMaxLength(30);
return emailField;
}
private <T> ComboBox<T> createComboBox(final String label, final T[] items) {
ComboBox<T> comboBox = new ComboBox<>(label);
comboBox.setItems(items);
comboBox.setItemLabelGenerator(Object::toString);
comboBox.setWidthFull();
return comboBox;
}
private boolean validateForm() {
return !firstName.isEmpty() && !lastName.isEmpty() && status.getValue() != null;
}
private void saveEmployee() {
if (validateForm()) {
Employee employee = getEntity();
employee.setStatus(status.getValue());
employeeService.createOrUpdate(employee);
Notification.show(NOTIFICATION_SAVE_SUCCESS);
getUI().ifPresent(ui -> ui.navigate(EmployeesListView.class));
} else {
Notification.show(NOTIFICATION_VALIDATE_ERROR, 3000, Notification.Position.MIDDLE);
}
}
private void enableEditMode() {
setFieldsEditable();
saveButton.setVisible(true);
editButton.setVisible(false);
}
@Override
public void setParameter(final BeforeEvent beforeEvent, final String action) {
RouteParameters params = beforeEvent.getRouteParameters();
String s = params.get("employeeId").orElse(null);
if ("new".equals(action)) {
setEntityWithEnabledSave(new Employee());
saveButton.setVisible(true);
editButton.setVisible(false);
setFieldsEditable();
} else {
UUID employeeId = UUID.fromString(s);
var employee = employeeService.getEmployee(employeeId);
setEntityWithEnabledSave(employee);
if ("edit".equals(action) && !s.isEmpty()) {
saveButton.setVisible(true);
editButton.setVisible(false);
status.setValue(employee.getStatus());
setFieldsEditable();
} else if ("view".equals(action) && !s.isEmpty()) {
setFieldsReadOnly();
saveButton.setVisible(false);
editButton.setVisible(true);
setFieldsReadOnly();
displayProfileImage(employee);
}
}
}
private void displayProfileImage(final Employee employee) {
if (employee.getProfileImage() != null && !employee.getProfileImage().isEmpty()) {
profileImagePreview.setSrc("data:image/jpeg;base64," + employee.getProfileImage());
profileImagePreview.setVisible(true);
profileImagePreview.setMaxWidth("150px");
profileImagePreview.setMaxHeight("150px");
upload.setVisible(false);
} else {
profileImagePreview.setVisible(false);
upload.setVisible(true);
}
}
private void setFieldsReadOnly() {
firstName.setReadOnly(true);
lastName.setReadOnly(true);
status.setReadOnly(true);
birthday.setReadOnly(true);
birthCity.setReadOnly(true);
maritalStatus.setReadOnly(true);
residenceAddress.setReadOnly(true);
phoneNumber.setReadOnly(true);
personalEmail.setReadOnly(true);
position.setReadOnly(true);
team.setReadOnly(true);
emergencyCName.setReadOnly(true);
emergencyCAddress.setReadOnly(true);
emergencyCPhone.setReadOnly(true);
emergencyCEmail.setReadOnly(true);
upload.setVisible(true);
profileImagePreview.setVisible(true);
}
private void setFieldsEditable() {
firstName.setReadOnly(false);
lastName.setReadOnly(false);
status.setReadOnly(false);
birthday.setReadOnly(false);
birthCity.setReadOnly(false);
maritalStatus.setReadOnly(false);
residenceAddress.setReadOnly(false);
phoneNumber.setReadOnly(false);
personalEmail.setReadOnly(false);
position.setReadOnly(false);
team.setReadOnly(false);
emergencyCName.setReadOnly(false);
emergencyCAddress.setReadOnly(false);
emergencyCPhone.setReadOnly(false);
emergencyCEmail.setReadOnly(false);
upload.setVisible(true);
}
@Override
protected List<Component> getFormComponents() {
return List.of(
mt, fs, firstName, lastName, status, birthday, birthCity, maritalStatus,
residenceAddress, phoneNumber, personalEmail, position, team, ss, emergencyCName,
emergencyCAddress, emergencyCPhone, emergencyCEmail, upload, profileImagePreview, saveButton, editButton
); );
} }
} }

View File

@ -42,6 +42,7 @@ public class EmployeesListView extends Main {
private void configureTable() { private void configureTable() {
table.setColumns("firstName", "lastName", "status"); table.setColumns("firstName", "lastName", "status");
addEditButtonColumn("View", this::navigateToEmployeeView);
addEditButtonColumn("Edit", this::navigateToEditView); addEditButtonColumn("Edit", this::navigateToEditView);
setupPagingGrid(); setupPagingGrid();
@ -72,7 +73,11 @@ public class EmployeesListView extends Main {
} }
private void navigateToEditView(final Employee employee) { private void navigateToEditView(final Employee employee) {
getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, employee.getId().toString())); getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, employee.getId().toString() + "/edit"));
}
private void navigateToEmployeeView(final Employee employee) {
getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, employee.getId().toString() + "/view"));
} }
private void navigateToAddEmployeeView() { private void navigateToAddEmployeeView() {