From 07885d3ed49876250736580b349f068ef4e3380d Mon Sep 17 00:00:00 2001 From: pramod mahajan Date: Thu, 17 Jul 2025 20:41:57 +0530 Subject: [PATCH] intergrated react-query --- src/components/Activities/Attendance.jsx | 95 ++++++-- src/components/Activities/AttendcesLogs.jsx | 237 +++++++++---------- src/hooks/useAttendance.js | 35 ++- src/pages/Activities/AttendancePage.jsx | 244 +++++++------------- src/slices/localVariablesSlice.jsx | 11 +- 5 files changed, 312 insertions(+), 310 deletions(-) diff --git a/src/components/Activities/Attendance.jsx b/src/components/Activities/Attendance.jsx index 01ebc105..c3cbfe41 100644 --- a/src/components/Activities/Attendance.jsx +++ b/src/components/Activities/Attendance.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useCallback } from "react"; import moment from "moment"; import Avatar from "../common/Avatar"; import { convertShortTime } from "../../utils/dateUtils"; @@ -6,29 +6,40 @@ import RenderAttendanceStatus from "./RenderAttendanceStatus"; import usePagination from "../../hooks/usePagination"; import { useNavigate } from "react-router-dom"; import { ITEMS_PER_PAGE } from "../../utils/constants"; +import { useAttendance } from "../../hooks/useAttendance"; +import { useSelector } from "react-redux"; +import { useQueryClient } from "@tanstack/react-query"; +import eventBus from "../../services/eventBus"; -const Attendance = ({ - attendance, - getRole, - handleModalData, - setshowOnlyCheckout, - showOnlyCheckout, -}) => { +const Attendance = ({ getRole, handleModalData }) => { + const queryClient = useQueryClient(); const [loading, setLoading] = useState(false); const navigate = useNavigate(); const [todayDate, setTodayDate] = useState(new Date()); + const [ShowPending, setShowPending] = useState(false); + const selectedProject = useSelector( + (store) => store.localVariables.projectId + ); + const { + attendance, + loading: attLoading, + recall: attrecall, + } = useAttendance(selectedProject); + const filteredAttendance = ShowPending + ? attendance?.filter( + (att) => att?.checkInTime !== null && att?.checkOutTime === null + ) + : attendance; - // Ensure attendance is an array - const attendanceList = Array.isArray(attendance) ? attendance : []; + const attendanceList = Array.isArray(filteredAttendance) + ? filteredAttendance + : []; - // Function to sort by first and last name const sortByName = (a, b) => { const nameA = (a.firstName + a.lastName).toLowerCase(); const nameB = (b.firstName + b.lastName).toLowerCase(); return nameA?.localeCompare(nameB); }; - - // Filter employees based on activity const group1 = attendanceList .filter((d) => d.activity === 1 || d.activity === 4) .sort(sortByName); @@ -37,30 +48,65 @@ const Attendance = ({ .sort(sortByName); const filteredData = [...group1, ...group2]; - const { currentPage, totalPages, currentItems, paginate } = usePagination( filteredData, ITEMS_PER_PAGE ); + + const handler = useCallback( + (msg) => { + if (selectedProject == msg.projectId) { + const updatedAttendance = attendances.map((item) => + item.employeeId === msg.response.employeeId + ? { ...item, ...msg.response } + : item + ); + queryClient.setQueryData(["attendance", selectedProject], (oldData) => { + if (!oldData) return oldData; + return oldData.map((emp) => + emp.employeeId === data.employeeId ? { ...emp, ...data } : emp + ); + }); + } + }, + [selectedProject, attrecall] + ); + + const employeeHandler = useCallback( + (msg) => { + if (attendances.some((item) => item.employeeId == msg.employeeId)) { + attrecall(); + } + }, + [selectedProject, attendance] + ); + useEffect(() => { + eventBus.on("attendance", handler); + return () => eventBus.off("attendance", handler); + }, [handler]); + + useEffect(() => { + eventBus.on("employee", employeeHandler); + return () => eventBus.off("employee", employeeHandler); + }, [employeeHandler]); return ( <> -
+
Date : {todayDate.toLocaleDateString("en-GB")} -
setshowOnlyCheckout(e.target.checked)} + checked={ShowPending} + onChange={(e) => setShowPending(e.target.checked)} />
- {attendance && attendance.length > 0 && ( + {Array.isArray(attendance) && attendance.length > 0 ? ( <> @@ -81,14 +127,13 @@ const Attendance = ({ {currentItems && currentItems .sort((a, b) => { - // If checkInTime exists, compare it, otherwise, treat null as earlier than a date const checkInA = a?.checkInTime ? new Date(a.checkInTime) : new Date(0); const checkInB = b?.checkInTime ? new Date(b.checkInTime) : new Date(0); - return checkInB - checkInA; // Sort in descending order of checkInTime + return checkInB - checkInA; }) .map((item) => ( @@ -189,6 +234,14 @@ const Attendance = ({ )} + ) : attLoading ? ( +
Loading...
+ ) : ( +
+ {Array.isArray(attendance) + ? "No employees assigned to the project" + : "Attendance data unavailable"} +
)} diff --git a/src/components/Activities/AttendcesLogs.jsx b/src/components/Activities/AttendcesLogs.jsx index 5642c65a..5c78bc62 100644 --- a/src/components/Activities/AttendcesLogs.jsx +++ b/src/components/Activities/AttendcesLogs.jsx @@ -38,11 +38,12 @@ const AttendanceLog = ({ setshowOnlyCheckout, showOnlyCheckout, }) => { - const selectedProject = useSelector((store)=>store.localVariables.projectId) + const selectedProject = useSelector( + (store) => store.localVariables.projectId + ); const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" }); const dispatch = useDispatch(); - const [loading,setLoading] = useState(false) - // const { data, loading, error } = useSelector((store) => store.attendanceLogs); + const [loading, setLoading] = useState(false); const [isRefreshing, setIsRefreshing] = useState(false); const [processedData, setProcessedData] = useState([]); @@ -73,18 +74,17 @@ const AttendanceLog = ({ return nameA?.localeCompare(nameB); }; - // useEffect(() => { - // const { startDate, endDate } = dateRange; - // dispatch( - // fetchAttendanceData({ - // projectId, - // fromDate: startDate, - // toDate: endDate, - // }) - // ); - // setIsRefreshing(false); - // }, [dateRange, projectId, dispatch, isRefreshing]); - const {data= [],isLoading, error, refetch,isFetching} = useAttendancesLogs(selectedProject,dateRange.startDate, dateRange.endDate) + const { + data = [], + isLoading, + error, + refetch, + isFetching, + } = useAttendancesLogs( + selectedProject, + dateRange.startDate, + dateRange.endDate + ); const filtering = (data) => { const filteredData = showOnlyCheckout ? data.filter((item) => item.checkOutTime === null) @@ -128,18 +128,16 @@ const AttendanceLog = ({ return acc; }, {}); - // Sort dates in descending order const sortedDates = Object.keys(groupedByDate).sort( (a, b) => new Date(b) - new Date(a) ); - // Create the final sorted array const finalData = sortedDates.flatMap((date) => groupedByDate[date]); setProcessedData(finalData); - } + }; useEffect(() => { - filtering(data) + filtering(data); }, [data, showOnlyCheckout]); const { @@ -155,49 +153,47 @@ const AttendanceLog = ({ }, [processedData, resetPage]); const handler = useCallback( - (msg) => { - const { startDate, endDate } = dateRange; - const checkIn = msg.response.checkInTime.substring(0, 10); - if ( - projectId === msg.projectId && - startDate <= checkIn && - checkIn <= endDate - ) { - const updatedAttendance = data.map((item) => - item.id === msg.response.id - ? { ...item, ...msg.response } - : item - ); + (msg) => { + const { startDate, endDate } = dateRange; + const checkIn = msg.response.checkInTime.substring(0, 10); + if ( + projectId === msg.projectId && + startDate <= checkIn && + checkIn <= endDate + ) { + const updatedAttendance = data.map((item) => + item.id === msg.response.id ? { ...item, ...msg.response } : item + ); - filtering(updatedAttendance); - resetPage(); - } - }, - [projectId, dateRange, data, filtering, resetPage] -); + filtering(updatedAttendance); + resetPage(); + } + }, + [projectId, dateRange, data, filtering, resetPage] + ); - useEffect(() => { + useEffect(() => { eventBus.on("attendance_log", handler); return () => eventBus.off("attendance_log", handler); }, [handler]); - const employeeHandler = useCallback( + const employeeHandler = useCallback( (msg) => { const { startDate, endDate } = dateRange; if (data.some((item) => item.employeeId == msg.employeeId)) { dispatch( fetchAttendanceData({ - projectId, - fromDate: startDate, - toDate: endDate, - }) - ) + projectId, + fromDate: startDate, + toDate: endDate, + }) + ); } }, - [projectId, dateRange,data] + [projectId, dateRange, data] ); - useEffect(() => { + useEffect(() => { eventBus.on("employee", employeeHandler); return () => eventBus.off("employee", employeeHandler); }, [employeeHandler]); @@ -231,15 +227,14 @@ const AttendanceLog = ({ isFetching ? "spin" : "" }`} title="Refresh" - onClick={()=>refetch()} + onClick={() => refetch()} /> -
- {data && data.length > 0 && ( +
+ {isLoading ? ( +
Loading...
+ ) : data?.length > 0 ? (
@@ -258,87 +253,79 @@ const AttendanceLog = ({ - {(loading || isRefreshing) && ( - - - - )} - {!loading && - !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( - previousAttendance.checkInTime || - previousAttendance.checkOutTime - ).format("YYYY-MM-DD") - : null; + {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 + ).format("YYYY-MM-DD") + : 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) + : "--"} + + +
- )} - {!loading && !isRefreshing && data?.length === 0 && ( - No employee logs + ) : ( + No employee logs )}
- {!loading && !isRefreshing && processedData.length > 10 && ( + {processedData.length > 10 && (
)} */} - -{isCreateModalOpen && modelConfig && ( - - {(modelConfig?.action === 0 || modelConfig?.action === 1 || modelConfig?.action === 2) && ( - - - )} - {/* For view logs */} - {modelConfig?.action === 6 && ( - - + {isCreateModalOpen && modelConfig && ( + + {(modelConfig?.action === 0 || + modelConfig?.action === 1 || + modelConfig?.action === 2) && ( + + )} + {/* For view logs */} + {modelConfig?.action === 6 && ( + + )} + {modelConfig?.action === 7 && ( + + )} + )} - { - modelConfig?.action === 7 &&( - - ) - } - -)} -
{ { label: "Attendance", link: null }, ]} > -
- - +
-
+
{activeTab === "all" && ( - <> - {!attLoading && (
- -
- )} - {!attLoading && filteredAttendance?.length === 0 && ( -

- {" "} - {ShowPending - ? "No Pending Available" - : "No Employee assigned yet."}{" "} -

- )} - + +
)} - {activeTab === "logs" && (
{ />
)} - {activeTab === "regularization" && DoRegularized && (
- {/* */} - +
)} - - {attLoading && Loading..} - {!attLoading && !attendances && Not Found}
diff --git a/src/slices/localVariablesSlice.jsx b/src/slices/localVariablesSlice.jsx index 9bd787c6..7e7ada9d 100644 --- a/src/slices/localVariablesSlice.jsx +++ b/src/slices/localVariablesSlice.jsx @@ -5,6 +5,10 @@ const localVariablesSlice = createSlice({ initialState: { selectedMaster:"Application Role", regularizationCount:0, + defaultDateRange: { + startDate: null, + endDate: null, + }, projectId: null, reload:false @@ -22,9 +26,12 @@ const localVariablesSlice = createSlice({ refreshData: ( state, action ) => { state.reload = action.payload - } + }, + setDefaultDateRange: (state, action) => { + state.defaultDateRange = action.payload; + }, }, }); -export const { changeMaster ,updateRegularizationCount,setProjectId,refreshData} = localVariablesSlice.actions; +export const { changeMaster ,updateRegularizationCount,setProjectId,refreshData,setDefaultDateRange} = localVariablesSlice.actions; export default localVariablesSlice.reducer;