Optimize attendance logs and regularization APIs to fetch data only when their respective tabs are active
This commit is contained in:
parent
6dc30f8e2a
commit
6b241b14de
@ -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)}
|
||||||
|
>
|
||||||
|
«
|
||||||
|
</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)}
|
||||||
|
>
|
||||||
|
»
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user