Remove warnings

This commit is contained in:
Vikas Nale 2025-04-17 17:29:18 +05:30
parent 83b6c2a307
commit 1418f84976
8 changed files with 487 additions and 417 deletions

View File

@ -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 (
<ModalContext.Provider value={{ isOpen, openModal, closeModal, modalContent, modalSize, onSubmit }}>
<ModalContext.Provider
value={{
isOpen,
openModal,
closeModal,
modalContent,
modalSize,
onSubmit,
}}
>
{children}
{isOpen && (
<div style={overlayStyles}>
<div ref={modalRef} style={{ ...modalStyles, maxWidth: modalSize === 'sm' ? '400px' : '800px' }}>
<div
ref={modalRef}
style={{
...modalStyles,
maxWidth: modalSize === "sm" ? "400px" : "800px",
}}
>
<div>{modalContent}</div>
</div>
</div>
)}
@ -77,5 +108,5 @@ const modalStyles = {
borderRadius: "5px",
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
width: "90%",
maxWidth: "800px",
maxWidth: "800px",
};

View File

@ -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 (
<>
<div className="dataTables_length text-start py-2" id="DataTables_Table_0_length">
<div
className="dataTables_length text-start py-2"
id="DataTables_Table_0_length"
>
<div className="col-md-3">
<input
className="form-control form-control-sm"
@ -50,10 +54,13 @@ const AttendanceLog = ({ attendance, handleModalData, projectId }) => {
<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" colSpan={2}>
Name
</th>
<th className="border-top-1">Role</th>
<th>
<i className="bx bxs-down-arrow-alt text-success"></i> Check-In
<i className="bx bxs-down-arrow-alt text-success"></i>{" "}
Check-In
</th>
<th>
<i className="bx bxs-up-arrow-alt text-danger"></i> Check-Out
@ -65,14 +72,19 @@ const AttendanceLog = ({ attendance, handleModalData, projectId }) => {
{loading && <td colSpan={5}>Loading...</td>}
{error && <td colSpan={5}>{error}</td>}
{selectedDate && renderAttendanceData.length === 0 && (
<td colSpan={5}>No Data Found</td>
<tr>
<td colSpan={5}>No Data Found</td>
</tr>
)}
{renderAttendanceData?.map((attendance, index) => (
<tr key={index}>
<td colSpan={2}>
<td colSpan={2}>
<div className="d-flex justify-content-start align-items-center">
<Avatar firstName={attendance.firstName} lastName={attendance.lastName} />
<Avatar
firstName={attendance.firstName}
lastName={attendance.lastName}
/>
<div className="d-flex flex-column">
<a href="#" className="text-heading text-truncate">
<span className="fw-medium">
@ -82,9 +94,13 @@ const AttendanceLog = ({ attendance, handleModalData, projectId }) => {
</div>
</div>
</td>
<td>{ attendance.jobRoleName}</td>
<td>{attendance.jobRoleName}</td>
<td>{convertShortTime(attendance.checkInTime)}</td>
<td>{attendance.checkOutTime ? convertShortTime(attendance.checkOutTime) : '--'}</td>
<td>
{attendance.checkOutTime
? convertShortTime(attendance.checkOutTime)
: "--"}
</td>
<td className="text-center">
<RenderAttendanceStatus
attendanceData={attendance}

View File

@ -1,79 +1,82 @@
import React, { useEffect, useState } from 'react';
import Avatar from '../common/Avatar';
import { convertShortTime } from '../../utils/dateUtils';
import RegularizationActions from './RegularizationActions';
import {useSelector} from 'react-redux';
import {useRegularizationRequests} from '../../hooks/useAttendance';
import moment from 'moment';
import React, { useEffect, useState } from "react";
import Avatar from "../common/Avatar";
import { convertShortTime } from "../../utils/dateUtils";
import RegularizationActions from "./RegularizationActions";
import { useSelector } from "react-redux";
import { useRegularizationRequests } from "../../hooks/useAttendance";
import moment from "moment";
const Regularization = ({ handleRequest }) => {
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 (
<div className="table-responsive text-nowrap">
<table className="table mb-0">
<thead>
<tr>
<th colSpan={2}>Name</th>
<th>Date</th>
<th><i className='bx bxs-down-arrow-alt text-success' ></i>Check-In</th>
<th><i className='bx bxs-up-arrow-alt text-danger' ></i>Check-Out</th>
<th>Action</th>
</tr>
</thead>
<div className="table-responsive text-nowrap">
<table className="table mb-0">
<thead>
<tr>
<th colSpan={2}>Name</th>
<th>Date</th>
<th>
<i className="bx bxs-down-arrow-alt text-success"></i>Check-In
</th>
<th>
<i className="bx bxs-up-arrow-alt text-danger"></i>Check-Out
</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{loading &&<td colSpan={5}>Loading...</td>}
{
regularizes?.length > 0 ? (
regularizes?.map((att, index) => (
<tr key={index}>
<td colSpan={2}>
<div className="d-flex justify-content-start align-items-center">
<Avatar
firstName={att.firstName}
lastName={att.lastName}
></Avatar>
<div className="d-flex flex-column">
<a
href="#"
className="text-heading text-truncate"
>
<span className="fw-medium">
{att.firstName} {att.lastName}
</span>
</a>
</div>
</div>
</td>
<td>{moment(att.checkOutTime).format("DD-MMM-YYYY")}</td>
<td>{convertShortTime(att.checkInTime)}</td>
<td>{att.checkOutTime ? convertShortTime(att.checkOutTime):"--"}</td>
<td className='text-center ' >
{/* <div className='d-flex justify-content-center align-items-center gap-3'> */}
<RegularizationActions attendanceData={att} handleRequest={handleRequest} refresh={refetch } />
{/* </div> */}
</td>
</tr>
))
):(
<td colSpan={5}>No Record Found</td>
)
}
</tbody>
</table>
</div>
{loading && <td colSpan={5}>Loading...</td>}
{regularizes?.length > 0 ? (
regularizes?.map((att, index) => (
<tr key={index}>
<td colSpan={2}>
<div className="d-flex justify-content-start align-items-center">
<Avatar
firstName={att.firstName}
lastName={att.lastName}
></Avatar>
<div className="d-flex flex-column">
<a href="#" className="text-heading text-truncate">
<span className="fw-medium">
{att.firstName} {att.lastName}
</span>
</a>
</div>
</div>
</td>
<td>{moment(att.checkOutTime).format("DD-MMM-YYYY")}</td>
<td>{convertShortTime(att.checkInTime)}</td>
<td>
{att.checkOutTime ? convertShortTime(att.checkOutTime) : "--"}
</td>
<td className="text-center ">
{/* <div className='d-flex justify-content-center align-items-center gap-3'> */}
<RegularizationActions
attendanceData={att}
handleRequest={handleRequest}
refresh={refetch}
/>
{/* </div> */}
</td>
</tr>
))
) : (
<tr>
<td colSpan={5}>No Record Found</td>
</tr>
)}
</tbody>
</table>
</div>
);
};
export default Regularization
export default Regularization;

View File

@ -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 (
<nav aria-label="breadcrumb">
<ol className="breadcrumb breadcrumb-style1">
{data.map((item,index) =>
{data.map((item, index) =>
item.link ? (
<li className="breadcrumb-item cursor-pointer" key={index}>
<a
aria-label="pagination link link-underline-primary "
onClick={()=>navigate(item.link)}
onClick={() => navigate(item.link)}
>
{item.label}
</a>
</li>
) : (
<li className="breadcrumb-item active "> {item.label}</li>
<li
className="breadcrumb-item active "
key={new Date().getMilliseconds()}
>
{" "}
{item.label}
</li>
)
)}
</ol>

View File

@ -23,8 +23,8 @@ const AttendancePage = () => {
const loginUser = getCachedProfileData();
var selectedProject = useSelector((store) => store.localVariables.projectId);
const { projects, loading: projectLoading } = useProjects();
const {attendance, loading: attLoading} = useAttendace( selectedProject );
const [ attendances, setAttendances ] = useState();
const { attendance, loading: attLoading } = useAttendace(selectedProject);
const [attendances, setAttendances] = useState();
const [empRoles, setEmpRoles] = useState(null);
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
const [modelConfig, setModelConfig] = useState();
@ -32,12 +32,11 @@ const AttendancePage = () => {
const dispatch = useDispatch();
const [formData, setFormData] = useState({
markTime: "",
description: "",
date: new Date().toLocaleDateString(),
});
markTime: "",
description: "",
date: new Date().toLocaleDateString(),
});
const getRole = (roleId) => {
if (!empRoles) return "Unassigned";
if (!roleId) return "Unassigned";
@ -49,9 +48,7 @@ const AttendancePage = () => {
setIsCreateModalOpen(true);
};
const handleModalData = ( employee ) =>
{
const handleModalData = (employee) => {
setModelConfig(employee);
};
@ -66,26 +63,25 @@ const AttendancePage = () => {
document.querySelector(".modal-backdrop").remove();
}
};
const handleSubmit = ( formData ) =>
{
dispatch( markCurrentAttendance( formData ) ).then( ( action ) =>
{
const updatedAttendance = attendances.map(item =>
item.employeeId === action.payload.employeeId
? { ...item, ...action.payload }
: item
);
cacheData("Attendance", { data: updatedAttendance, projectId: selectedProject })
setAttendances(updatedAttendance)
showToast("Attedance Marked Successfully","success")
})
.catch( ( error ) =>
{
showToast(error.message,"error")
});
const handleSubmit = (formData) => {
dispatch(markCurrentAttendance(formData))
.then((action) => {
const updatedAttendance = attendances.map((item) =>
item.employeeId === action.payload.employeeId
? { ...item, ...action.payload }
: item
);
cacheData("Attendance", {
data: updatedAttendance,
projectId: selectedProject,
});
setAttendances(updatedAttendance);
showToast("Attedance Marked Successfully", "success");
})
.catch((error) => {
showToast(error.message, "error");
});
};
useEffect(() => {
@ -94,14 +90,12 @@ const AttendancePage = () => {
}
}, [modelConfig, isCreateModalOpen]);
useEffect(() => {
setAttendances( attendance );
setAttendances(attendance);
}, [attendance]);
useEffect(() => {
dispatch(setProjectId(projects[0]?.id));
}, [projects]);
return (
<>
{isCreateModalOpen && modelConfig && (
@ -126,59 +120,71 @@ const AttendancePage = () => {
{ label: "Home", link: "/dashboard" },
{ label: "Attendance", link: null },
]}
></Breadcrumb>
<div class="nav-align-top nav-tabs-shadow">
<ul class="nav nav-tabs" role="tablist">
<div
className="dataTables_length text-start py-2 px-2"
id="DataTables_Table_0_length"
>
{
((loginUser && loginUser?.projects?.length > 1) ) && (<label>
<select
name="DataTables_Table_0_length"
aria-controls="DataTables_Table_0"
className="form-select form-select-sm"
value={selectedProject}
onChange={(e)=>dispatch(setProjectId(e.target.value))}
aria-label=""
></Breadcrumb>
<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"
id="DataTables_Table_0_length"
>
{loginUser && loginUser?.projects?.length > 1 && (
<label>
<select
name="DataTables_Table_0_length"
aria-controls="DataTables_Table_0"
className="form-select form-select-sm"
value={selectedProject}
onChange={(e) => dispatch(setProjectId(e.target.value))}
aria-label=""
>
{!projectLoading &&
projects
?.filter((project) =>
loginUser?.projects?.map(Number).includes(project.id)
)
.map((project) => (
<option value={project.id} key={project.id}>
{project.name}
</option>
))}
{projectLoading && (
<option value="Loading..." disabled>
Loading...
</option>
)}
</select>
</label>
)}
</div>
</ul>
<ul className="nav nav-tabs" role="tablist">
<li className="nav-item">
<button
type="button"
className="nav-link active"
role="tab"
data-bs-toggle="tab"
data-bs-target="#navs-top-home"
aria-controls="navs-top-home"
aria-selected="true"
>
{!projectLoading && projects?.filter(project =>
loginUser?.projects?.map(Number).includes(project.id)).map((project)=>(
<option value={project.id} key={project.id}>{project.name}</option>
))}
{projectLoading && <option value="Loading..." disabled>Loading...</option> }
</select>
</label>)
}
</div>
</ul>
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<button
type="button"
class="nav-link active"
role="tab"
data-bs-toggle="tab"
data-bs-target="#navs-top-home"
aria-controls="navs-top-home"
aria-selected="true">
All
</button>
</li>
<li class="nav-item">
<button
type="button"
class="nav-link"
role="tab"
data-bs-toggle="tab"
data-bs-target="#navs-top-profile"
aria-controls="navs-top-profile"
aria-selected="false">
Logs
</button>
</li>
<li className={`nav-item ${!DoRegularized && 'd-none'}`}>
All
</button>
</li>
<li className="nav-item">
<button
type="button"
className="nav-link"
role="tab"
data-bs-toggle="tab"
data-bs-target="#navs-top-profile"
aria-controls="navs-top-profile"
aria-selected="false"
>
Logs
</button>
</li>
<li className={`nav-item ${!DoRegularized && "d-none"}`}>
<button
type="button"
className="nav-link "
@ -225,10 +231,7 @@ const AttendancePage = () => {
id="navs-top-messages"
role="tabpanel"
>
<Regularization
handleRequest={handleSubmit}
/>
<Regularization handleRequest={handleSubmit} />
</div>
</>
)}

View File

@ -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 && (
<ManageEmp employeeId={modelConfig} onClosed={closeModal} />
)}
<div
className={`modal fade ${showModal ? 'show' : ''}`}
<div
className={`modal fade ${showModal ? "show" : ""}`}
tabIndex="-1"
role="dialog"
style={{ display: showModal ? 'block' : 'none' }}
style={{ display: showModal ? "block" : "none" }}
aria-hidden={!showModal}
>
<SuspendEmp onClose={handleClose}/>
<SuspendEmp onClose={handleClose} />
</div>
<div className="container-xxl flex-grow-1 container-p-y">
@ -329,130 +327,134 @@ const EmployeeList = () =>
</tr>
)}
{!loading && employeeList?.length === 0 && (
<td
colSpan={8}
style={{ paddingTop: "20px", textAlign: "center" }}
>
No Data Found
</td>
<tr>
<td
colSpan={8}
style={{ paddingTop: "20px", textAlign: "center" }}
>
No Data Found
</td>
</tr>
)}
{!loading &&
employeeList &&
currentItems.length === 0 &&
employeeList.length !== 0 && (
<td colSpan={8}>
<small className="muted">
'{searchText}' employee not found
</small>{" "}
</td>
<tr>
<td colSpan={8}>
<small className="muted">
'{searchText}' employee not found
</small>{" "}
</td>
</tr>
)}
{currentItems &&
!loading &&
currentItems
.map((item) => (
<tr className="odd" key={item.id}>
<td className="sorting_1" colSpan={2}>
<div className="d-flex justify-content-start align-items-center user-name">
<Avatar
firstName={item.firstName}
lastName={item.lastName}
></Avatar>
<div className="d-flex flex-column">
<a
currentItems.map((item) => (
<tr className="odd" key={item.id}>
<td className="sorting_1" colSpan={2}>
<div className="d-flex justify-content-start align-items-center user-name">
<Avatar
firstName={item.firstName}
lastName={item.lastName}
></Avatar>
<div className="d-flex flex-column">
<a
onClick={() =>
navigate(`/employee/${item.id}?for=account`)
}
className="text-heading text-truncate cursor-pointer"
>
<span className="fw-medium">
{item.firstName} {item.lastName}
</span>
</a>
</div>
</div>
</td>
<td className="text-start d-none d-sm-table-cell">
{item.email ? (
<span className="text-truncate">
<i className="bx bxs-envelope text-primary me-2"></i>
{item.email}
</span>
) : (
<span className="text-truncate text-italic">
NA
</span>
)}
</td>
<td className="text-start d-none d-sm-table-cell">
<span className="text-truncate">
<i className="bx bxs-phone-call text-primary me-2"></i>
{item.phoneNumber}
</span>
</td>
<td className=" d-none d-sm-table-cell text-start">
<span className="text-truncate">
<i className="bx bxs-wrench text-success me-2"></i>
{item.jobRole || "Not Assign Yet"}
</span>
</td>
<td className=" d-none d-md-table-cell">
{moment(item.joiningDate).format("DD-MMM-YYYY")}
</td>
<td>
<span
className="badge bg-label-success"
text-capitalized=""
>
Active
</span>
</td>
{ManageEmployee && (
<td className="text-end">
<div className="dropdown">
<button
className="btn btn-icon dropdown-toggle hide-arrow"
data-bs-toggle="dropdown"
>
<i className="bx bx-dots-vertical-rounded bx-md"></i>
</button>
<div className="dropdown-menu dropdown-menu-end">
<button
onClick={() =>
navigate(
`/employee/${item.id}?for=account`
)
navigate(`/employee/${item.id}`)
}
className="text-heading text-truncate cursor-pointer"
className="dropdown-item"
>
<span className="fw-medium">
{item.firstName} {item.lastName}
</span>
</a>
View
</button>
<Link
to={`/employee/manage/${item.id}`}
className="dropdown-item"
>
Edit
</Link>
<button
className="dropdown-item"
onClick={handleShow}
>
Suspend
</button>
<button
className="dropdown-item"
type="button"
data-bs-toggle="modal"
data-bs-target="#managerole-modal"
onClick={() => handleConfigData(item.id)}
>
Manage Role
</button>
</div>
</div>
</td>
<td className="text-start d-none d-sm-table-cell">
{item.email ? (
<span className="text-truncate">
<i className="bx bxs-envelope text-primary me-2"></i>
{item.email}
</span>
) : (
<span className="text-truncate text-italic">
NA
</span>
)}
</td>
<td className="text-start d-none d-sm-table-cell">
<span className="text-truncate">
<i className="bx bxs-phone-call text-primary me-2"></i>
{item.phoneNumber}
</span>
</td>
<td className=" d-none d-sm-table-cell text-start">
<span className="text-truncate">
<i className="bx bxs-wrench text-success me-2"></i>
{item.jobRole || "Not Assign Yet"}
</span>
</td>
<td className=" d-none d-md-table-cell">
{moment(item.joiningDate).format("DD-MMM-YYYY")}
</td>
<td>
<span
className="badge bg-label-success"
text-capitalized=""
>
Active
</span>
</td>
{ManageEmployee && (
<td className="text-end">
<div className="dropdown">
<button
className="btn btn-icon dropdown-toggle hide-arrow"
data-bs-toggle="dropdown"
>
<i className="bx bx-dots-vertical-rounded bx-md"></i>
</button>
<div className="dropdown-menu dropdown-menu-end">
<button
onClick={() =>
navigate(`/employee/${item.id}`)
}
className="dropdown-item"
>
View
</button>
<Link
to={`/employee/manage/${item.id}`}
className="dropdown-item"
>
Edit
</Link>
<button className="dropdown-item" onClick={handleShow}>
Suspend
</button>
<button
className="dropdown-item"
type="button"
data-bs-toggle="modal"
data-bs-target="#managerole-modal"
onClick={() => handleConfigData(item.id)}
>
Manage Role
</button>
</div>
</div>
</td>
)}
</tr>
))}
)}
</tr>
))}
</tbody>
</table>

View File

@ -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: <AuthLayout />,
children: [
{ path: "/auth/login", element: <LoginPage /> },
{ path: "/auth/reqest/demo", element: <RegisterPage /> },
{ path: "/auth/forgot-password", element: <ForgotPasswordPage /> },
{ path: "/reset-password", element: <ResetPasswordPage /> },
],
},
{
element: <ProtectedRoute />,
children: [
{
element: <HomeLayout />,
children: [
{ path: "/", element: <Dashboard /> },
{ path: "/dashboard", element: <Dashboard /> },
{ path: "/projects", element: <ProjectList /> },
{ path: "/projects/:projectId", element: <ProjectDetails /> },
{ path: "/project/manage/:projectId", element: <ManageProject /> },
{ path: "/employees", element: <EmployeeList /> },
{ path: "/employee/:employeeId", element: <EmployeeProfile /> },
{ path: "/employee/manage", element: <ManageEmp /> },
{ path: "/employee/manage/:employeeId", element: <ManageEmp /> },
{ path: "/inventory", element: <Inventory /> },
{ path: "/activities/attendance", element: <AttendancePage /> },
{ path: "/activities/records", element: <DailyTask /> },
{ path: "/activities/task", element: <TaskPlannng /> },
{ path: "/activities/reports", element: <Reports /> },
{ path: "/activities/gallary", element: <ImageGallary /> },
{ path: "/masters", element: <MasterPage /> },
{ path: "/help/support", element: <Support /> },
{ path: "/help/docs", element: <Documentation /> },
{ path: "/help/connect", element: <Connect /> },
],
},
],
},
{
path: "*",
element: <ErrorPage />,
},
],
{
// Enables the v7 splat path resolution behavior
future: {
v7_relativeSplatPath: true,
v7_startTransition: true,
},
}
);
const AppRoutes = () => {
return (
<Router>
<Routes>
{/* Authentication Routes */}
<Route element={<AuthLayout />}>
<Route path="/auth/login" element={<LoginPage />} />
<Route path="/auth/reqest/demo" element={<RegisterPage />} />
<Route
path="/auth/forgot-password"
element={<ForgotPasswordPage />}
/>
<Route path="/reset-password" element={<ResetPasswordPage />} />
</Route>
{/* Protected Routes */}
<Route element={<ProtectedRoute />}>
<Route element={<HomeLayout />}>
<Route path="/" element={<Dashboard />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/projects" element={<ProjectList />} />
<Route path="/projects/:projectId" element={<ProjectDetails />} />
<Route
path="/project/manage/:projectId"
element={<ManageProject />}
/>
<Route path="/employees" element={<EmployeeList />} />
<Route path="/employee/:employeeId" element={<EmployeeProfile />} />
<Route path="/employee/manage" element={<ManageEmp />} />
<Route
path="/employee/manage/:employeeId"
element={<ManageEmp />}
/>
<Route path="/inventory" element={<Inventory />} />
<Route path="/activities/attendance" element={<AttendancePage />} />
<Route path="/activities/records" element={<DailyTask />} />
<Route path="/activities/task" element={<TaskPlannng />} />
<Route path="/activities/reports" element={<Reports />} />
<Route path="/activities/gallary" element={<ImageGallary />} />
<Route path="/masters" element={<MasterPage />} />
<Route path="/help/support" element={<Support />} />
<Route path="/help/docs" element={<Documentation />} />
<Route path="/help/connect" element={<Connect />} />
</Route>
</Route>
{/* Fallback Route */}
<Route path="*" element={<ErrorPage />} />
</Routes>
</Router>
);
return <RouterProvider router={router} />;
};
export default AppRoutes;

View File

@ -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.",