diff --git a/src/components/Activities/AttendcesLogs.jsx b/src/components/Activities/AttendcesLogs.jsx index 6d59d320..0a28ffd3 100644 --- a/src/components/Activities/AttendcesLogs.jsx +++ b/src/components/Activities/AttendcesLogs.jsx @@ -4,31 +4,24 @@ import Avatar from "../common/Avatar"; import { convertShortTime } from "../../utils/dateUtils"; import RenderAttendanceStatus from "./RenderAttendanceStatus"; import { useSelector, useDispatch } from "react-redux"; -import { fetchAttendanceData, setAttendanceData } from "../../slices/apiSlice/attedanceLogsSlice"; +import { fetchAttendanceData } from "../../slices/apiSlice/attedanceLogsSlice"; import DateRangePicker from "../common/DateRangePicker"; +import { clearCacheKey, getCachedData } from "../../slices/apiDataManager"; import eventBus from "../../services/eventBus"; +import AttendanceRepository from "../../repositories/AttendanceRepository"; +import { useAttendancesLogs } from "../../hooks/useAttendance"; +import { queryClient } from "../../layouts/AuthLayout"; const usePagination = (data, itemsPerPage) => { const [currentPage, setCurrentPage] = useState(1); - const totalItems = Array.isArray(data) ? data.length : 0; - const maxPage = Math.ceil(totalItems / itemsPerPage); - + const maxPage = Math.ceil(data.length / itemsPerPage); const currentItems = useMemo(() => { - if (!Array.isArray(data) || data.length === 0) { - return []; - } const startIndex = (currentPage - 1) * itemsPerPage; const endIndex = startIndex + itemsPerPage; return data.slice(startIndex, endIndex); }, [data, currentPage, itemsPerPage]); - const paginate = useCallback((pageNumber) => { - if (pageNumber > 0 && pageNumber <= maxPage) { - setCurrentPage(pageNumber); - } - }, [maxPage]); - - // Ensure resetPage is returned by the hook + const paginate = useCallback((pageNumber) => setCurrentPage(pageNumber), []); const resetPage = useCallback(() => setCurrentPage(1), []); return { @@ -42,91 +35,59 @@ const usePagination = (data, itemsPerPage) => { const AttendanceLog = ({ handleModalData, - projectId, - setshowOnlyCheckout, - showOnlyCheckout, // Prop for showPending state - searchQuery, // Prop for search query }) => { const selectedProject = useSelector( (store) => store.localVariables.projectId ); const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" }); const dispatch = useDispatch(); + const [loading, setLoading] = useState(false); + const [showPending,setShowPending] = useState(false) - // Get data, loading, and fetching state from the Redux store's attendanceLogs slice - const { data: attendanceLogsData, loading: logsLoading, isFetching: logsFetching } = useSelector( - (state) => state.attendanceLogs // Assuming your slice is named 'attendanceLogs' - ); + const [isRefreshing, setIsRefreshing] = useState(false); + const [processedData, setProcessedData] = useState([]); - const [isRefreshing, setIsRefreshing] = useState(false); // Local state for refresh spinner + const today = new Date(); + today.setHours(0, 0, 0, 0); - const today = useMemo(() => { - const d = new Date(); - d.setHours(0, 0, 0, 0); - return d; - }, []); + const yesterday = new Date(); + yesterday.setDate(yesterday.getDate() - 1); - const yesterday = useMemo(() => { - const d = new Date(); - d.setDate(d.getDate() - 1); - return d; - }, []); - - const isSameDay = useCallback((dateStr) => { + const isSameDay = (dateStr) => { if (!dateStr) return false; const d = new Date(dateStr); d.setHours(0, 0, 0, 0); return d.getTime() === today.getTime(); - }, [today]); + }; - const isBeforeToday = useCallback((dateStr) => { + const isBeforeToday = (dateStr) => { if (!dateStr) return false; const d = new Date(dateStr); d.setHours(0, 0, 0, 0); return d.getTime() < today.getTime(); - }, [today]); + }; - const sortByName = useCallback((a, b) => { - const nameA = `${a.firstName || ""} ${a.lastName || ""}`.toLowerCase(); - const nameB = `${b.firstName || ""} ${b.lastName || ""}`.toLowerCase(); - return nameA.localeCompare(nameB); - }, []); + const sortByName = (a, b) => { + const nameA = a.firstName.toLowerCase() + a.lastName.toLowerCase(); + const nameB = b.firstName.toLowerCase() + b.lastName.toLowerCase(); + return nameA?.localeCompare(nameB); + }; - // Effect to fetch attendance data when dateRange or projectId changes - useEffect(() => { - const { startDate, endDate } = dateRange; - dispatch( - fetchAttendanceData({ - projectId, - fromDate: startDate, - toDate: endDate, - }) - ); - setIsRefreshing(false); // Reset refreshing state after fetch attempt - }, [dateRange, projectId, dispatch, isRefreshing]); // isRefreshing is a dependency because it triggers a re-fetch - - const processedData = useMemo(() => { - let filteredData = showOnlyCheckout // Use the prop directly - ? attendanceLogsData.filter((item) => item.checkOutTime === null) // Use attendanceLogsData - : attendanceLogsData; // Use attendanceLogsData - - // Apply search query filter - if (searchQuery) { - const lowerCaseSearchQuery = searchQuery.toLowerCase(); - filteredData = filteredData.filter((att) => { - // Construct a full name from available parts, filtering out null/undefined - const fullName = [att.firstName, att.middleName, att.lastName] - .filter(Boolean) // This removes null, undefined, or empty string parts - .join(" ") - .toLowerCase(); - - return ( - att.employeeName?.toLowerCase().includes(lowerCaseSearchQuery) || - att.employeeId?.toLowerCase().includes(lowerCaseSearchQuery) || - fullName.includes(lowerCaseSearchQuery) - ); - }); - } + const { + data = [], + isLoading, + error, + refetch, + isFetching, + } = useAttendancesLogs( + selectedProject, + dateRange.startDate, + dateRange.endDate + ); + const filtering = (data) => { + const filteredData = showPending + ? data.filter((item) => item.checkOutTime === null) + : data; const group1 = filteredData .filter((d) => d.activity === 1 && isSameDay(d.checkInTime)) @@ -170,41 +131,49 @@ const AttendanceLog = ({ (a, b) => new Date(b) - new Date(a) ); - // Create the final sorted array - return sortedDates.flatMap((date) => groupedByDate[date]); - }, [attendanceLogsData, showOnlyCheckout, searchQuery, isSameDay, isBeforeToday, sortByName]); // Added attendanceLogsData to dependencies + const finalData = sortedDates.flatMap((date) => groupedByDate[date]); + setProcessedData(finalData); + }; + + useEffect(() => { + filtering(data); + }, [data, showPending]); const { currentPage, totalPages, currentItems: paginatedAttendances, paginate, - resetPage, // Destructure resetPage here + resetPage, } = usePagination(processedData, 20); - // Effect to reset pagination when search query changes useEffect(() => { resetPage(); - }, [searchQuery, resetPage]); // Add resetPage to dependencies + }, [processedData, resetPage]); const handler = useCallback( (msg) => { const { startDate, endDate } = dateRange; const checkIn = msg.response.checkInTime.substring(0, 10); if ( - projectId === msg.projectId && + selectedProject === msg.projectId && startDate <= checkIn && checkIn <= endDate ) { - const updatedAttendance = data.map((item) => - item.id === msg.response.id - ? { ...item, ...msg.response } - : item + queryClient.setQueriesData(["attendanceLogs"],(oldData)=>{ + if(!oldData) { + queryClient.invalidateQueries({queryKey:["attendanceLogs"]}) + } + return oldData.map((record) => + record.id === msg.response.id ? { ...record, ...msg.response } : record ); - dispatch(setAttendanceData(updatedAttendance)); // Update Redux store + }) + + filtering(updatedAttendance); + resetPage(); } }, - [projectId, dateRange, data, dispatch] + [selectedProject, dateRange, data, filtering, resetPage] ); useEffect(() => { @@ -215,28 +184,26 @@ const AttendanceLog = ({ const employeeHandler = useCallback( (msg) => { const { startDate, endDate } = dateRange; - dispatch( - fetchAttendanceData({ - projectId, - fromDate: startDate, - toDate: endDate, - }) - ); + if (data.some((item) => item.employeeId == msg.employeeId)) { + // dispatch( + // fetchAttendanceData({ + // , + // fromDate: startDate, + // toDate: endDate, + // }) + // ); + + refetch() + } }, - [projectId, dateRange, dispatch] + [selectedProject, dateRange, data] ); - // Removed duplicate useEffect, keeping only one useEffect(() => { eventBus.on("employee", employeeHandler); return () => eventBus.off("employee", employeeHandler); }, [employeeHandler]); - const handleRefreshClick = () => { - setIsRefreshing(true); // Set refreshing state to true - // The useEffect for fetching data will trigger because isRefreshing is a dependency - }; - return ( <>
setshowOnlyCheckout(e.target.checked)} // Use the prop setter + checked={showPending} + onChange={(e) => setShowPending(e.target.checked)} />
refetch()} />
-
- {processedData && processedData.length > 0 ? ( +
+ {isLoading ? ( +

Loading...

+ ) : data?.length > 0 ? ( @@ -293,96 +260,82 @@ const AttendanceLog = ({ - {(logsLoading || isRefreshing) && ( // Use logsLoading and isRefreshing - - - - )} - {!logsLoading && // Use logsLoading - !isRefreshing && // Use isRefreshing - paginatedAttendances.reduce((acc, attendance, index, arr) => { - const currentDate = moment( - attendance.checkInTime || attendance.checkOutTime - ).format("YYYY-MM-DD"); - const previousAttendance = arr[index - 1]; - const previousDate = previousAttendance - ? moment( + {paginatedAttendances.reduce((acc, attendance, index, arr) => { + const currentDate = moment( + attendance.checkInTime || attendance.checkOutTime + ).format("YYYY-MM-DD"); + const previousAttendance = arr[index - 1]; + const previousDate = previousAttendance + ? moment( previousAttendance.checkInTime || - previousAttendance.checkOutTime + previousAttendance.checkOutTime ).format("YYYY-MM-DD") - : null; + : null; - if (!previousDate || currentDate !== previousDate) { - acc.push( - - - - ); - } + if (!previousDate || currentDate !== previousDate) { acc.push( - - - - - - + ); - return acc; - }, [])} + } + acc.push( + + + + + + + + ); + return acc; + }, [])}
Loading...
- - {moment(currentDate).format("DD-MM-YYYY")} - -
- - - {moment( - attendance.checkInTime || attendance.checkOutTime - ).format("DD-MMM-YYYY")} - {convertShortTime(attendance.checkInTime)} - {attendance.checkOutTime - ? convertShortTime(attendance.checkOutTime) - : "--"} - - +
+ + {moment(currentDate).format("DD-MM-YYYY")} +
+ + + {moment( + attendance.checkInTime || attendance.checkOutTime + ).format("DD-MMM-YYYY")} + {convertShortTime(attendance.checkInTime)} + {attendance.checkOutTime + ? convertShortTime(attendance.checkOutTime) + : "--"} + + +
) : ( - !logsLoading && // Use logsLoading - !isRefreshing && ( // Use isRefreshing -
- No employee logs. -
- ) +
No Record Available !
)}
- {!logsLoading && !isRefreshing && processedData.length > 20 && ( // Use logsLoading and isRefreshing + {paginatedAttendances?.length == 0 && data?.length > 0 && ( +
No Pending Record Available !
+ )} + {processedData.length > 10 && (
- {/* Search Box remains here */} -
- setSearchQuery(e.target.value)} - // style={{ width: "200px", height: "30px" }} // Optional: further reduce width/height - /> -
- -