diff --git a/src/main/java/com/primefactorsolutions/repositories/TimeOffRequestRepository.java b/src/main/java/com/primefactorsolutions/repositories/TimeOffRequestRepository.java index 1485fa0..f58ae50 100644 --- a/src/main/java/com/primefactorsolutions/repositories/TimeOffRequestRepository.java +++ b/src/main/java/com/primefactorsolutions/repositories/TimeOffRequestRepository.java @@ -13,4 +13,5 @@ public interface TimeOffRequestRepository extends JpaRepository findByEmployeeId(UUID idEmployee); Optional findByEmployeeIdAndState(UUID employeeId, TimeOffRequestStatus state); List findByEmployeeIdAndCategory(UUID employeeId, TimeOffRequestType category); + List findByState(TimeOffRequestStatus state); } diff --git a/src/main/java/com/primefactorsolutions/service/TimeOffRequestService.java b/src/main/java/com/primefactorsolutions/service/TimeOffRequestService.java index c5eba83..a097a83 100644 --- a/src/main/java/com/primefactorsolutions/service/TimeOffRequestService.java +++ b/src/main/java/com/primefactorsolutions/service/TimeOffRequestService.java @@ -31,6 +31,10 @@ public class TimeOffRequestService { return timeOffRequest.orElse(null); } + public List findRequestsByState(TimeOffRequestStatus state) { + return timeOffRequestRepository.findByState(state); + } + public List findRequestsByEmployeeId(final UUID idEmployee) { return timeOffRequestRepository.findByEmployeeId(idEmployee); } diff --git a/src/main/java/com/primefactorsolutions/views/MainLayout.java b/src/main/java/com/primefactorsolutions/views/MainLayout.java index b5602f5..d7e59b6 100644 --- a/src/main/java/com/primefactorsolutions/views/MainLayout.java +++ b/src/main/java/com/primefactorsolutions/views/MainLayout.java @@ -143,9 +143,11 @@ public class MainLayout extends AppLayout { SideNavItem timeOff = new SideNavItem("My Time-off", TimeoffView.class, LineAwesomeIcon.PLANE_DEPARTURE_SOLID.create()); timeOff.addItem(new SideNavItem("Vacations", RequestsListView.class, - LineAwesomeIcon.SUN.create())); + LineAwesomeIcon.UMBRELLA_BEACH_SOLID.create())); timeOff.addItem(new SideNavItem("Add Vacation", RequestRegisterView.class, - LineAwesomeIcon.SUN.create())); + LineAwesomeIcon.CALENDAR_PLUS.create())); + timeOff.addItem(new SideNavItem("Pending Requests", PendingRequestsListView.class, + LineAwesomeIcon.LIST_ALT.create())); SideNavItem timesheet = new SideNavItem("My Timesheet", TimesheetView.class, LineAwesomeIcon.HOURGLASS_START_SOLID.create()); timesheet.addItem(new SideNavItem("Hours Worked", HoursWorkedView.class, diff --git a/src/main/java/com/primefactorsolutions/views/PendingRequestsListView.java b/src/main/java/com/primefactorsolutions/views/PendingRequestsListView.java new file mode 100644 index 0000000..e1311ea --- /dev/null +++ b/src/main/java/com/primefactorsolutions/views/PendingRequestsListView.java @@ -0,0 +1,224 @@ +package com.primefactorsolutions.views; + +import com.primefactorsolutions.model.*; +import com.primefactorsolutions.service.EmployeeService; +import com.primefactorsolutions.service.TeamService; +import com.primefactorsolutions.service.TimeOffRequestService; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.html.Main; +import com.vaadin.flow.component.notification.Notification; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.spring.annotation.SpringComponent; +import jakarta.annotation.security.PermitAll; +import org.springframework.context.annotation.Scope; +import org.vaadin.firitin.components.grid.PagingGrid; + +import java.util.*; +import java.util.stream.Collectors; + +@SpringComponent +@Scope("prototype") +@PageTitle("PendingRequests") +@Route(value = "/pending-requests", layout = MainLayout.class) +@PermitAll +public class PendingRequestsListView extends Main { + + private final TimeOffRequestService requestService; + private final EmployeeService employeeService; + private final TeamService teamService; + private final PagingGrid pendingRequestsGrid = new PagingGrid<>(); + + private List employees = Collections.emptyList(); + private ComboBox employeeFilter; + private ComboBox teamFilter; + private ComboBox categoryFilter; + private UUID selectedRequestId; + + + public PendingRequestsListView(final TimeOffRequestService requestService, + final EmployeeService employeeService, + final TeamService teamService) { + this.requestService = requestService; + this.employeeService = employeeService; + this.teamService = teamService; + this.employees = employeeService.findAllEmployees(); + initializeView(); + refreshGeneralPendingRequestsGrid(null, null, null); + } + + private void initializeView() { + setupFilters(); + setupPendingRequestsGrid(); + add(pendingRequestsGrid); + add(createActionButtons()); + } + + private void setupFilters() { + add(createEmployeeFilter()); + add(createTeamFilter()); + add(createCategoryFilter()); + } + + private void setupPendingRequestsGrid() { + pendingRequestsGrid.addColumn(this::getEmployeeFullName).setHeader("Empleado"); + pendingRequestsGrid.addColumn(this::getTeamName).setHeader("Equipo"); + pendingRequestsGrid.addColumn(this::getCategory).setHeader("Categoría"); + + pendingRequestsGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM); + pendingRequestsGrid.setPageSize(5); + pendingRequestsGrid.asSingleSelect().addValueChangeListener(event -> { + TimeOffRequest selectedRequest = event.getValue(); + if (selectedRequest != null) { + selectedRequestId = selectedRequest.getId(); + } + }); + } + + private HorizontalLayout createActionButtons() { + Button approveButton = createActionButton("Aprobar", TimeOffRequestStatus.APROBADO); + Button rejectButton = createActionButton("Rechazar", TimeOffRequestStatus.RECHAZADO); + Button closeButton = new Button("Salir", event -> navigateToMainView()); + return new HorizontalLayout(approveButton, rejectButton, closeButton); + } + + private Button createActionButton(String caption, TimeOffRequestStatus status) { + return new Button(caption, event -> { + if (selectedRequestId != null) { + TimeOffRequest request = requestService.findTimeOffRequest(selectedRequestId); + request.setState(status); + requestService.saveTimeOffRequest(request); + refreshGeneralPendingRequestsGrid(null, null, null); + } else { + Notification.show("Seleccione una solicitud.", 3000, Notification.Position.MIDDLE); + } + }); + } + + private void refreshGeneralPendingRequestsGrid(final Employee employee, + final Team team, + final TimeOffRequestType category) { + pendingRequestsGrid.setPagingDataProvider((page, pageSize) -> { + int start = (int) (page * pendingRequestsGrid.getPageSize()); + return fetchFilteredPendingRequests(start, pageSize, employee, team, category); + }); + pendingRequestsGrid.getDataProvider().refreshAll(); + } + + private List fetchFilteredPendingRequests(final int start, + final int pageSize, + final Employee employee, + final Team team, + final TimeOffRequestType category) { + List filteredPendingRequests = requestService.findRequestsByState(TimeOffRequestStatus.PENDIENTE); + + if (employee != null && !"TODOS".equals(employee.getFirstName())) { + filteredPendingRequests = filteredPendingRequests.stream() + .filter(emp -> emp.getEmployee().getId().equals(employee.getId())) + .collect(Collectors.toList()); + } + + if (team != null && !"TODOS".equals(team.getName())) { + filteredPendingRequests = filteredPendingRequests.stream() + .filter(emp -> emp.getEmployee().getTeam() != null && emp.getEmployee().getTeam().getId().equals(team.getId())) + .collect(Collectors.toList()); + } + + if (category != null && category != TimeOffRequestType.TODOS) { + filteredPendingRequests = filteredPendingRequests.stream() + .filter(emp -> emp.getCategory().equals(category)) + .collect(Collectors.toList()); + } + + int end = Math.min(start + pageSize, filteredPendingRequests.size()); + return filteredPendingRequests.subList(start, end); + } + + private String getEmployeeFullName(final TimeOffRequest request) { + Employee employee = request.getEmployee(); + return getEmployeeFullNameLabel(employee); + } + + private String getEmployeeFullNameLabel(final Employee employee) { + return "TODOS".equals(employee.getFirstName()) ? "TODOS" : employee.getFirstName() + " " + employee.getLastName(); + } + + private String getTeamName(final TimeOffRequest request) { + Team team = request.getEmployee().getTeam(); + return team != null ? team.getName() : "Sin asignar"; + } + + private String getTeamLabel(final Team team) { + return "TODOS".equals(team.getName()) ? "TODOS" : team.getName(); + } + + private String getCategory(TimeOffRequest request){ + return String.valueOf(request.getCategory()); + } + + private ComboBox createEmployeeFilter() { + employeeFilter = new ComboBox<>("Empleado"); + List employees = new ArrayList<>(employeeService.findAllEmployees()); + employees.addFirst(createAllEmployeesOption()); + employeeFilter.setItems(employees); + employeeFilter.setItemLabelGenerator(this::getEmployeeFullNameLabel); + employeeFilter.setValue(employees.getFirst()); + employeeFilter.addValueChangeListener(event -> + refreshGeneralPendingRequestsGrid( + event.getValue(), + teamFilter.getValue(), + categoryFilter.getValue() + ) + ); + return employeeFilter; + } + + private ComboBox createTeamFilter() { + teamFilter = new ComboBox<>("Equipo"); + List teams = new ArrayList<>(teamService.findAllTeams()); + teams.addFirst(createAllTeamsOption()); + teamFilter.setItems(teams); + teamFilter.setItemLabelGenerator(this::getTeamLabel); + teamFilter.setValue(teams.getFirst()); + teamFilter.addValueChangeListener(event -> + refreshGeneralPendingRequestsGrid( + employeeFilter.getValue(), + event.getValue(), + categoryFilter.getValue() + ) + ); + return teamFilter; + } + + private ComboBox createCategoryFilter() { + categoryFilter = new ComboBox<>("Categoría"); + categoryFilter.setItems(TimeOffRequestType.values()); + categoryFilter.setValue(TimeOffRequestType.values()[0]); + categoryFilter.addValueChangeListener(event -> + refreshGeneralPendingRequestsGrid( + employeeFilter.getValue(), + teamFilter.getValue(), + event.getValue() + ) + ); + return categoryFilter; + } + + private Employee createAllEmployeesOption() { + Employee allEmployeesOption = new Employee(); + allEmployeesOption.setFirstName("TODOS"); + return allEmployeesOption; + } + + private Team createAllTeamsOption() { + Team allTeamsOption = new Team(); + allTeamsOption.setName("TODOS"); + return allTeamsOption; + } + + private void navigateToMainView() { + getUI().ifPresent(ui -> ui.navigate(MainView.class)); + } +} \ No newline at end of file