Implemented attendance funcationality in attendance module

This commit is contained in:
ashutosh.nehete 2025-06-11 23:23:14 +05:30
parent 369343f1d5
commit 792529776c
5 changed files with 124 additions and 25 deletions

View File

@ -7,6 +7,7 @@ import { useSelector, useDispatch } from "react-redux";
import { fetchAttendanceData } from "../../slices/apiSlice/attedanceLogsSlice";
import DateRangePicker from "../common/DateRangePicker";
import { getCachedData } from "../../slices/apiDataManager";
import eventBus from "../../services/eventBus";
const usePagination = (data, itemsPerPage) => {
const [currentPage, setCurrentPage] = useState(1);
@ -69,7 +70,7 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
setIsRefreshing(false);
}, [dateRange, projectId, dispatch, isRefreshing]);
useEffect(() => {
const filtering = (data) => {
const filteredData = showOnlyCheckout
? data.filter((item) => item.checkOutTime === null)
: data;
@ -108,6 +109,10 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
// Create the final sorted array
const finalData = sortedDates.flatMap((date) => groupedByDate[date]);
setProcessedData(finalData);
}
useEffect(() => {
filtering(data)
}, [data, showOnlyCheckout]);
const { currentPage, totalPages, currentItems: paginatedAttendances, paginate, resetPage } = usePagination(
@ -120,6 +125,34 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
resetPage();
}, [processedData, resetPage]);
const handler = useCallback(
(msg) => {
const { startDate, endDate } = dateRange;
const checkIn = msg.response.checkInTime.substring(0, 10);
if (
projectId === msg.projectId &&
startDate <= checkIn &&
checkIn <= endDate
) {
const updatedAttendance = data.map((item) =>
item.employeeId === msg.response.employeeId
? { ...item, ...msg.response }
: item
);
filtering(updatedAttendance);
resetPage();
}
},
[projectId, dateRange, data, filtering, resetPage]
);
useEffect(() => {
eventBus.on("attendance_log", handler);
return () => eventBus.off("attendance_log", handler);
}, [handler]);
return (
<>

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useCallback, useEffect, useState } from "react";
import Avatar from "../common/Avatar";
import { convertShortTime } from "../../utils/dateUtils";
import RegularizationActions from "./RegularizationActions";
@ -6,6 +6,8 @@ import { useSelector } from "react-redux";
import { useRegularizationRequests } from "../../hooks/useAttendance";
import moment from "moment";
import usePagination from "../../hooks/usePagination";
import eventBus from "../../services/eventBus";
import { cacheData, clearCacheKey } from "../../slices/apiDataManager";
const Regularization = ({ handleRequest }) => {
var selectedProject = useSelector((store) => store.localVariables.projectId);
@ -22,16 +24,38 @@ const Regularization = ({ handleRequest }) => {
const nameB = b.firstName.toLowerCase() + b.lastName.toLowerCase();
return nameA.localeCompare(nameB);
};
const filteredData = [...regularizesList]?.sort(sortByName);
const handler = useCallback(
(msg) => {
if (selectedProject == msg.projectId) {
const updatedAttendance = regularizes?.filter( item => item.id !== msg.response.id );
cacheData("regularizedList", {
data: updatedAttendance,
projectId: selectedProject,
});
// clearCacheKey("regularizedList")
refetch();
}
},
[selectedProject, regularizes]
);
const filteredData = [...regularizesList]?.sort(sortByName);
const { currentPage, totalPages, currentItems, paginate } = usePagination(
filteredData,
10
);
useEffect(() => {
eventBus.on("regularization", handler);
return () => eventBus.off("regularization", handler);
}, [handler]);
return (
<div className="table-responsive text-nowrap" style={{minHeight:"300px"}}>
<div
className="table-responsive text-nowrap"
style={{ minHeight: "300px" }}
>
<table className="table mb-0">
<thead>
<tr>
@ -47,7 +71,11 @@ const Regularization = ({ handleRequest }) => {
</tr>
</thead>
<tbody>
{loading && <td colSpan={6} className="text-center py-5">Loading...</td>}
{loading && (
<td colSpan={6} className="text-center py-5">
Loading...
</td>
)}
{!loading &&
(regularizes?.length > 0 ? (
@ -55,7 +83,7 @@ const Regularization = ({ handleRequest }) => {
<tr key={index}>
<td colSpan={2}>
<div className="d-flex justify-content-start align-items-center">
<Avatar
<Avatar
firstName={att.firstName}
lastName={att.lastName}
></Avatar>
@ -88,17 +116,22 @@ const Regularization = ({ handleRequest }) => {
))
) : (
<tr>
<td colSpan={6}
className="text-center" style={{
<td
colSpan={6}
className="text-center"
style={{
height: "200px",
verticalAlign: "middle",
borderBottom: "none",
}}>No Record Found</td>
}}
>
No Record Found
</td>
</tr>
))}
</tbody>
</table>
{!loading >10 && (
{!loading > 10 && (
<nav aria-label="Page ">
<ul className="pagination pagination-sm justify-content-end py-1">
<li className={`page-item ${currentPage === 1 ? "disabled" : ""}`}>
@ -112,8 +145,9 @@ const Regularization = ({ handleRequest }) => {
{[...Array(totalPages)].map((_, index) => (
<li
key={index}
className={`page-item ${currentPage === index + 1 ? "active" : ""
}`}
className={`page-item ${
currentPage === index + 1 ? "active" : ""
}`}
>
<button
className="page-link "
@ -124,8 +158,9 @@ const Regularization = ({ handleRequest }) => {
</li>
))}
<li
className={`page-item ${currentPage === totalPages ? "disabled" : ""
}`}
className={`page-item ${
currentPage === totalPages ? "disabled" : ""
}`}
>
<button
className="page-link "

View File

@ -1,9 +1,29 @@
import React from "react";
import React, { useCallback, useEffect, useState } from "react";
import { useDashboardTeamsCardData } from "../../hooks/useDashboard_Data";
import eventBus from "../../services/eventBus";
const Teams = () => {
const { teamsCardData } = useDashboardTeamsCardData();
const[totalEmployees,setTotalEmployee] = useState(0);
const[inToday,setInToday] = useState(0);
useEffect(() =>{
setTotalEmployee(teamsCardData.totalEmployees)
setInToday(teamsCardData.inToday)
},[teamsCardData.totalEmployees,teamsCardData.inToday])
const handler = useCallback(
(msg) => {
if (msg.activity == 1) {
setInToday(prev => prev + 1);
}
},
[inToday]
);
useEffect(() => {
eventBus.on("attendance", handler);
return () => eventBus.off("attendance", handler);
}, [handler]);
return (
<div className="card p-3 h-100 text-center d-flex justify-content-between">
<div className="d-flex justify-content-start align-items-center mb-3">
@ -14,13 +34,13 @@ const Teams = () => {
<div className="d-flex justify-content-around align-items-start mt-n2">
<div>
<h4 className="mb-0 fw-bold">
{teamsCardData.totalEmployees?.toLocaleString()}
{totalEmployees?.toLocaleString()}
</h4>
<small className="text-muted">Total Employees</small>
</div>
<div>
<h4 className="mb-0 fw-bold">
{teamsCardData.inToday?.toLocaleString()}
{inToday?.toLocaleString()}
</h4>
<small className="text-muted">In Today</small>
</div>

View File

@ -43,10 +43,8 @@ const AttendancePage = () => {
description: "",
date: new Date().toLocaleDateString(),
});
const handler = useCallback(
(msg) => {
console.log("Equal:", selectedProject == msg.projectId);
if (selectedProject == msg.projectId) {
const updatedAttendance = attendances.map((item) =>
item.employeeId === msg.response.employeeId

View File

@ -3,15 +3,14 @@ import { clearCacheKey, getCachedData } from "../slices/apiDataManager";
import showToast from "./toastService";
import eventBus from "./eventBus";
import { useSelector } from "react-redux";
// const base_Url = process.env.VITE_BASE_URL;
const base_Url = "https://devapi.marcoaiot.com";
const base_Url = process.env.VITE_BASE_URL;
// const base_Url = "https://devapi.marcoaiot.com";
let connection = null;
const targetPath = "";
export function startSignalR(loggedUser) {
var jwtToken = localStorage.getItem("jwtToken");
console.log("token", jwtToken);
connection = new signalR.HubConnectionBuilder()
.withUrl(`${base_Url}/hubs/marco`, {
accessTokenFactory: () => jwtToken,
@ -20,11 +19,25 @@ export function startSignalR(loggedUser) {
})
.withAutomaticReconnect()
.build();
const todayDate = new Date();
const today = new Date(
Date.UTC(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate())
)
.toISOString()
.split("T")[0];
connection.on("Attendance", (data) => {
clearCacheKey("Attendance");
const checkIn = data.response.checkInTime.substring(0, 10);
if (data.loginUserId != loggedUser?.employeeInfo.id) {
eventBus.emit("attendance", data);
if (today === checkIn) {
eventBus.emit("attendance", data);
}
var onlyDate = Number(checkIn.substring(8, 10));
var afterTwoDay = checkIn.substring(0, 8) + (onlyDate + 2).toString().padStart(2, "0");;
if(afterTwoDay <= today && (data.response.activity == 4 || data.response.activity == 5)){
eventBus.emit("regularization", data);
}
eventBus.emit("attendance_log", data);
}
});