import React, { useState, useEffect } from 'react'; import { Box, Card, CardContent, Typography, Grid, Divider, Chip, Stack, Pagination, CircularProgress, Select, MenuItem, FormControl, InputLabel, TextField, Button, IconButton, SelectChangeEvent, Alert, } from '@mui/material'; import FilterListIcon from '@mui/icons-material/FilterList'; import VisibilityIcon from '@mui/icons-material/Visibility'; import { subYears, getYear } from 'date-fns'; import { Leave, LeaveStatus } from '../../types/Leave'; import LeaveCard from './LeaveCard'; import LeaveDetail from './LeaveDetail'; import LeaveStatusUpdate from './LeaveStatusUpdate'; // Extend the Leave type to include additional properties needed interface ExtendedLeave extends Leave { employeeName?: string; leaveMasterId?: number; appliedOn?: string; // To match with imported type } export interface LeaveListProps { leaves: ExtendedLeave[]; isLoading?: boolean; error?: string | null; onStatusUpdate?: (leaveId: string, status: LeaveStatus, comment?: string) => Promise; canApprove?: boolean; title?: string; showFilters?: boolean; leaveTypes?: string[]; employees?: { id: string; firstName: string; lastName: string }[]; getLeaveTypeName?: (id?: number) => string; } const LeaveList: React.FC = ({ leaves, isLoading = false, error = null, onStatusUpdate, canApprove = false, title = "Leave Requests", showFilters = true, leaveTypes = [], employees = [], getLeaveTypeName, }) => { const [filteredLeaves, setFilteredLeaves] = useState(leaves); const [statusFilter, setStatusFilter] = useState("All"); const [typeFilter, setTypeFilter] = useState("All"); const [employeeFilter, setEmployeeFilter] = useState("All"); const [yearFilter, setYearFilter] = useState(getYear(new Date())); const [searchTerm, setSearchTerm] = useState(""); const [displayFilters, setDisplayFilters] = useState(false); const [page, setPage] = useState(1); const [selectedLeave, setSelectedLeave] = useState(null); const [showDetailDialog, setShowDetailDialog] = useState(false); const [showApproveDialog, setShowApproveDialog] = useState(false); const [showRejectDialog, setShowRejectDialog] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const itemsPerPage = 6; const years = Array.from({ length: 5 }, (_, i) => getYear(subYears(new Date(), i))); // Apply filters whenever filter values change useEffect(() => { if (!leaves) return; let filtered = [...leaves]; // Filter by year filtered = filtered.filter(leave => { const leaveYear = getYear(new Date(leave.startDate)); return leaveYear === yearFilter; }); // Filter by status if not "All" if (statusFilter !== "All") { filtered = filtered.filter(leave => leave.status === statusFilter); } // Filter by type if not "All" if (typeFilter !== "All") { filtered = filtered.filter(leave => { if (leave.type) return leave.type === typeFilter; return false; }); } // Filter by employee if not "All" if (employeeFilter !== "All") { filtered = filtered.filter(leave => leave.employeeId === employeeFilter); } // Filter by search term if (searchTerm) { filtered = filtered.filter(leave => leave.reason.toLowerCase().includes(searchTerm.toLowerCase()) || leave.employeeName?.toLowerCase().includes(searchTerm.toLowerCase()) ); } setFilteredLeaves(filtered); setPage(1); // Reset to first page whenever filters change }, [leaves, statusFilter, typeFilter, employeeFilter, yearFilter, searchTerm]); const handlePageChange = (event: React.ChangeEvent, value: number) => { setPage(value); }; const handleStatusFilterChange = (event: SelectChangeEvent) => { setStatusFilter(event.target.value); }; const handleTypeFilterChange = (event: SelectChangeEvent) => { setTypeFilter(event.target.value); }; const handleEmployeeFilterChange = (event: SelectChangeEvent) => { setEmployeeFilter(event.target.value); }; const handleYearFilterChange = (event: SelectChangeEvent) => { setYearFilter(Number(event.target.value)); }; const handleSearchChange = (event: React.ChangeEvent) => { setSearchTerm(event.target.value); }; const handleViewLeave = (leave: ExtendedLeave) => { setSelectedLeave(leave); setShowDetailDialog(true); }; const handleApproveLeave = (leave: ExtendedLeave) => { setSelectedLeave(leave); setShowApproveDialog(true); }; const handleRejectLeave = (leave: ExtendedLeave) => { setSelectedLeave(leave); setShowRejectDialog(true); }; const handleSubmitStatusUpdate = async (status: LeaveStatus, comment?: string) => { if (!selectedLeave || !onStatusUpdate) return; setIsSubmitting(true); try { await onStatusUpdate(selectedLeave.id, status, comment); // Close dialogs setShowApproveDialog(false); setShowRejectDialog(false); setSelectedLeave(null); } catch (error) { console.error("Error in status update:", error); } finally { setIsSubmitting(false); } }; const paginatedLeaves = filteredLeaves.slice( (page - 1) * itemsPerPage, page * itemsPerPage ); // Helper function to get leave type name if getLeaveTypeName is not provided const getLeaveTypeDisplay = (leave: ExtendedLeave): string => { if (getLeaveTypeName && leave.leaveMasterId) { return getLeaveTypeName(leave.leaveMasterId); } return leave.type; }; return ( {title} {filteredLeaves.length > 0 && `(${filteredLeaves.length})`} {showFilters && ( setDisplayFilters(!displayFilters)} color={displayFilters ? "primary" : "default"} > )} {displayFilters && ( Status Year {leaveTypes.length > 0 && ( Type )} {employees.length > 0 && ( Employee )} )} {error && ( {error} )} {isLoading ? ( ) : filteredLeaves.length === 0 ? ( No leave requests found ) : ( <> {paginatedLeaves.map(leave => ( handleViewLeave(leave)} onApprove={canApprove && leave.status === 'Pending' ? () => handleApproveLeave(leave) : undefined} onReject={canApprove && leave.status === 'Pending' ? () => handleRejectLeave(leave) : undefined} /> ))} )} {selectedLeave && ( <> setShowDetailDialog(false)} /> {canApprove && ( <> setShowApproveDialog(false)} onSubmit={(comment) => handleSubmitStatusUpdate("Approved", comment)} isSubmitting={isSubmitting} title="Approve Leave Request" actionLabel="Approve" /> setShowRejectDialog(false)} onSubmit={(comment) => handleSubmitStatusUpdate("Rejected", comment)} isSubmitting={isSubmitting} title="Reject Leave Request" actionLabel="Reject" /> )} )} ); }; export default LeaveList;