Optimize attendance logs and regularization APIs to fetch data only when their respective tabs are active

This commit is contained in:
Pramod Mahajan 2025-04-29 00:47:32 +05:30
parent 6dc30f8e2a
commit 6b241b14de
2 changed files with 124 additions and 81 deletions

View File

@ -1,64 +1,69 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import moment from "moment";
import Avatar from "../common/Avatar"; 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 } from "../../slices/apiSlice/attedanceLogsSlice"; import { fetchAttendanceData } from "../../slices/apiSlice/attedanceLogsSlice";
import DateRangePicker from "../common/DateRangePicker";
import { getCachedData } from "../../slices/apiDataManager";
import usePagination from "../../hooks/usePagination";
const AttendanceLog = ({ attendance, handleModalData, projectId }) => { const AttendanceLog = ({ handleModalData, projectId }) => {
const [attendances, setAttendnaces] = useState([]); const [attendances, setAttendnaces] = useState([]);
const [selectedDate, setSelectedDate] = useState(""); const [selectedDate, setSelectedDate] = useState("");
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
const dispatch = useDispatch(); const dispatch = useDispatch();
const { data, loading, error } = useSelector((store) => store.attendanceLogs); const { data, loading, error } = useSelector((store) => store.attendanceLogs);
const [isRefreshing, setIsRefreshing] = useState(true);
// Set the default selected date to the current date const currentDate = new Date().toLocaleDateString( "en-CA" );
const { currentPage, totalPages, currentItems, paginate } = usePagination(
// const currentDate = new Date().toISOString().split("T")[0]; // "YYYY-MM-DD" data,
const currentDate = new Date().toLocaleDateString('en-CA'); 5
const handleDateChange = (e) => { );
const date = e.target.value;
setSelectedDate(date);
if (date) {
dispatch(fetchAttendanceData({ projectId, date: date }));
}
};
useEffect(() => { useEffect(() => {
// If attendance has check-in time, filter it const { startDate, endDate } = dateRange;
setAttendnaces(attendance?.filter((record) => record.checkInTime !== null)); if (startDate && endDate) {
setSelectedDate(currentDate); // Set default selected date to today dispatch(
}, [attendance]); fetchAttendanceData({
projectId,
const renderAttendanceData = fromDate: startDate,
selectedDate === currentDate ? attendances : data; toDate: endDate,
})
);
}
}, [dateRange, projectId, isRefreshing]);
return ( return (
<> <>
<div <div
className="dataTables_length text-start py-2" className="dataTables_length text-start py-2 d-flex justify-content-between"
id="DataTables_Table_0_length" id="DataTables_Table_0_length"
> >
<div className="col-md-3"> <div className="col-md-3 my-0 ">
<input <DateRangePicker onRangeChange={setDateRange} />
className="form-control form-control-sm" </div>
type="date" <div className="col-md-2 m-0 text-end">
placeholder="Select Date" <i
value={selectedDate} className={`bx bx-refresh cursor-pointer fs-4 ${
onChange={handleDateChange} loading ? "spin":""
id="html5-date-input" }`}
title="Refresh"
onClick={()=>setIsRefreshing(!isRefreshing)}
/> />
</div> </div>
</div> </div>
<div className="table-responsive text-nowrap"> <div className="table-responsive text-nowrap">
{attendance && attendance.length > 0 ? ( {data && data.length > 0 ? (
<table className="table mb-0"> <table className="table mb-0">
<thead> <thead>
<tr> <tr>
<th className="border-top-1" colSpan={2}> <th className="border-top-1" colSpan={2}>
Name Name
</th> </th>
<th className="border-top-1">Role</th> <th className="border-top-1">Date</th>
<th> <th>
<i className="bx bxs-down-arrow-alt text-success"></i>{" "} <i className="bx bxs-down-arrow-alt text-success"></i>{" "}
Check-In Check-In
@ -72,13 +77,13 @@ const AttendanceLog = ({ attendance, handleModalData, projectId }) => {
<tbody> <tbody>
{loading && <td colSpan={5}>Loading...</td>} {loading && <td colSpan={5}>Loading...</td>}
{error && <td colSpan={5}>{error}</td>} {error && <td colSpan={5}>{error}</td>}
{selectedDate && renderAttendanceData.length === 0 && ( {data && data.length === 0 && (
<tr> <tr>
<td colSpan={5}>No Data Found</td> <td colSpan={5}>No Data Found</td>
</tr> </tr>
)} )}
{renderAttendanceData?.map((attendance, index) => ( {currentItems?.map((attendance, index) => (
<tr key={index}> <tr key={index}>
<td colSpan={2}> <td colSpan={2}>
<div className="d-flex justify-content-start align-items-center"> <div className="d-flex justify-content-start align-items-center">
@ -95,7 +100,10 @@ const AttendanceLog = ({ attendance, handleModalData, projectId }) => {
</div> </div>
</div> </div>
</td> </td>
<td>{attendance.jobRoleName}</td> <td>
{" "}
{moment(attendance.checkInTime).format("DD-MMM-YYYY")}
</td>
<td>{convertShortTime(attendance.checkInTime)}</td> <td>{convertShortTime(attendance.checkInTime)}</td>
<td> <td>
{attendance.checkOutTime {attendance.checkOutTime
@ -118,6 +126,51 @@ const AttendanceLog = ({ attendance, handleModalData, projectId }) => {
<span>No employee logs</span> <span>No employee logs</span>
)} )}
</div> </div>
{!loading && (
<nav aria-label="Page ">
<ul className="pagination pagination-sm justify-content-end py-1">
<li
className={`page-item ${
currentPage === 1 ? "disabled" : ""
}`}
>
<button
className="page-link btn-xs"
onClick={() => paginate(currentPage - 1)}
>
&laquo;
</button>
</li>
{[...Array(totalPages)].map((_, index) => (
<li
key={index}
className={`page-item ${
currentPage === index + 1 ? "active" : ""
}`}
>
<button
className="page-link "
onClick={() => paginate(index + 1)}
>
{index + 1}
</button>
</li>
))}
<li
className={`page-item ${
currentPage === totalPages ? "disabled" : ""
}`}
>
<button
className="page-link "
onClick={() => paginate(currentPage + 1)}
>
&raquo;
</button>
</li>
</ul>
</nav>
)}
</> </>
); );
}; };

View File

@ -20,6 +20,8 @@ import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { REGULARIZE_ATTENDANCE } from "../../utils/constants"; import { REGULARIZE_ATTENDANCE } from "../../utils/constants";
const AttendancePage = () => { const AttendancePage = () => {
const [activeTab, setActiveTab] = useState("all");
const loginUser = getCachedProfileData(); const loginUser = getCachedProfileData();
var selectedProject = useSelector((store) => store.localVariables.projectId); var selectedProject = useSelector((store) => store.localVariables.projectId);
const { projects, loading: projectLoading } = useProjects(); const { projects, loading: projectLoading } = useProjects();
@ -121,7 +123,7 @@ const AttendancePage = () => {
<div className="nav-align-top nav-tabs-shadow"> <div className="nav-align-top nav-tabs-shadow">
<ul className="nav nav-tabs" role="tablist"> <ul className="nav nav-tabs" role="tablist">
<div <div
className="dataTables_length text-start py-2 px-2" className="dataTables_length text-start py-2 px-2 d-flex "
id="DataTables_Table_0_length" id="DataTables_Table_0_length"
> >
{loginUser && loginUser?.projects?.length > 1 && ( {loginUser && loginUser?.projects?.length > 1 && (
@ -152,18 +154,17 @@ const AttendancePage = () => {
</select> </select>
</label> </label>
)} )}
</div> </div>
</ul> </ul>
<ul className="nav nav-tabs" role="tablist"> <ul className="nav nav-tabs" role="tablist">
<li className="nav-item"> <li className="nav-item">
<button <button
type="button" type="button"
className="nav-link active" className={`nav-link ${activeTab === "all" ? "active" : ""}`}
role="tab" onClick={() => setActiveTab("all")}
data-bs-toggle="tab" data-bs-toggle="tab"
data-bs-target="#navs-top-home" data-bs-target="#navs-top-home"
aria-controls="navs-top-home"
aria-selected="true"
> >
All All
</button> </button>
@ -171,12 +172,10 @@ const AttendancePage = () => {
<li className="nav-item"> <li className="nav-item">
<button <button
type="button" type="button"
className="nav-link" className={`nav-link ${activeTab === "logs" ? "active" : ""}`}
role="tab" onClick={() => setActiveTab("logs")}
data-bs-toggle="tab" data-bs-toggle="tab"
data-bs-target="#navs-top-profile" data-bs-target="#navs-top-profile"
aria-controls="navs-top-profile"
aria-selected="false"
> >
Logs Logs
</button> </button>
@ -184,12 +183,12 @@ const AttendancePage = () => {
<li className={`nav-item ${!DoRegularized && "d-none"}`}> <li className={`nav-item ${!DoRegularized && "d-none"}`}>
<button <button
type="button" type="button"
className="nav-link " className={`nav-link ${
role="tab" activeTab === "regularization" ? "active" : ""
}`}
onClick={() => setActiveTab("regularization")}
data-bs-toggle="tab" data-bs-toggle="tab"
data-bs-target="#navs-top-messages" data-bs-target="#navs-top-messages"
aria-controls="navs-top-messages"
aria-selected="false"
> >
Regularization Regularization
</button> </button>
@ -198,39 +197,30 @@ const AttendancePage = () => {
<div className="tab-content attedanceTabs py-2"> <div className="tab-content attedanceTabs py-2">
{projectLoading && <span>Loading..</span>} {projectLoading && <span>Loading..</span>}
{!projectLoading && !attendances && <span>Not Found</span>} {!projectLoading && !attendances && <span>Not Found</span>}
{projects && projects.length > 0 && (
<> {activeTab === "all" && (
<div <div className="tab-pane fade show active py-0">
className="tab-pane fade show active py-0" <Attendance
id="navs-top-home" attendance={attendances}
role="tabpanel" handleModalData={handleModalData}
key={projects.id} getRole={getRole}
> />
<Attendance </div>
attendance={attendances} )}
handleModalData={handleModalData}
getRole={getRole} {activeTab === "logs" && (
/> <div className="tab-pane fade show active py-0">
</div> <AttendanceLog
<div handleModalData={handleModalData}
className="tab-pane fade" projectId={selectedProject}
id="navs-top-profile" />
role="tabpanel" </div>
> )}
<AttendanceLog
attendance={attendances} {activeTab === "regularization" && DoRegularized && (
handleModalData={handleModalData} <div className="tab-pane fade show active py-0">
projectId={selectedProject} <Regularization handleRequest={handleSubmit} />
/> </div>
</div>
<div
className="tab-pane fade"
id="navs-top-messages"
role="tabpanel"
>
<Regularization handleRequest={handleSubmit} />
</div>
</>
)} )}
</div> </div>
</div> </div>