diff --git a/src/components/Activities/Attendance.jsx b/src/components/Activities/Attendance.jsx index fed34f34..2dde2938 100644 --- a/src/components/Activities/Attendance.jsx +++ b/src/components/Activities/Attendance.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback } from "react"; +import React, { useState, useEffect, useCallback, useMemo } from "react"; import moment from "moment"; import Avatar from "../common/Avatar"; import { convertShortTime } from "../../utils/dateUtils"; @@ -10,16 +10,18 @@ import { useAttendance } from "../../hooks/useAttendance"; import { useSelector } from "react-redux"; import { useQueryClient } from "@tanstack/react-query"; import eventBus from "../../services/eventBus"; +import { useSelectedproject } from "../../slices/apiDataManager"; -const Attendance = ({ getRole, handleModalData }) => { +const Attendance = ({ getRole, handleModalData, searchTerm }) => { 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 selectedProject = useSelector( + // (store) => store.localVariables.projectId + // ); + const selectedProject = useSelectedproject(); const { attendance, loading: attLoading, @@ -28,8 +30,8 @@ const Attendance = ({ getRole, handleModalData }) => { } = useAttendance(selectedProject); const filteredAttendance = ShowPending ? attendance?.filter( - (att) => att?.checkInTime !== null && att?.checkOutTime === null - ) + (att) => att?.checkInTime !== null && att?.checkOutTime === null + ) : attendance; const attendanceList = Array.isArray(filteredAttendance) @@ -48,18 +50,40 @@ const Attendance = ({ getRole, handleModalData }) => { .filter((d) => d.activity === 0) .sort(sortByName); - const filteredData = [...group1, ...group2]; + const finalFilteredData = useMemo(() => { + const combinedData = [...group1, ...group2]; + if (!searchTerm) { + return combinedData; + } + const lowercasedSearchTerm = searchTerm.toLowerCase(); + + return combinedData.filter((item) => { + const fullName = `${item.firstName} ${item.lastName}`.toLowerCase(); + const role = item.jobRoleName?.toLowerCase() || ""; + return ( + fullName.includes(lowercasedSearchTerm) || + role.includes(lowercasedSearchTerm) // ✅ also search by role + ); + }); + }, [group1, group2, searchTerm]); + + const { currentPage, totalPages, currentItems, paginate } = usePagination( - filteredData, + finalFilteredData, ITEMS_PER_PAGE ); + // Reset pagination when the filter or search term changes + useEffect(() => { + }, [finalFilteredData]); + + const handler = useCallback( (msg) => { if (selectedProject == msg.projectId) { queryClient.setQueryData(["attendance", selectedProject], (oldData) => { if (!oldData) { - queryClient.invalidateQueries({queryKey:["attendance"]}) + queryClient.invalidateQueries({ queryKey: ["attendance"] }) }; return oldData.map((record) => record.employeeId === msg.response.employeeId ? { ...record, ...msg.response } : record @@ -72,7 +96,7 @@ const Attendance = ({ getRole, handleModalData }) => { const employeeHandler = useCallback( (msg) => { - if (attendances.some((item) => item.employeeId == msg.employeeId)) { + if (attendance.some((item) => item.employeeId == msg.employeeId)) { attrecall(); } }, @@ -106,7 +130,9 @@ const Attendance = ({ getRole, handleModalData }) => { - {Array.isArray(attendance) && attendance.length > 0 ? ( + {attLoading ? ( +
Loading...
+ ) : currentItems?.length > 0 ? ( <> @@ -188,13 +214,12 @@ const Attendance = ({ getRole, handleModalData }) => {
- {!loading && filteredData.length > 20 && ( + {!loading && finalFilteredData.length > ITEMS_PER_PAGE && ( )} - ) : attLoading ? ( -
Loading...
) : ( -
- {Array.isArray(attendance) - ? "No employees assigned to the project" - : "Attendance data unavailable"} +
+ {searchTerm + ? "No results found for your search." + : attendanceList.length === 0 + ? "No employees assigned to the project." + : "No pending records available."}
)} - - {currentItems?.length == 0 && attendance.length > 0 && ( -
No Pending Record Available !
- )}
); diff --git a/src/components/Activities/AttendcesLogs.jsx b/src/components/Activities/AttendcesLogs.jsx index 0a28ffd3..548175d9 100644 --- a/src/components/Activities/AttendcesLogs.jsx +++ b/src/components/Activities/AttendcesLogs.jsx @@ -6,7 +6,7 @@ import RenderAttendanceStatus from "./RenderAttendanceStatus"; import { useSelector, useDispatch } from "react-redux"; import { fetchAttendanceData } from "../../slices/apiSlice/attedanceLogsSlice"; import DateRangePicker from "../common/DateRangePicker"; -import { clearCacheKey, getCachedData } from "../../slices/apiDataManager"; +import { clearCacheKey, getCachedData, useSelectedproject } from "../../slices/apiDataManager"; import eventBus from "../../services/eventBus"; import AttendanceRepository from "../../repositories/AttendanceRepository"; import { useAttendancesLogs } from "../../hooks/useAttendance"; @@ -33,12 +33,11 @@ const usePagination = (data, itemsPerPage) => { }; }; -const AttendanceLog = ({ - handleModalData, -}) => { - const selectedProject = useSelector( - (store) => store.localVariables.projectId - ); +const AttendanceLog = ({ handleModalData, searchTerm }) => { + // const selectedProject = useSelector( + // (store) => store.localVariables.projectId + // ); + const selectedProject = useSelectedproject(); const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" }); const dispatch = useDispatch(); const [loading, setLoading] = useState(false); @@ -139,17 +138,29 @@ const AttendanceLog = ({ filtering(data); }, [data, showPending]); + // New useEffect to handle search filtering + const filteredSearchData = useMemo(() => { + if (!searchTerm) { + return processedData; + } + const lowercasedSearchTerm = searchTerm.toLowerCase(); + return processedData.filter((item) => { + const fullName = `${item.firstName} ${item.lastName}`.toLowerCase(); + return fullName.includes(lowercasedSearchTerm); + }); + }, [processedData, searchTerm]); + const { currentPage, totalPages, currentItems: paginatedAttendances, paginate, resetPage, - } = usePagination(processedData, 20); + } = usePagination(filteredSearchData, 20); useEffect(() => { resetPage(); - }, [processedData, resetPage]); + }, [filteredSearchData, resetPage]); const handler = useCallback( (msg) => { @@ -160,20 +171,23 @@ const AttendanceLog = ({ startDate <= checkIn && checkIn <= endDate ) { - queryClient.setQueriesData(["attendanceLogs"],(oldData)=>{ - if(!oldData) { - queryClient.invalidateQueries({queryKey:["attendanceLogs"]}) + queryClient.setQueriesData(["attendanceLogs"], (oldData) => { + if (!oldData) { + queryClient.invalidateQueries({ queryKey: ["attendanceLogs"] }); + return; } - return oldData.map((record) => - record.id === msg.response.id ? { ...record, ...msg.response } : record - ); - }) - - filtering(updatedAttendance); + const updatedAttendance = oldData.map((record) => + record.id === msg.response.id + ? { ...record, ...msg.response } + : record + ); + filtering(updatedAttendance); + return updatedAttendance; + }); resetPage(); } }, - [selectedProject, dateRange, data, filtering, resetPage] + [selectedProject, dateRange, filtering, resetPage] ); useEffect(() => { @@ -196,7 +210,7 @@ const AttendanceLog = ({ refetch() } }, - [selectedProject, dateRange, data] + [selectedProject, dateRange, data, refetch] ); useEffect(() => { @@ -240,8 +254,10 @@ const AttendanceLog = ({
{isLoading ? ( -

Loading...

- ) : data?.length > 0 ? ( +
+

Loading...

+
+ ) : filteredSearchData?.length > 0 ? ( @@ -332,10 +348,12 @@ const AttendanceLog = ({
No Record Available !
)} - {paginatedAttendances?.length == 0 && data?.length > 0 && ( -
No Pending Record Available !
- )} - {processedData.length > 10 && ( + {paginatedAttendances?.length == 0 && filteredSearchData?.length > 0 && ( +
+ No Pending Record Available ! +
+ )} + {filteredSearchData.length > 10 && (
) : (
- {" "} - No Requests Found ! + + {searchTerm ? "No results found for your search." : "No Requests Found !"} +
)} {!loading && totalPages > 1 && ( diff --git a/src/components/Activities/RegularizationActions.jsx b/src/components/Activities/RegularizationActions.jsx index 4ec9b7b9..318b8382 100644 --- a/src/components/Activities/RegularizationActions.jsx +++ b/src/components/Activities/RegularizationActions.jsx @@ -4,7 +4,7 @@ import useAttendanceStatus, { ACTIONS } from '../../hooks/useAttendanceStatus'; import { useDispatch, useSelector } from 'react-redux'; import { usePositionTracker } from '../../hooks/usePositionTracker'; import {markCurrentAttendance} from '../../slices/apiSlice/attendanceAllSlice'; -import {cacheData, getCachedData} from '../../slices/apiDataManager'; +import {cacheData, getCachedData, useSelectedproject} from '../../slices/apiDataManager'; import showToast from '../../services/toastService'; import { useMarkAttendance } from '../../hooks/useAttendance'; import { useQueryClient } from '@tanstack/react-query'; @@ -17,7 +17,8 @@ const [loadingReject,setLoadingForReject] = useState(false) const {mutate:MarkAttendance,isPending} = useMarkAttendance() const queryClient = useQueryClient() -const projectId = useSelector((store)=>store.localVariables.projectId) +// const projectId = useSelector((store)=>store.localVariables.projectId) +const projectId = useSelectedproject(); const {latitude,longitude} = usePositionTracker(); const dispatch = useDispatch() diff --git a/src/components/Dashboard/AttendanceChart.jsx b/src/components/Dashboard/AttendanceChart.jsx index df99b07d..1ac04954 100644 --- a/src/components/Dashboard/AttendanceChart.jsx +++ b/src/components/Dashboard/AttendanceChart.jsx @@ -98,42 +98,42 @@ const AttendanceOverview = () => { colors: roles.map((_, i) => flatColors[i % flatColors.length]), }; - return ( -
- {/* Header */} -
-
-
Attendance Overview
-

Role-wise present count

-
-
- - - -
-
+ return ( +
+ {/* Header */} +
+
+
Attendance Overview
+

Role-wise present count

+
+
+ + + +
+
{/* Content */}
diff --git a/src/components/Directory/ManageBucket.jsx b/src/components/Directory/ManageBucket.jsx index 0af5108a..58344a15 100644 --- a/src/components/Directory/ManageBucket.jsx +++ b/src/components/Directory/ManageBucket.jsx @@ -19,7 +19,7 @@ import { useProfile } from "../../hooks/useProfile"; const ManageBucket = () => { const { profile } = useProfile(); const [bucketList, setBucketList] = useState([]); - const {employeesList} = useAllEmployees( false ); + const { employeesList } = useAllEmployees(false); const [selectedEmployee, setSelectEmployee] = useState([]); const { buckets, loading, refetch } = useBuckets(); const [action_bucket, setAction_bucket] = useState(false); @@ -237,9 +237,8 @@ const ManageBucket = () => { onChange={(e) => setSearchTerm(e.target.value)} /> refetch()} /> @@ -248,9 +247,8 @@ const ManageBucket = () => { - - {jobRoleData?.map((user) => ( -
  • - + {selectedRolesCount} + + )} + + {/* Dropdown Menu with Scroll */} +
      + {/* All Roles */} +
    • +
      + + handleRoleChange(e, e.target.value) + } + /> + +
    • - ))} -
    + + {/* Dynamic Roles */} + {jobRolesForDropdown?.map((role) => ( +
  • +
    + + handleRoleChange(e, e.target.value) + } + /> + +
    +
  • + ))} + +
    + + {/* Search Box */} +
    -
    -
    - {selectedRole !== "" && ( -
    - {employeeLoading ? ( -
    -

    Loading employees...

    -
    - ) : filteredEmployees?.length > 0 ? ( - filteredEmployees.map((emp) => { - const jobRole = jobRoleData?.find( - (role) => role?.id === emp?.jobRoleId - ); + {/* Employees list */} +
    + {selectedRoles?.length > 0 && ( +
    + {employeeLoading ? ( +
    +

    Loading employees...

    +
    + ) : filteredEmployees?.length > 0 ? ( + filteredEmployees.map((emp) => { + const jobRole = jobRoleData?.find( + (role) => role?.id === emp?.jobRoleId + ); - return ( -
    -
    - ( - { - handleCheckboxChange(e, emp); - }} - /> + return ( +
    +
    + ( + { + handleCheckboxChange(e, emp); + }} + /> + )} + /> +
    +

    + {emp.firstName} {emp.lastName} +

    + + {loading ? ( + + + + ) : ( + jobRole?.name || "Unknown Role" )} - /> -
    -

    - {emp.firstName} {emp.lastName} -

    - - {loading ? ( - - - - ) : ( - jobRole?.name || "Unknown Role" - )} - -
    +
    - ); - }) - ) : ( -
    -

    +

    + ); + }) + ) : ( +
    +

    No employees found for the selected role. -

    -
    - )} -
    - )} -
    +

    +
    + )} +
    + )}
    {
    -
    @@ -397,10 +501,7 @@ const AssignTask = ({ assignData, onClose, setAssigned }) => { {/* Target for Today input and validation */}
    -
    )} />
    {errors.plannedTask && ( -
    - {errors.plannedTask.message} -
    - )} - - {isHelpVisible && ( -
    - {/* Add your help content here */} -

    - Enter the target value for today's task. -

    -
    +
    {errors.plannedTask.message}
    )}
    @@ -476,12 +543,7 @@ const AssignTask = ({ assignData, onClose, setAssigned }) => { name="description" control={control} render={({ field }) => ( -