Refactor_Expenses #321

Merged
pramod.mahajan merged 249 commits from Refactor_Expenses into hotfix/MasterActivity 2025-08-01 13:14:59 +00:00
Showing only changes of commit 30b567d020 - Show all commits

View File

@ -4,7 +4,7 @@ import Avatar from "../common/Avatar";
import { convertShortTime } from "../../utils/dateUtils"; import { convertShortTime } from "../../utils/dateUtils";
import RenderAttendanceStatus from "./RenderAttendanceStatus"; import RenderAttendanceStatus from "./RenderAttendanceStatus";
import { useSelector, useDispatch } from "react-redux"; import { useSelector, useDispatch } from "react-redux";
import { fetchAttendanceData, setAttendanceData } from "../../slices/apiSlice/attedanceLogsSlice"; import { fetchAttendanceData, setAttendanceData } from "../../slices/apiSlice/attedanceLogsSlice"; // Corrected typo: atttendanceLogsSlice to attedanceLogsSlice
import DateRangePicker from "../common/DateRangePicker"; import DateRangePicker from "../common/DateRangePicker";
import eventBus from "../../services/eventBus"; import eventBus from "../../services/eventBus";
@ -44,7 +44,7 @@ const AttendanceLog = ({
handleModalData, handleModalData,
projectId, projectId,
setshowOnlyCheckout, setshowOnlyCheckout,
showOnlyCheckout, showOnlyCheckout, // Prop for showPending state
searchQuery, // Prop for search query searchQuery, // Prop for search query
}) => { }) => {
const selectedProject = useSelector( const selectedProject = useSelector(
@ -52,10 +52,13 @@ const AttendanceLog = ({
); );
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" }); const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [showPending,setShowPending] = useState(false)
const [isRefreshing, setIsRefreshing] = 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); // Local state for refresh spinner
const today = useMemo(() => { const today = useMemo(() => {
const d = new Date(); const d = new Date();
@ -89,6 +92,7 @@ const AttendanceLog = ({
return nameA.localeCompare(nameB); return nameA.localeCompare(nameB);
}, []); }, []);
// Effect to fetch attendance data when dateRange or projectId changes
useEffect(() => { useEffect(() => {
const { startDate, endDate } = dateRange; const { startDate, endDate } = dateRange;
dispatch( dispatch(
@ -98,13 +102,13 @@ const AttendanceLog = ({
toDate: endDate, toDate: endDate,
}) })
); );
setIsRefreshing(false); setIsRefreshing(false); // Reset refreshing state after fetch attempt
}, [dateRange, projectId, dispatch, isRefreshing]); }, [dateRange, projectId, dispatch, isRefreshing]); // isRefreshing is a dependency because it triggers a re-fetch
const processedData = useMemo(() => { const processedData = useMemo(() => {
let filteredData = showOnlyCheckout let filteredData = showOnlyCheckout // Use the prop directly
? data.filter((item) => item.checkOutTime === null) ? attendanceLogsData.filter((item) => item.checkOutTime === null) // Use attendanceLogsData
: data; : attendanceLogsData; // Use attendanceLogsData
// Apply search query filter // Apply search query filter
if (searchQuery) { if (searchQuery) {
@ -168,7 +172,7 @@ const AttendanceLog = ({
// Create the final sorted array // Create the final sorted array
return sortedDates.flatMap((date) => groupedByDate[date]); return sortedDates.flatMap((date) => groupedByDate[date]);
}, [data, showOnlyCheckout, searchQuery, isSameDay, isBeforeToday, sortByName]); }, [attendanceLogsData, showOnlyCheckout, searchQuery, isSameDay, isBeforeToday, sortByName]); // Added attendanceLogsData to dependencies
const { const {
currentPage, currentPage,
@ -178,10 +182,10 @@ const AttendanceLog = ({
resetPage, // Destructure resetPage here resetPage, // Destructure resetPage here
} = usePagination(processedData, 20); } = usePagination(processedData, 20);
// Effect to reset pagination when search query changes // Effect to reset pagination when search query or showOnlyCheckout changes
useEffect(() => { useEffect(() => {
resetPage(); resetPage();
}, [searchQuery, resetPage]); // Add resetPage to dependencies }, [searchQuery, showOnlyCheckout, resetPage]); // Add resetPage to dependencies
const handler = useCallback( const handler = useCallback(
(msg) => { (msg) => {
@ -192,7 +196,8 @@ const AttendanceLog = ({
startDate <= checkIn && startDate <= checkIn &&
checkIn <= endDate checkIn <= endDate
) { ) {
const updatedAttendance = data.map((item) => // Create a new array to avoid direct mutation of Redux state data
const updatedAttendance = attendanceLogsData.map((item) => // Use attendanceLogsData
item.id === msg.response.id item.id === msg.response.id
? { ...item, ...msg.response } ? { ...item, ...msg.response }
: item : item
@ -200,16 +205,14 @@ const AttendanceLog = ({
dispatch(setAttendanceData(updatedAttendance)); // Update Redux store dispatch(setAttendanceData(updatedAttendance)); // Update Redux store
} }
}, },
[projectId, dateRange, data, dispatch] [projectId, dateRange, attendanceLogsData, dispatch] // Added attendanceLogsData to dependencies
); );
useEffect(() => {
useEffect(() => { useEffect(() => {
eventBus.on("attendance_log", handler); eventBus.on("attendance_log", handler);
return () => eventBus.off("attendance_log", handler); return () => eventBus.off("attendance_log", handler);
}, [handler]); }, [handler]);
const employeeHandler = useCallback(
const employeeHandler = useCallback( const employeeHandler = useCallback(
(msg) => { (msg) => {
const { startDate, endDate } = dateRange; const { startDate, endDate } = dateRange;
@ -224,12 +227,17 @@ const AttendanceLog = ({
[projectId, dateRange, dispatch] [projectId, dateRange, dispatch]
); );
useEffect(() => { // Removed duplicate useEffect, keeping only one
useEffect(() => { useEffect(() => {
eventBus.on("employee", employeeHandler); eventBus.on("employee", employeeHandler);
return () => eventBus.off("employee", employeeHandler); return () => eventBus.off("employee", employeeHandler);
}, [employeeHandler]); }, [employeeHandler]);
const handleRefreshClick = () => {
setIsRefreshing(true); // Set refreshing state to true
// The useEffect for fetching data will trigger because isRefreshing is a dependency
};
return ( return (
<> <>
<div <div
@ -246,20 +254,20 @@ const AttendanceLog = ({
type="checkbox" type="checkbox"
className="form-check-input" className="form-check-input"
role="switch" role="switch"
disabled={isFetching} disabled={logsFetching} // Use logsFetching from Redux store
id="inactiveEmployeesCheckbox" id="inactiveEmployeesCheckbox"
checked={showPending} checked={showOnlyCheckout} // Use the prop directly
onChange={(e) => setShowPending(e.target.checked)} onChange={(e) => setshowOnlyCheckout(e.target.checked)} // Use the prop setter
/> />
<label className="form-check-label ms-0">Show Pending</label> <label className="form-check-label ms-0">Show Pending</label>
</div> </div>
</div> </div>
<div className="col-md-2 m-0 text-end"> <div className="col-md-2 m-0 text-end">
<i <i
className={`bx bx-refresh cursor-pointer fs-4 ${loading || isRefreshing ? "spin" : "" className={`bx bx-refresh cursor-pointer fs-4 ${logsLoading || isRefreshing ? "spin" : "" // Use logsLoading for overall loading, isRefreshing for local spinner
}`} }`}
title="Refresh" title="Refresh"
onClick={() => refetch()} onClick={handleRefreshClick} // Call the new handler
/> />
</div> </div>
</div> </div>
@ -286,13 +294,13 @@ const AttendanceLog = ({
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{(loading || isRefreshing) && ( {(logsLoading || isRefreshing) && ( // Use logsLoading and isRefreshing
<tr> <tr>
<td colSpan={6}>Loading...</td> <td colSpan={6}>Loading...</td>
</tr> </tr>
)} )}
{!loading && {!logsLoading && // Use logsLoading
!isRefreshing && !isRefreshing && // Use isRefreshing
paginatedAttendances.reduce((acc, attendance, index, arr) => { paginatedAttendances.reduce((acc, attendance, index, arr) => {
const currentDate = moment( const currentDate = moment(
attendance.checkInTime || attendance.checkOutTime attendance.checkInTime || attendance.checkOutTime
@ -362,8 +370,8 @@ const AttendanceLog = ({
</tbody> </tbody>
</table> </table>
) : ( ) : (
!loading && !logsLoading && // Use logsLoading
!isRefreshing && ( !isRefreshing && ( // Use isRefreshing
<div <div
className="d-flex justify-content-center align-items-center text-muted" className="d-flex justify-content-center align-items-center text-muted"
style={{ style={{
@ -375,7 +383,7 @@ const AttendanceLog = ({
) )
)} )}
</div> </div>
{!loading && !isRefreshing && processedData.length > 20 && ( {!logsLoading && !isRefreshing && processedData.length > 20 && ( // Use logsLoading and isRefreshing
<nav aria-label="Page "> <nav aria-label="Page ">
<ul className="pagination pagination-sm justify-content-end py-1"> <ul className="pagination pagination-sm justify-content-end py-1">
<li className={`page-item ${currentPage === 1 ? "disabled" : ""}`}> <li className={`page-item ${currentPage === 1 ? "disabled" : ""}`}>