Implemented signalR in Employee module

This commit is contained in:
ashutosh.nehete 2025-06-18 11:57:55 +05:30
parent 6f247fb0e9
commit 200ef5ae0a
7 changed files with 136 additions and 14 deletions

View File

@ -6,8 +6,9 @@ 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 DateRangePicker from "../common/DateRangePicker";
import { getCachedData } from "../../slices/apiDataManager"; import { clearCacheKey, getCachedData } from "../../slices/apiDataManager";
import eventBus from "../../services/eventBus"; import eventBus from "../../services/eventBus";
import AttendanceRepository from "../../repositories/AttendanceRepository";
const usePagination = (data, itemsPerPage) => { const usePagination = (data, itemsPerPage) => {
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
@ -177,6 +178,27 @@ const AttendanceLog = ({
return () => eventBus.off("attendance_log", handler); return () => eventBus.off("attendance_log", handler);
}, [handler]); }, [handler]);
const employeeHandler = useCallback(
(msg) => {
const { startDate, endDate } = dateRange;
if (data.some((item) => item.employeeId == msg.employeeId)) {
dispatch(
fetchAttendanceData({
projectId,
fromDate: startDate,
toDate: endDate,
})
)
}
},
[projectId, dateRange,data]
);
useEffect(() => {
eventBus.on("employee", employeeHandler);
return () => eventBus.off("employee", employeeHandler);
}, [employeeHandler]);
return ( return (
<> <>
<div <div

View File

@ -51,6 +51,20 @@ const Regularization = ({ handleRequest }) => {
return () => eventBus.off("regularization", handler); return () => eventBus.off("regularization", handler);
}, [handler]); }, [handler]);
const employeeHandler = useCallback(
(msg) => {
if (regularizes.some((item) => item.employeeId == msg.employeeId)) {
refetch();
}
},
[regularizes]
);
useEffect(() => {
eventBus.on("employee", employeeHandler);
return () => eventBus.off("employee", employeeHandler);
}, [employeeHandler]);
return ( return (
<div <div
className="table-responsive text-nowrap" className="table-responsive text-nowrap"

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from "react"; import React, { useState, useEffect, useRef, useCallback } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { changeMaster } from "../../slices/localVariablesSlice"; import { changeMaster } from "../../slices/localVariablesSlice";
import useMaster from "../../hooks/masterHook/useMaster"; import useMaster from "../../hooks/masterHook/useMaster";
@ -10,6 +10,7 @@ import { useEmployeesAllOrByProjectId } from "../../hooks/useEmployees";
import { TasksRepository } from "../../repositories/ProjectRepository"; import { TasksRepository } from "../../repositories/ProjectRepository";
import showToast from "../../services/toastService"; import showToast from "../../services/toastService";
import { useProjectDetails } from "../../hooks/useProjects"; import { useProjectDetails } from "../../hooks/useProjects";
import eventBus from "../../services/eventBus";
const AssignRoleModel = ({ assignData, onClose, setAssigned }) => { const AssignRoleModel = ({ assignData, onClose, setAssigned }) => {
// Calculate maxPlanned based on assignData // Calculate maxPlanned based on assignData
@ -77,7 +78,7 @@ const AssignRoleModel = ({ assignData, onClose, setAssigned }) => {
const selectedProject = useSelector( const selectedProject = useSelector(
(store) => store.localVariables.projectId (store) => store.localVariables.projectId
); );
const { employees, loading: employeeLoading } = useEmployeesAllOrByProjectId( const { employees, loading: employeeLoading,recallEmployeeData } = useEmployeesAllOrByProjectId(
selectedProject, selectedProject,
false false
); );
@ -188,6 +189,25 @@ const AssignRoleModel = ({ assignData, onClose, setAssigned }) => {
onClose(); onClose();
}; };
const handler = useCallback(
(msg) => {
if(employees.some((item) => item.id == msg.employeeId)){
console.log("handller function start")
clearCacheKey("employeeListByProject");
clearCacheKey("allEmployeeList");
clearCacheKey("allInactiveEmployeeList");
clearCacheKey("employeeProfile");
recallEmployeeData(false);
console.log("handller function end")
}
},[employees]
);
useEffect(() => {
eventBus.on("employee",handler);
return () => eventBus.off("employee",handler)
},[handler])
return ( return (
<div <div
className="modal-dialog modal-lg modal-simple mx-sm-auto mx-1 edit-project-modal" className="modal-dialog modal-lg modal-simple mx-sm-auto mx-1 edit-project-modal"

View File

@ -188,6 +188,19 @@ const Teams = ({ project }) => {
return () => eventBus.off("assign_project_all", handler); return () => eventBus.off("assign_project_all", handler);
}, [handler]); }, [handler]);
const employeeHandler = useCallback(
(msg) => {
if(filteredEmployees.some((item) => item.employeeId == msg.employeeId)){
fetchEmployees();
}
},[filteredEmployees]
);
useEffect(() => {
eventBus.on("employee",employeeHandler);
return () => eventBus.off("employee",employeeHandler)
},[employeeHandler])
return ( return (
<> <>
<div <div

View File

@ -1,6 +1,7 @@
import React, { useState, useEffect, useCallback } from "react"; import React, { useState, useEffect, useCallback } from "react";
import { import {
cacheData, cacheData,
clearCacheKey,
getCachedData, getCachedData,
getCachedProfileData, getCachedProfileData,
} from "../../slices/apiDataManager"; } from "../../slices/apiDataManager";
@ -19,13 +20,14 @@ import { hasUserPermission } from "../../utils/authUtils";
import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { REGULARIZE_ATTENDANCE } from "../../utils/constants"; import { REGULARIZE_ATTENDANCE } from "../../utils/constants";
import eventBus from "../../services/eventBus"; import eventBus from "../../services/eventBus";
import AttendanceRepository from "../../repositories/AttendanceRepository";
const AttendancePage = () => { const AttendancePage = () => {
const [activeTab, setActiveTab] = useState("all"); const [activeTab, setActiveTab] = useState("all");
const [ShowPending, setShowPending] = useState(false); const [ShowPending, setShowPending] = useState(false);
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();
const { const {
attendance, attendance,
loading: attLoading, loading: attLoading,
@ -62,6 +64,22 @@ const AttendancePage = () => {
[selectedProject, attrecall] [selectedProject, attrecall]
); );
const employeeHandler = useCallback(
(msg) => {
if (attendances.some((item) => item.employeeId == msg.employeeId)) {
AttendanceRepository.getAttendance(selectedProject)
.then((response) => {
cacheData("Attendance", { data: response.data, selectedProject });
setAttendances(response.data);
})
.catch((error) => {
console.error(error);
});
}
},
[selectedProject, attendances]
);
const getRole = (roleId) => { const getRole = (roleId) => {
if (!empRoles) return "Unassigned"; if (!empRoles) return "Unassigned";
if (!roleId) return "Unassigned"; if (!roleId) return "Unassigned";
@ -135,13 +153,20 @@ const AttendancePage = () => {
// ) // )
// : attendances; // : attendances;
const filteredAttendance = ShowPending const filteredAttendance = ShowPending
? attendances?.filter((att) => att?.checkInTime !== null && att?.checkOutTime === null) ? attendances?.filter(
(att) => att?.checkInTime !== null && att?.checkOutTime === null
)
: attendances; : attendances;
useEffect(() => { useEffect(() => {
eventBus.on("attendance", handler); eventBus.on("attendance", handler);
return () => eventBus.off("attendance", handler); return () => eventBus.off("attendance", handler);
}, [handler]); }, [handler]);
useEffect(() => {
eventBus.on("employee", employeeHandler);
return () => eventBus.off("employee", employeeHandler);
}, [employeeHandler]);
return ( return (
<> <>
{isCreateModalOpen && modelConfig && ( {isCreateModalOpen && modelConfig && (
@ -242,11 +267,8 @@ const AttendancePage = () => {
</li> </li>
</ul> </ul>
<div className="tab-content attedanceTabs py-0 px-1 px-sm-3"> <div className="tab-content attedanceTabs py-0 px-1 px-sm-3">
{activeTab === "all" && ( {activeTab === "all" && (
<> <>
<div className="tab-pane fade show active py-0"> <div className="tab-pane fade show active py-0">
<Attendance <Attendance
attendance={filteredAttendance} attendance={filteredAttendance}
@ -256,8 +278,13 @@ const AttendancePage = () => {
showOnlyCheckout={ShowPending} showOnlyCheckout={ShowPending}
/> />
</div> </div>
{!attLoading && filteredAttendance?.length === 0 && ( {!attLoading && filteredAttendance?.length === 0 && (
<p> {ShowPending ? "No Pending Available" : "No Employee assigned yet."} </p> <p>
{" "}
{ShowPending
? "No Pending Available"
: "No Employee assigned yet."}{" "}
</p>
)} )}
</> </>
)} )}
@ -279,7 +306,7 @@ const AttendancePage = () => {
</div> </div>
)} )}
{attLoading && <span>Loading..</span>} {attLoading && <span>Loading..</span>}
{!attLoading && !attendances && <span>Not Found</span>} {!attLoading && !attendances && <span>Not Found</span>}
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from "react"; import React, { useState, useEffect, useRef, useCallback } from "react";
import moment from "moment"; import moment from "moment";
import showToast from "../../services/toastService"; import showToast from "../../services/toastService";
import { Link, NavLink, useNavigate } from "react-router-dom"; import { Link, NavLink, useNavigate } from "react-router-dom";
@ -23,6 +23,8 @@ import EmployeeRepository from "../../repositories/EmployeeRepository";
import ManageEmployee from "../../components/Employee/ManageEmployee"; import ManageEmployee from "../../components/Employee/ManageEmployee";
import ConfirmModal from "../../components/common/ConfirmModal"; import ConfirmModal from "../../components/common/ConfirmModal";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import eventBus from "../../services/eventBus";
import { newlineChars } from "pdf-lib";
const EmployeeList = () => { const EmployeeList = () => {
const selectedProjectId = useSelector((store) => store.localVariables.projectId); const selectedProjectId = useSelector((store) => store.localVariables.projectId);
@ -202,7 +204,6 @@ const EmployeeList = () => {
}; };
const handleOpenDelete = (employee) => { const handleOpenDelete = (employee) => {
console.log(employee);
setSelectedEmpFordelete(employee); setSelectedEmpFordelete(employee);
setIsDeleteModalOpen(true); setIsDeleteModalOpen(true);
}; };
@ -218,6 +219,20 @@ const EmployeeList = () => {
setSelectedProject(selectedProjectId || ""); setSelectedProject(selectedProjectId || "");
}, [selectedProjectId]); }, [selectedProjectId]);
const handler = useCallback(
(msg) => {
if(employees.some((item) => item.id == msg.employeeId)){
setEmployeeList([]);
recallEmployeeData(showInactive);
}
},[employees]
);
useEffect(() => {
eventBus.on("employee",handler);
return () => eventBus.off("employee",handler)
},[handler])
return ( return (
<> <>

View File

@ -77,9 +77,20 @@ export function startSignalR(loggedUser) {
} }
// if created or updated infra // if created or updated infra
if (data.keyword == "Infra") { if (data.keyword == "Infra") {
console.log("Infra")
eventBus.emit("infra", data); eventBus.emit("infra", data);
} }
// if created or updated Employee
if (data.keyword == "Employee") {
clearCacheKey("employeeListByProject");
clearCacheKey("allEmployeeList");
clearCacheKey("allInactiveEmployeeList");
clearCacheKey("employeeProfile");
clearCacheKey("Attendance");
clearCacheKey("regularizedList")
clearCacheKey("AttendanceLogs")
eventBus.emit("employee", data);
}
} }
}); });