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 moment from "moment";
|
||||
import Avatar from "../common/Avatar";
|
||||
import { convertShortTime } from "../../utils/dateUtils";
|
||||
import RenderAttendanceStatus from "./RenderAttendanceStatus";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
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 [selectedDate, setSelectedDate] = useState("");
|
||||
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
|
||||
const dispatch = useDispatch();
|
||||
const { data, loading, error } = useSelector((store) => store.attendanceLogs);
|
||||
|
||||
// Set the default selected date to the current date
|
||||
|
||||
// const currentDate = new Date().toISOString().split("T")[0]; // "YYYY-MM-DD"
|
||||
const currentDate = new Date().toLocaleDateString('en-CA');
|
||||
const handleDateChange = (e) => {
|
||||
const date = e.target.value;
|
||||
setSelectedDate(date);
|
||||
if (date) {
|
||||
dispatch(fetchAttendanceData({ projectId, date: date }));
|
||||
}
|
||||
};
|
||||
const [isRefreshing, setIsRefreshing] = useState(true);
|
||||
const currentDate = new Date().toLocaleDateString( "en-CA" );
|
||||
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
||||
data,
|
||||
5
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// If attendance has check-in time, filter it
|
||||
setAttendnaces(attendance?.filter((record) => record.checkInTime !== null));
|
||||
setSelectedDate(currentDate); // Set default selected date to today
|
||||
}, [attendance]);
|
||||
const { startDate, endDate } = dateRange;
|
||||
if (startDate && endDate) {
|
||||
dispatch(
|
||||
fetchAttendanceData({
|
||||
projectId,
|
||||
fromDate: startDate,
|
||||
toDate: endDate,
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [dateRange, projectId, isRefreshing]);
|
||||
|
||||
const renderAttendanceData =
|
||||
selectedDate === currentDate ? attendances : data;
|
||||
|
||||
return (
|
||||
<>
|
||||
<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"
|
||||
>
|
||||
<div className="col-md-3">
|
||||
<input
|
||||
className="form-control form-control-sm"
|
||||
type="date"
|
||||
placeholder="Select Date"
|
||||
value={selectedDate}
|
||||
onChange={handleDateChange}
|
||||
id="html5-date-input"
|
||||
<div className="col-md-3 my-0 ">
|
||||
<DateRangePicker onRangeChange={setDateRange} />
|
||||
</div>
|
||||
<div className="col-md-2 m-0 text-end">
|
||||
<i
|
||||
className={`bx bx-refresh cursor-pointer fs-4 ${
|
||||
loading ? "spin":""
|
||||
}`}
|
||||
title="Refresh"
|
||||
onClick={()=>setIsRefreshing(!isRefreshing)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="table-responsive text-nowrap">
|
||||
{attendance && attendance.length > 0 ? (
|
||||
{data && data.length > 0 ? (
|
||||
<table className="table mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="border-top-1" colSpan={2}>
|
||||
Name
|
||||
</th>
|
||||
<th className="border-top-1">Role</th>
|
||||
<th className="border-top-1">Date</th>
|
||||
<th>
|
||||
<i className="bx bxs-down-arrow-alt text-success"></i>{" "}
|
||||
Check-In
|
||||
@ -72,13 +77,13 @@ const AttendanceLog = ({ attendance, handleModalData, projectId }) => {
|
||||
<tbody>
|
||||
{loading && <td colSpan={5}>Loading...</td>}
|
||||
{error && <td colSpan={5}>{error}</td>}
|
||||
{selectedDate && renderAttendanceData.length === 0 && (
|
||||
{data && data.length === 0 && (
|
||||
<tr>
|
||||
<td colSpan={5}>No Data Found</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
{renderAttendanceData?.map((attendance, index) => (
|
||||
{currentItems?.map((attendance, index) => (
|
||||
<tr key={index}>
|
||||
<td colSpan={2}>
|
||||
<div className="d-flex justify-content-start align-items-center">
|
||||
@ -95,7 +100,10 @@ const AttendanceLog = ({ attendance, handleModalData, projectId }) => {
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>{attendance.jobRoleName}</td>
|
||||
<td>
|
||||
{" "}
|
||||
{moment(attendance.checkInTime).format("DD-MMM-YYYY")}
|
||||
</td>
|
||||
<td>{convertShortTime(attendance.checkInTime)}</td>
|
||||
<td>
|
||||
{attendance.checkOutTime
|
||||
@ -118,6 +126,51 @@ const AttendanceLog = ({ attendance, handleModalData, projectId }) => {
|
||||
<span>No employee logs</span>
|
||||
)}
|
||||
</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";
|
||||
|
||||
const AttendancePage = () => {
|
||||
const [activeTab, setActiveTab] = useState("all");
|
||||
|
||||
const loginUser = getCachedProfileData();
|
||||
var selectedProject = useSelector((store) => store.localVariables.projectId);
|
||||
const { projects, loading: projectLoading } = useProjects();
|
||||
@ -121,7 +123,7 @@ const AttendancePage = () => {
|
||||
<div className="nav-align-top nav-tabs-shadow">
|
||||
<ul className="nav nav-tabs" role="tablist">
|
||||
<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"
|
||||
>
|
||||
{loginUser && loginUser?.projects?.length > 1 && (
|
||||
@ -152,18 +154,17 @@ const AttendancePage = () => {
|
||||
</select>
|
||||
</label>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</ul>
|
||||
<ul className="nav nav-tabs" role="tablist">
|
||||
<li className="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
className="nav-link active"
|
||||
role="tab"
|
||||
className={`nav-link ${activeTab === "all" ? "active" : ""}`}
|
||||
onClick={() => setActiveTab("all")}
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target="#navs-top-home"
|
||||
aria-controls="navs-top-home"
|
||||
aria-selected="true"
|
||||
>
|
||||
All
|
||||
</button>
|
||||
@ -171,12 +172,10 @@ const AttendancePage = () => {
|
||||
<li className="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
className="nav-link"
|
||||
role="tab"
|
||||
className={`nav-link ${activeTab === "logs" ? "active" : ""}`}
|
||||
onClick={() => setActiveTab("logs")}
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target="#navs-top-profile"
|
||||
aria-controls="navs-top-profile"
|
||||
aria-selected="false"
|
||||
>
|
||||
Logs
|
||||
</button>
|
||||
@ -184,12 +183,12 @@ const AttendancePage = () => {
|
||||
<li className={`nav-item ${!DoRegularized && "d-none"}`}>
|
||||
<button
|
||||
type="button"
|
||||
className="nav-link "
|
||||
role="tab"
|
||||
className={`nav-link ${
|
||||
activeTab === "regularization" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => setActiveTab("regularization")}
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target="#navs-top-messages"
|
||||
aria-controls="navs-top-messages"
|
||||
aria-selected="false"
|
||||
>
|
||||
Regularization
|
||||
</button>
|
||||
@ -198,39 +197,30 @@ const AttendancePage = () => {
|
||||
<div className="tab-content attedanceTabs py-2">
|
||||
{projectLoading && <span>Loading..</span>}
|
||||
{!projectLoading && !attendances && <span>Not Found</span>}
|
||||
{projects && projects.length > 0 && (
|
||||
<>
|
||||
<div
|
||||
className="tab-pane fade show active py-0"
|
||||
id="navs-top-home"
|
||||
role="tabpanel"
|
||||
key={projects.id}
|
||||
>
|
||||
|
||||
{activeTab === "all" && (
|
||||
<div className="tab-pane fade show active py-0">
|
||||
<Attendance
|
||||
attendance={attendances}
|
||||
handleModalData={handleModalData}
|
||||
getRole={getRole}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="tab-pane fade"
|
||||
id="navs-top-profile"
|
||||
role="tabpanel"
|
||||
>
|
||||
)}
|
||||
|
||||
{activeTab === "logs" && (
|
||||
<div className="tab-pane fade show active py-0">
|
||||
<AttendanceLog
|
||||
attendance={attendances}
|
||||
handleModalData={handleModalData}
|
||||
projectId={selectedProject}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="tab-pane fade"
|
||||
id="navs-top-messages"
|
||||
role="tabpanel"
|
||||
>
|
||||
)}
|
||||
|
||||
{activeTab === "regularization" && DoRegularized && (
|
||||
<div className="tab-pane fade show active py-0">
|
||||
<Regularization handleRequest={handleSubmit} />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user