diff --git a/src/ModalContext.jsx b/src/ModalContext.jsx index fa0f30f8..72607465 100644 --- a/src/ModalContext.jsx +++ b/src/ModalContext.jsx @@ -1,4 +1,10 @@ -import React, { createContext, useContext, useState, useEffect, useRef } from "react"; +import React, { + createContext, + useContext, + useState, + useEffect, + useRef, +} from "react"; const ModalContext = createContext(); @@ -9,12 +15,12 @@ export const ModalProvider = ({ children }) => { const [isOpen, setIsOpen] = useState(false); const [modalContent, setModalContent] = useState(null); const [onSubmit, setOnSubmit] = useState(null); - const [modalSize, setModalSize] = useState('lg'); + const [modalSize, setModalSize] = useState("lg"); // Ref to track the modal content element const modalRef = useRef(null); - const openModal = (content, onSubmitCallback, size = 'lg') => { + const openModal = (content, onSubmitCallback, size = "lg") => { setModalContent(content); // Set modal content dynamically setOnSubmit(() => onSubmitCallback); // Set the submit handler dynamically setIsOpen(true); // Open the modal @@ -26,9 +32,20 @@ export const ModalProvider = ({ children }) => { setIsOpen(false); // Close the modal setModalContent(null); // Clear modal content setOnSubmit(null); // Clear the submit callback - setModalSize('lg'); // Reset modal size + setModalSize("lg"); // Reset modal size }; + useEffect(() => { + const handleEscape = (event) => { + if (event.key === "Escape") { + closeModal(); + } + }; + document.addEventListener("keydown", handleEscape); + return () => { + document.removeEventListener("keydown", handleEscape); + }; + }, []); useEffect(() => { const handleClickOutside = (event) => { @@ -43,14 +60,28 @@ export const ModalProvider = ({ children }) => { }, []); return ( - + {children} {isOpen && (
-
+
{modalContent}
-
)} @@ -77,5 +108,5 @@ const modalStyles = { borderRadius: "5px", boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)", width: "90%", - maxWidth: "800px", + maxWidth: "800px", }; diff --git a/src/components/Activities/AttendcesLogs.jsx b/src/components/Activities/AttendcesLogs.jsx index 71f0c9f8..a18522ed 100644 --- a/src/components/Activities/AttendcesLogs.jsx +++ b/src/components/Activities/AttendcesLogs.jsx @@ -1,18 +1,18 @@ -import React, { useEffect, useState } from 'react'; -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 React, { useEffect, useState } from "react"; +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"; const AttendanceLog = ({ attendance, handleModalData, projectId }) => { const [attendances, setAttendnaces] = useState([]); - const [selectedDate, setSelectedDate] = useState(''); + const [selectedDate, setSelectedDate] = useState(""); const dispatch = useDispatch(); - const { data, loading, error } = useSelector((store) => store.attendanceLogs); + 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().toISOString().split("T")[0]; // "YYYY-MM-DD" const handleDateChange = (e) => { const date = e.target.value; @@ -28,11 +28,15 @@ const AttendanceLog = ({ attendance, handleModalData, projectId }) => { setSelectedDate(currentDate); // Set default selected date to today }, [attendance]); - const renderAttendanceData = selectedDate === currentDate ? attendances : data; + const renderAttendanceData = + selectedDate === currentDate ? attendances : data; return ( <> -
+
{ - - + + } {error && } {selectedDate && renderAttendanceData.length === 0 && ( - + + + )} {renderAttendanceData?.map((attendance, index) => ( - - + - + } + {regularizes?.length > 0 ? ( + regularizes?.map((att, index) => ( + + + + + + + + )) + ) : ( + + + + )} + +
NameRole + Name + Role - Check-In + {" "} + Check-In Check-Out @@ -65,14 +72,19 @@ const AttendanceLog = ({ attendance, handleModalData, projectId }) => { {loading && Loading...{error}No Data Found
No Data Found
+ { attendance.jobRoleName}{attendance.jobRoleName} {convertShortTime(attendance.checkInTime)}{attendance.checkOutTime ? convertShortTime(attendance.checkOutTime) : '--'} + {attendance.checkOutTime + ? convertShortTime(attendance.checkOutTime) + : "--"} + { + var selectedProject = useSelector((store) => store.localVariables.projectId); + const [regularizesList, setregularizedList] = useState([]); + const { regularizes, loading, error, refetch } = + useRegularizationRequests(selectedProject); -const Regularization = ( { handleRequest} ) => -{ - var selectedProject = useSelector((store) => store.localVariables.projectId); - const [ regularizesList, setregularizedList ] = useState( [] ) - const { regularizes, loading,error,refetch} = useRegularizationRequests(selectedProject) - - + useEffect(() => { + setregularizedList(regularizes); + }, [regularizes]); - useEffect(()=>{ - setregularizedList(regularizes) - },[regularizes]) - return ( -
- - - - - - - - - - +
+
NameDateCheck-InCheck-OutAction
+ + + + + + + + + - - {loading &&} - { - regularizes?.length > 0 ? ( - regularizes?.map((att, index) => ( - - - - - - - - )) - ):( - - ) - } - -
NameDate + Check-In + + Check-Out + Action
Loading...
- - {moment(att.checkOutTime).format("DD-MMM-YYYY")}{convertShortTime(att.checkInTime)}{att.checkOutTime ? convertShortTime(att.checkOutTime):"--"} - {/*
*/} - - {/*
*/} -
No Record Found
-
+ {loading &&
Loading...
+ + {moment(att.checkOutTime).format("DD-MMM-YYYY")}{convertShortTime(att.checkInTime)} + {att.checkOutTime ? convertShortTime(att.checkOutTime) : "--"} + + {/*
*/} + + {/*
*/} +
No Record Found
+
); }; -export default Regularization +export default Regularization; diff --git a/src/components/common/Breadcrumb.jsx b/src/components/common/Breadcrumb.jsx index f45804df..6c803be6 100644 --- a/src/components/common/Breadcrumb.jsx +++ b/src/components/common/Breadcrumb.jsx @@ -1,23 +1,29 @@ import React from "react"; -import {useNavigate} from "react-router-dom"; +import { useNavigate } from "react-router-dom"; const Breadcrumb = ({ data }) => { - const navigate = useNavigate() + const navigate = useNavigate(); return (
)} diff --git a/src/pages/employee/EmployeeList.jsx b/src/pages/employee/EmployeeList.jsx index 3b4babb4..ab780481 100644 --- a/src/pages/employee/EmployeeList.jsx +++ b/src/pages/employee/EmployeeList.jsx @@ -12,9 +12,7 @@ import { MANAGE_EMPLOYEES } from "../../utils/constants"; import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import SuspendEmp from "../../components/Employee/SuspendEmp"; -const EmployeeList = () => -{ - +const EmployeeList = () => { const { profile: loginUser } = useProfile(); const [selectedProject, setSelectedProject] = useState(""); const { projects, loading: projectLoading } = useProjects(); @@ -30,7 +28,7 @@ const EmployeeList = () => const [itemsPerPage] = useState(10); const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); const [searchText, setSearchText] = useState(""); - const [ filteredData, setFilteredData ] = useState( [] ); + const [filteredData, setFilteredData] = useState([]); const [showModal, setShowModal] = useState(false); const navigate = useNavigate(); @@ -59,7 +57,7 @@ const EmployeeList = () => const nameB = `${b.firstName || ""}${b.lastName || ""}`.toLowerCase(); return nameA.localeCompare(nameB); }); - + setEmployeeList(sorted); setFilteredData(sorted); } @@ -92,8 +90,8 @@ const EmployeeList = () => } }; const handleShow = () => setShowModal(true); - const handleClose = () => setShowModal( false ); - + const handleClose = () => setShowModal(false); + const handleConfigData = (config) => { setModelConfig(config); }; @@ -109,15 +107,15 @@ const EmployeeList = () => {isCreateModalOpen && ( )} - -
- +
@@ -329,130 +327,134 @@ const EmployeeList = () => )} {!loading && employeeList?.length === 0 && ( - - No Data Found - + + + No Data Found + + )} {!loading && employeeList && currentItems.length === 0 && employeeList.length !== 0 && ( - - - '{searchText}' employee not found - {" "} - + + + + '{searchText}' employee not found + {" "} + + )} {currentItems && !loading && - currentItems - .map((item) => ( - - -
- -
- ( + + + + + + {item.email ? ( + + + + {item.email} + + ) : ( + + NA + + )} + + + + + {item.phoneNumber} + + + + + + {item.jobRole || "Not Assign Yet"} + + + + + {moment(item.joiningDate).format("DD-MMM-YYYY")} + + + + Active + + + {ManageEmployee && ( + +
+ +
+ + + Edit + + +
- - {item.email ? ( - - - - {item.email} - - ) : ( - - NA - - )} - - - - - {item.phoneNumber} - - - - - - {item.jobRole || "Not Assign Yet"} - - - - - {moment(item.joiningDate).format("DD-MMM-YYYY")} - - - - Active - - - {ManageEmployee && ( - -
- -
- - - Edit - - - -
-
- - )} - - ))} + )} + + ))} diff --git a/src/router/AppRoutes.jsx b/src/router/AppRoutes.jsx index 9221851f..63db879b 100644 --- a/src/router/AppRoutes.jsx +++ b/src/router/AppRoutes.jsx @@ -1,92 +1,96 @@ +// AppRoutes.jsx import React from "react"; -import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; -import AuthLayout from "../layouts/AuthLayout" +import { createBrowserRouter, RouterProvider, Outlet } from "react-router-dom"; + +// Layouts +import AuthLayout from "../layouts/AuthLayout"; import HomeLayout from "../layouts/HomeLayout"; + +// Authentication Pages import LoginPage from "../pages/authentication/LoginPage"; import RegisterPage from "../pages/authentication/RegisterPage"; import ForgotPasswordPage from "../pages/authentication/ForgotPasswordPage"; import ResetPasswordPage from "../pages/authentication/ResetPasswordPage"; +// Home & Protected Pages import Dashboard from "../components/Dashboard/Dashboard"; import ProjectList from "../pages/project/ProjectList"; -import EmployeeList from "../pages/employee/EmployeeList"; -import NotFound from "../pages/Home/NotFound"; -import ProtectedRoute from "./ProtectedRoute"; import ProjectDetails from "../pages/project/ProjectDetails"; +import ManageProject from "../components/Project/ManageProject"; +import EmployeeList from "../pages/employee/EmployeeList"; +import ManageEmp from "../pages/employee/ManageEmp"; +import EmployeeProfile from "../pages/employee/EmployeeProfile"; import Inventory from "../pages/project/Inventory"; +import AttendancePage from "../pages/Activities/AttendancePage"; +import DailyTask from "../pages/Activities/DailyTask"; import TaskPlannng from "../pages/Activities/TaskPlannng"; import Reports from "../pages/reports/Reports"; import ImageGallary from "../pages/Gallary/ImageGallary"; +import MasterPage from "../pages/master/MasterPage"; import Support from "../pages/support/Support"; import Documentation from "../pages/support/Documentation"; import Connect from "../pages/support/Connect"; -import ManageProject from "../components/Project/ManageProject"; -import ManageEmp from "../pages/employee/ManageEmp"; -import EmployeeProfile from "../pages/employee/EmployeeProfile"; import { ErrorPage } from "../pages/support/ErrorPage"; -import MasterPage from "../pages/master/MasterPage"; -import DailyTask from "../pages/Activities/DailyTask"; -import AttendancePage from "../pages/Activities/AttendancePage"; +// Protected Route Wrapper +import ProtectedRoute from "./ProtectedRoute"; + +const router = createBrowserRouter( + [ + { + element: , + children: [ + { path: "/auth/login", element: }, + { path: "/auth/reqest/demo", element: }, + { path: "/auth/forgot-password", element: }, + { path: "/reset-password", element: }, + ], + }, + { + element: , + children: [ + { + element: , + children: [ + { path: "/", element: }, + { path: "/dashboard", element: }, + { path: "/projects", element: }, + { path: "/projects/:projectId", element: }, + { path: "/project/manage/:projectId", element: }, + { path: "/employees", element: }, + { path: "/employee/:employeeId", element: }, + { path: "/employee/manage", element: }, + { path: "/employee/manage/:employeeId", element: }, + { path: "/inventory", element: }, + { path: "/activities/attendance", element: }, + { path: "/activities/records", element: }, + { path: "/activities/task", element: }, + { path: "/activities/reports", element: }, + { path: "/activities/gallary", element: }, + { path: "/masters", element: }, + { path: "/help/support", element: }, + { path: "/help/docs", element: }, + { path: "/help/connect", element: }, + ], + }, + ], + }, + { + path: "*", + element: , + }, + ], + { + // ✅ Enables the v7 splat path resolution behavior + future: { + v7_relativeSplatPath: true, + v7_startTransition: true, + }, + } +); const AppRoutes = () => { - return ( - - - {/* Authentication Routes */} - }> - } /> - } /> - } - /> - } /> - - - - {/* Protected Routes */} - }> - }> - } /> - } /> - } /> - } /> - } - /> - } /> - } /> - - } /> - } - /> - } /> - - } /> - - } /> - } /> - - } /> - - } /> - } /> - - } /> - } /> - } /> - - - - {/* Fallback Route */} - } /> - - - ); + return ; }; export default AppRoutes; diff --git a/src/utils/axiosClient.jsx b/src/utils/axiosClient.jsx index 04bf60d8..99eaee6f 100644 --- a/src/utils/axiosClient.jsx +++ b/src/utils/axiosClient.jsx @@ -3,7 +3,7 @@ import { useNavigate } from "react-router-dom"; import axiosRetry from "axios-retry"; import showToast from "../services/toastService"; const base_Url = process.env.VITE_BASE_URL; -// const base_Url = https://api.marcoaiot.com; +// const base_Url = "https://api.marcoaiot.com"; export const axiosClient = axios.create({ baseURL: base_Url, // Your Web API URL withCredentials: false, // Required if the API uses cookies @@ -31,11 +31,8 @@ axiosClient.interceptors.request.use( // // Response interceptor to handle responses globally (optional) // Add an interceptor to handle expired tokens axiosClient.interceptors.response.use( - - (response) => response, async (error) => { - const originalRequest = error.config; if (!originalRequest) { @@ -50,47 +47,47 @@ axiosClient.interceptors.response.use( console.error( "Connection refused. Please ensure the server is running." ); - - if ( error.config.url.indexOf( 'refresh-token' ) == -1 ) - { - showToast("Server is unreachable. Try again later!", "error"); - } - showToast( - "Unable to connect to the server. Please try again later.", - "error" - ); + + if (error.config.url.indexOf("refresh-token") == -1) { + //showToast("Server is unreachable. Try again later!", "error"); + console.log("1 - error fetching refresh token :", error); + } else { + showToast( + "Unable to connect to the server. Please try again later.", + "error" + ); + } } else if (error.code === "ERR_NETWORK") { - console.error( "Network error: Unable to reach the server." ); - if ( error.config.url.indexOf( 'refresh-token' ) == -1 ) - { - showToast("Server is unreachable. Try again later!", "error"); + console.error("Network error: Unable to reach the server."); + if (error.config.url.indexOf("refresh-token") == -1) { + //showToast("Server is unreachable. Try again later!", "error"); + console.log("2 - error fetching refresh token :", error); } redirectToLogin(); } else if (error.code === "ECONNABORTED") { - console.error( "Request timed out." ); - - if ( error.config.url.indexOf( 'refresh-token' ) == -1 ) - { - showToast("Server is unreachable. Try again later!", "error"); - } - showToast( - "The request took too long. Please try again later.", - "error" - ); - } else if ( error.response ) - { - - if ( error.config.url.indexOf( 'refresh-token' ) == -1 ) - { - showToast("Server is unreachable. Try again later!", "error"); - } - showToast(error.response.data.message, "error"); + console.error("Request timed out."); + + if (error.config.url.indexOf("refresh-token") == -1) { + //showToast("Server is unreachable. Try again later!", "error"); + console.log("3 - error fetching refresh token :", error); + } else { + showToast( + "The request took too long. Please try again later.", + "error" + ); + } + } else if (error.response) { + if (error.config.url.indexOf("refresh-token") == -1) { + //showToast("Server is unreachable. Try again later!", "error"); + console.log("4 - error fetching refresh token :", error); + } else { + showToast(error.response.data.message, "error"); + } if (error.response.status === 401 && !originalRequest._retry) { originalRequest._retry = true; try { - // Get the refresh token from secure storage const refreshToken = localStorage.getItem("refreshToken"); @@ -115,11 +112,19 @@ axiosClient.interceptors.response.use( // Retry the original request return axiosClient(originalRequest); } catch (err) { + console.log( + "5 - error fetching refresh token during refresh call :", + error + ); // Redirect to login if token refresh fails redirectToLogin(); return Promise.reject(err); } } else { + if (error.config.url.indexOf("refresh-token") == -1) { + //showToast("Server is unreachable. Try again later!", "error"); + console.log("6 - error fetching refresh token :", error); + } showToast( error.response.data?.message || "An error occurred. Please try again.",