diff --git a/pom.xml b/pom.xml index e192968..cdd0c6d 100644 --- a/pom.xml +++ b/pom.xml @@ -110,6 +110,11 @@ spring-boot-starter-test test + + commons-beanutils + commons-beanutils + 1.9.4 + org.mockito mockito-core diff --git a/src/main/java/com/primefactorsolutions/model/Employee.java b/src/main/java/com/primefactorsolutions/model/Employee.java index 3d0d863..c6d918b 100644 --- a/src/main/java/com/primefactorsolutions/model/Employee.java +++ b/src/main/java/com/primefactorsolutions/model/Employee.java @@ -1,51 +1,47 @@ -package com.primefactorsolutions.model; + package com.primefactorsolutions.model; + import jakarta.persistence.*; + import lombok.AllArgsConstructor; + import lombok.Data; + import lombok.EqualsAndHashCode; + import lombok.NoArgsConstructor; -import io.hypersistence.utils.hibernate.type.json.JsonType; -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import org.hibernate.annotations.Type; + import java.time.LocalDate; -import java.time.LocalDate; -import java.util.List; - -@Data -@Entity -@AllArgsConstructor -@NoArgsConstructor -@EqualsAndHashCode(callSuper = true) -public class Employee extends BaseEntity { - private String firstName; - private String lastName; - private LocalDate birthday; - private String birthCity; - - @Enumerated(EnumType.STRING) - private MaritalStatus maritalStatus; - - private String residenceAddress; - private String phoneNumber; - private String personalEmail; - - private String emergencyCName; - private String emergencyCAddress; - private String emergencyCPhone; - private String emergencyCEmail; - - @Enumerated(EnumType.STRING) - private Status status; - - public enum Status { - ACTIVE, - INACTIVE + @Data + @Entity + @AllArgsConstructor + @NoArgsConstructor + @EqualsAndHashCode(callSuper = true) + public class Employee extends BaseEntity { + private String firstName; + private String lastName; + private LocalDate birthday; + private String birthCity; + @Enumerated(EnumType.STRING) + private MaritalStatus maritalStatus; + private String residenceAddress; + private String phoneNumber; + private String personalEmail; + private String emergencyCName; + private String emergencyCAddress; + private String emergencyCPhone; + private String emergencyCEmail; + @Enumerated(EnumType.STRING) + private Status status; + public enum Status { + ACTIVE, + INACTIVE + } + public enum MaritalStatus { + SINGLE, + MARRIED, + WIDOWED, + DIVORCED + } + public Status getStatus() { + return status; + } + public void setStatus(final Status status) { + this.status = status; + } } - - public enum MaritalStatus { - SINGLE, - MARRIED, - WIDOWED, - DIVORCED - } -} diff --git a/src/main/java/com/primefactorsolutions/service/EmployeeService.java b/src/main/java/com/primefactorsolutions/service/EmployeeService.java index 5e5a94f..993eecd 100644 --- a/src/main/java/com/primefactorsolutions/service/EmployeeService.java +++ b/src/main/java/com/primefactorsolutions/service/EmployeeService.java @@ -1,17 +1,14 @@ package com.primefactorsolutions.service; - import com.primefactorsolutions.model.Employee; +import org.apache.commons.beanutils.BeanComparator; import com.primefactorsolutions.repositories.EmployeeRepository; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; import lombok.Data; -import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import java.util.List; import java.util.UUID; import java.util.Optional; +import java.util.Collections; @Service @@ -19,31 +16,37 @@ import java.util.Optional; public class EmployeeService { private final EmployeeRepository employeeRepository; - public EmployeeService(EmployeeRepository employeeRepository) { + public EmployeeService(final EmployeeRepository employeeRepository) { this.employeeRepository = employeeRepository; } - public Employee createOrUpdate(final Employee employee) { - final Employee saved = employeeRepository.save(employee); - return saved; + public List findEmployees( + final int start, final int pageSize, final String sortProperty, final boolean asc) { + List employees = employeeRepository.findAll(); + + int end = Math.min(start + pageSize, employees.size()); + employees.sort(new BeanComparator<>(sortProperty)); + + if (!asc) { + Collections.reverse(employees); + } + + return employees.subList(start, end); } - public List getEmployees() { - return employeeRepository.findAll(); + public List findEmployees(final int start, final int pageSize) { + List employees = employeeRepository.findAll(); + + int end = Math.min(start + pageSize, employees.size()); + return employees.subList(start, end); + } + + public Employee createOrUpdate(final Employee employee) { + return employeeRepository.save(employee); } public Employee getEmployee(final UUID id) { Optional employee = employeeRepository.findById(id); return employee.orElse(null); } - - public Page getEmployeesPaginated(int pageNo, int pageSize, String sortField, boolean ascending) { - Sort sort = ascending ? Sort.by(sortField).ascending() : Sort.by(sortField).descending(); - Pageable pageable = PageRequest.of(pageNo - 1, pageSize, sort); - return employeeRepository.findAll(pageable); - } - - public boolean hasNextPage(int currentPage, int pageSize, String sortField, boolean ascending) { - return getEmployeesPaginated(currentPage, pageSize, sortField, ascending).hasNext(); - } -} +} \ No newline at end of file diff --git a/src/main/java/com/primefactorsolutions/views/EmployeeView.java b/src/main/java/com/primefactorsolutions/views/EmployeeView.java index d2a570e..9e49fe4 100644 --- a/src/main/java/com/primefactorsolutions/views/EmployeeView.java +++ b/src/main/java/com/primefactorsolutions/views/EmployeeView.java @@ -145,11 +145,11 @@ public class EmployeeView extends BeanValidationForm implements HasUrl setSavedHandler((SavedHandler) employee -> { if (validateForm()) { final Employee saved = employeeService.createOrUpdate(employee); - Notification.show("Empleado guardado exitosamente."); + Notification.show("Employee saved successfully."); getUI().ifPresent(ui -> ui.navigate(EmployeesListView.class)); setEntityWithEnabledSave(saved); } else { - Notification.show("Acción inválida. Por favor, complete todos los campos requeridos correctamente.", 3000, Notification.Position.MIDDLE); + Notification.show("Please complete the required fields correctly.", 3000, Notification.Position.MIDDLE); } }); diff --git a/src/main/java/com/primefactorsolutions/views/EmployeesListView.java b/src/main/java/com/primefactorsolutions/views/EmployeesListView.java index 4dc9706..489ded8 100644 --- a/src/main/java/com/primefactorsolutions/views/EmployeesListView.java +++ b/src/main/java/com/primefactorsolutions/views/EmployeesListView.java @@ -3,18 +3,19 @@ package com.primefactorsolutions.views; import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.service.EmployeeService; import com.vaadin.flow.component.button.Button; -import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.html.H2; import com.vaadin.flow.component.html.Main; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; -import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.spring.annotation.SpringComponent; +import org.vaadin.firitin.components.grid.PagingGrid; +import com.vaadin.flow.component.grid.GridSortOrder; +import com.vaadin.flow.data.provider.SortDirection; import jakarta.annotation.security.PermitAll; import org.springframework.context.annotation.Scope; -import org.vaadin.firitin.components.grid.VGrid; -import org.springframework.data.domain.Page; + +import java.util.List; + @SpringComponent @Scope("prototype") @@ -24,111 +25,85 @@ import org.springframework.data.domain.Page; public class EmployeesListView extends Main { private final EmployeeService employeeService; - private final int pageSize = 5; - private int currentPage = 1; - private String sortField = "firstName"; - private boolean ascending = true; - private VGrid grid; - private Button previous; - private Button next; + private final PagingGrid table = new PagingGrid<>(Employee.class); - public EmployeesListView(EmployeeService employeeService) { + public EmployeesListView(final EmployeeService employeeService) { this.employeeService = employeeService; - addComponents(); - updateGrid(); + setupView(); + refreshGrid(); } - private void addComponents() { - addTitle(); - addOrderButtons(); - configureGrid(); - addNavigationButtons(); + private void setupView() { + add(new H2("Employee List")); + configureTable(); + add(createAddEmployeeButton()); + add(table); } - private void addTitle() { - final H2 title = new H2("Employees list"); - add(title); + private void configureTable() { + table.setColumns("firstName", "lastName", "status"); + addEditButtonColumn("Edit", this::navigateToEditView); + setupPagingGrid(); } - private void addOrderButtons() { - final HorizontalLayout hl = new HorizontalLayout(); - hl.add(createOrderButton("Employee List in Ascending Order", true)); - hl.add(createOrderButton("Employee List in Descending Order", false)); - add(hl); + private void updateEmployeeStatus(final Employee employee, final boolean isActive) { + employee.setStatus(isActive ? Employee.Status.ACTIVE : Employee.Status.INACTIVE); + employeeService.createOrUpdate(employee); + refreshGrid(); } - private Button createOrderButton(String label, boolean isAscending) { + private void addEditButtonColumn(final String label, final ButtonClickHandler handler) { + table.addComponentColumn(employee -> createButton(label, () -> handler.handle(employee))); + } + + private Button createButton(final String label, final Runnable onClickAction) { Button button = new Button(label); - button.addClickListener(event -> { - sortField = "firstName"; - ascending = isAscending; - updateGrid(); - }); + button.addClickListener(event -> onClickAction.run()); return button; } - private void configureGrid() { - grid = new VGrid<>(Employee.class); - grid.setColumns("firstName", "lastName", "status"); - grid.setAllRowsVisible(true); - grid.addComponentColumn(employee -> createStatusComboBox()).setHeader("Change Status"); - grid.addComponentColumn(employee -> createEditButton()); - grid.addComponentColumn(employee -> createSaveButton()); - add(grid); - } - private ComboBox createStatusComboBox() { - ComboBox statusComboBox = new ComboBox<>(); - statusComboBox.setItems("Active", "Inactive"); - return statusComboBox; - } - - private Button createEditButton() { - return new Button("Edit"); - } - private Button createSaveButton() { - return new Button("Save"); - } - - private void addNavigationButtons() { - final HorizontalLayout hf = new HorizontalLayout(); - previous = createNavigationButton("Previous", -1); - next = createNavigationButton("Next", 1); - hf.add(previous, next, createAddEmployeeButton()); - add(hf); - } - - private Button createNavigationButton(String label, int increment) { - Button button = new Button(label); - button.addClickListener(event -> handlePageChange(increment)); - return button; - } - private void handlePageChange(int increment) { - if (isPageChangeValid(increment)) { - currentPage += increment; - updateGrid(); - } else { - showNotification("No existen más datos en lista."); - } - } - private boolean isPageChangeValid(int increment) { - if (increment < 0) { - return currentPage > 1; - } else if (increment > 0) { - return employeeService.hasNextPage(currentPage, pageSize, sortField, ascending); - } - return false; - } - private void showNotification(String message) { - Notification notification = new Notification(message, 3000, Notification.Position.BOTTOM_END); - notification.open(); - } private Button createAddEmployeeButton() { - return new Button("Add Employee", event -> - getUI().flatMap(ui -> ui.navigate(EmployeeView.class, "new")) - ); + return createButton("Add Employee", this::navigateToAddEmployeeView); } - private void updateGrid() { - Page page = employeeService.getEmployeesPaginated(currentPage, pageSize, sortField, ascending); - grid.setItems(page.getContent()); + + private void navigateToEditView(final Employee employee) { + getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, employee.getId().toString())); } -} + + private void navigateToAddEmployeeView() { + getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, "new")); + } + + private void setupPagingGrid() { + table.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM); + table.setPageSize(5); + } + + private void refreshGrid() { + table.setPagingDataProvider((page, pageSize) -> fetchEmployees((int) page, pageSize)); + } + + private List fetchEmployees(final int page, final int pageSize) { + int start = page * pageSize; + if (hasSortOrder()) { + return fetchSortedEmployees(start, pageSize); + } + return employeeService.findEmployees(start, pageSize); + } + + private boolean hasSortOrder() { + return !table.getSortOrder().isEmpty(); + } + + private List fetchSortedEmployees(final int start, final int pageSize) { + GridSortOrder sortOrder = table.getSortOrder().getFirst(); + return employeeService.findEmployees(start, pageSize, + sortOrder.getSorted().getKey(), + sortOrder.getDirection() == SortDirection.ASCENDING); + } + + @FunctionalInterface + private interface ButtonClickHandler { + void handle(Employee employee); + } +} \ No newline at end of file