Compare commits
23 Commits
9e3101ebf4
...
5427fda41e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5427fda41e | ||
|
|
620bf064c9 | ||
| 16a9cab12a | |||
| 18125f7c6a | |||
| 3607bdc77d | |||
|
|
7c7b5a9be7 | ||
| a8ba185bb8 | |||
| 144f8a0595 | |||
|
|
f3bedf5826 | ||
|
|
e0994c6f43 | ||
| a2f23ee5ae | |||
|
|
e5f6ac23ef | ||
|
|
007b657e89 | ||
|
|
73efd67fbc | ||
|
|
7c81c87f18 | ||
|
|
cc1c378a3d | ||
|
|
9682de0854 | ||
|
|
cf0a0f00b2 | ||
| e795881c79 | |||
| 50f48d27f2 | |||
| 55aa6ec499 | |||
| 12c592b59c | |||
| 130fffcc16 |
@ -84,7 +84,7 @@ const AttendLogs = ({ Id }) => {
|
|||||||
document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||||
);
|
);
|
||||||
tooltipTriggerList.forEach((el) => new bootstrap.Tooltip(el));
|
tooltipTriggerList.forEach((el) => new bootstrap.Tooltip(el));
|
||||||
}, [] );
|
}, []);
|
||||||
return (
|
return (
|
||||||
<div className="table-responsive">
|
<div className="table-responsive">
|
||||||
<div className="text-start">
|
<div className="text-start">
|
||||||
@ -106,13 +106,12 @@ const AttendLogs = ({ Id }) => {
|
|||||||
<table className="table table-sm mb-0">
|
<table className="table table-sm mb-0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th >Date</th>
|
<th>Date</th>
|
||||||
<th >Time</th>
|
<th>Time</th>
|
||||||
<th >Activity</th>
|
<th>Activity</th>
|
||||||
<th >Location</th>
|
<th>Location</th>
|
||||||
<th >Recored By</th>
|
<th>Recored By</th>
|
||||||
<th >Description</th>
|
<th>Description</th>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -127,7 +126,7 @@ const AttendLogs = ({ Id }) => {
|
|||||||
<td>
|
<td>
|
||||||
{log?.latitude != 0 ? (
|
{log?.latitude != 0 ? (
|
||||||
<i
|
<i
|
||||||
class="bx bx-location-plus text-danger cursor-pointer"
|
className="bx bx-location-plus text-danger cursor-pointer"
|
||||||
data-bs-toggle="tooltip"
|
data-bs-toggle="tooltip"
|
||||||
data-bs-offset="0,8"
|
data-bs-offset="0,8"
|
||||||
data-bs-placement="top"
|
data-bs-placement="top"
|
||||||
@ -141,13 +140,14 @@ const AttendLogs = ({ Id }) => {
|
|||||||
"--"
|
"--"
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-wrap" >
|
<td className="text-wrap">
|
||||||
{`${logs[0]?.updatedByEmployee?.firstName ?? ''} ${logs[0]?.updatedByEmployee?.lastName ?? ''}`}
|
{`${log?.updatedByEmployee?.firstName ?? ""} ${
|
||||||
|
log?.updatedByEmployee?.lastName ?? ""
|
||||||
|
}`}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-wrap" colSpan={3} >
|
<td className="text-wrap" colSpan={3}>
|
||||||
{log?.comment || "--"}
|
{log?.comment || "--"}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useState,useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import Avatar from "../common/Avatar";
|
import Avatar from "../common/Avatar";
|
||||||
import { convertShortTime } from "../../utils/dateUtils";
|
import { convertShortTime } from "../../utils/dateUtils";
|
||||||
@ -32,7 +32,7 @@ const Attendance = ({ attendance, getRole, handleModalData }) => {
|
|||||||
|
|
||||||
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
||||||
filteredData,
|
filteredData,
|
||||||
5
|
10
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -116,7 +116,7 @@ const Attendance = ({ attendance, getRole, handleModalData }) => {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
{!attendance && (
|
{!attendance && (
|
||||||
<span>No employees assigned to the project</span>
|
<span>No employees assigned to the project</span>
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@ -16,6 +16,7 @@ const AttendanceLog = ({ handleModalData, projectId }) => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { data, loading, error } = useSelector((store) => store.attendanceLogs);
|
const { data, loading, error } = useSelector((store) => store.attendanceLogs);
|
||||||
const [isRefreshing, setIsRefreshing] = useState(true);
|
const [isRefreshing, setIsRefreshing] = useState(true);
|
||||||
|
const [dates, setDates] = useState([]);
|
||||||
|
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
today.setHours(0, 0, 0, 0); // Strip time to compare dates only
|
today.setHours(0, 0, 0, 0); // Strip time to compare dates only
|
||||||
@ -40,18 +41,32 @@ const AttendanceLog = ({ handleModalData, projectId }) => {
|
|||||||
return nameA.localeCompare(nameB);
|
return nameA.localeCompare(nameB);
|
||||||
};
|
};
|
||||||
|
|
||||||
const group1 = data.filter(d => d.activity === 1 && isSameDay(d.checkInTime)).sort(sortByName);
|
const group1 = data
|
||||||
const group2 = data.filter(d => d.activity === 4 && isSameDay(d.checkOutTime)).sort(sortByName);
|
.filter((d) => d.activity === 1 && isSameDay(d.checkInTime))
|
||||||
const group3 = data.filter(d => d.activity === 1 && isBeforeToday(d.checkInTime)).sort(sortByName);
|
.sort(sortByName);
|
||||||
const group4 = data.filter(d => d.activity === 4 && isBeforeToday(d.checkOutTime)).sort(sortByName);
|
const group2 = data
|
||||||
const group5 = data.filter(d => d.activity === 5).sort(sortByName);
|
.filter((d) => d.activity === 4 && isSameDay(d.checkOutTime))
|
||||||
|
.sort(sortByName);
|
||||||
|
const group3 = data
|
||||||
|
.filter((d) => d.activity === 1 && isBeforeToday(d.checkInTime))
|
||||||
|
.sort(sortByName);
|
||||||
|
const group4 = data
|
||||||
|
.filter((d) => d.activity === 4 && isBeforeToday(d.checkOutTime))
|
||||||
|
.sort(sortByName);
|
||||||
|
const group5 = data.filter((d) => d.activity === 5).sort(sortByName);
|
||||||
|
|
||||||
const sortedFinalList = [...group1, ...group2, ...group3, ...group4, ...group5];
|
const sortedFinalList = [
|
||||||
|
...group1,
|
||||||
|
...group2,
|
||||||
|
...group3,
|
||||||
|
...group4,
|
||||||
|
...group5,
|
||||||
|
];
|
||||||
|
|
||||||
const currentDate = new Date().toLocaleDateString( "en-CA" );
|
const currentDate = new Date().toLocaleDateString("en-CA");
|
||||||
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
||||||
sortedFinalList,
|
sortedFinalList,
|
||||||
5
|
10
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -65,8 +80,16 @@ const AttendanceLog = ({ handleModalData, projectId }) => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [ dateRange, projectId, isRefreshing ] );
|
}, [dateRange, projectId, isRefreshing]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const attendanceDate = [
|
||||||
|
...new Set(sortedFinalList.map((item) => item.checkInTime.split("T")[0])),
|
||||||
|
].sort((a, b) => new Date(b) - new Date(a));
|
||||||
|
if (attendanceDate != dates) {
|
||||||
|
setDates(attendanceDate);
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -80,16 +103,15 @@ const AttendanceLog = ({ handleModalData, projectId }) => {
|
|||||||
<div className="col-md-2 m-0 text-end">
|
<div className="col-md-2 m-0 text-end">
|
||||||
<i
|
<i
|
||||||
className={`bx bx-refresh cursor-pointer fs-4 ${
|
className={`bx bx-refresh cursor-pointer fs-4 ${
|
||||||
loading ? "spin":""
|
loading ? "spin" : ""
|
||||||
}`}
|
}`}
|
||||||
title="Refresh"
|
title="Refresh"
|
||||||
onClick={() => setIsRefreshing( !isRefreshing )}
|
onClick={() => setIsRefreshing(!isRefreshing)}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="table-responsive text-nowrap">
|
<div className="table-responsive text-nowrap">
|
||||||
{(data && data.length > 0 ) && (
|
{data && data.length > 0 && (
|
||||||
<table className="table mb-0">
|
<table className="table mb-0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -109,95 +131,111 @@ const AttendanceLog = ({ handleModalData, projectId }) => {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{loading && <td colSpan={5}>Loading...</td>}
|
{loading && <td colSpan={5}>Loading...</td>}
|
||||||
{currentItems?.map( ( attendance, index ) => (
|
{dates.map((date, i) => {
|
||||||
<tr key={index}>
|
return (
|
||||||
<td colSpan={2}>
|
<React.Fragment key={i}>
|
||||||
<div className="d-flex justify-content-start align-items-center">
|
{currentItems.some(
|
||||||
<Avatar
|
(item) => item.checkInTime.split("T")[0] === date
|
||||||
firstName={attendance.firstName}
|
) && (
|
||||||
lastName={attendance.lastName}
|
<tr className="table-row-header">
|
||||||
/>
|
<td colSpan={7} className="text-start">
|
||||||
<div className="d-flex flex-column">
|
<strong>{date}</strong>
|
||||||
<a href="#" className="text-heading text-truncate">
|
</td>
|
||||||
<span className="fw-normal">
|
</tr>
|
||||||
{attendance.firstName} {attendance.lastName}
|
)}
|
||||||
</span>
|
{currentItems
|
||||||
</a>
|
?.filter((item) => item.checkInTime.includes(date))
|
||||||
</div>
|
.map((attendance, index) => (
|
||||||
</div>
|
<tr key={index}>
|
||||||
</td>
|
<td colSpan={2}>
|
||||||
<td>
|
<div className="d-flex justify-content-start align-items-center">
|
||||||
{" "}
|
<Avatar
|
||||||
{moment( attendance.checkInTime ).format( "DD-MMM-YYYY" )}
|
firstName={attendance.firstName}
|
||||||
</td>
|
lastName={attendance.lastName}
|
||||||
<td>{convertShortTime( attendance.checkInTime )}</td>
|
/>
|
||||||
<td>
|
<div className="d-flex flex-column">
|
||||||
{attendance.checkOutTime
|
<a
|
||||||
? convertShortTime( attendance.checkOutTime )
|
href="#"
|
||||||
: "--"}
|
className="text-heading text-truncate"
|
||||||
</td>
|
>
|
||||||
<td className="text-center">
|
<span className="fw-normal">
|
||||||
<RenderAttendanceStatus
|
{attendance.firstName} {attendance.lastName}
|
||||||
attendanceData={attendance}
|
</span>
|
||||||
handleModalData={handleModalData}
|
</a>
|
||||||
Tab={2}
|
</div>
|
||||||
currentDate={currentDate}
|
</div>
|
||||||
/>
|
</td>
|
||||||
</td>
|
<td>
|
||||||
</tr>
|
{" "}
|
||||||
) )}
|
{moment(attendance.checkInTime).format(
|
||||||
|
"DD-MMM-YYYY"
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td>{convertShortTime(attendance.checkInTime)}</td>
|
||||||
|
<td>
|
||||||
|
{attendance.checkOutTime
|
||||||
|
? convertShortTime(attendance.checkOutTime)
|
||||||
|
: "--"}
|
||||||
|
</td>
|
||||||
|
<td className="text-center">
|
||||||
|
<RenderAttendanceStatus
|
||||||
|
attendanceData={attendance}
|
||||||
|
handleModalData={handleModalData}
|
||||||
|
Tab={2}
|
||||||
|
currentDate={currentDate}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
) }
|
)}
|
||||||
{(!loading && data.length === 0) &&
|
{!loading && data.length === 0 && <span>No employee logs</span>}
|
||||||
<span>No employee logs</span>
|
{error && <td colSpan={5}>{error}</td>}
|
||||||
}
|
|
||||||
{error && <td colSpan={5}>{error}</td>}
|
|
||||||
</div>
|
</div>
|
||||||
{!loading && (
|
{!loading && (
|
||||||
<nav aria-label="Page ">
|
<nav aria-label="Page ">
|
||||||
<ul className="pagination pagination-sm justify-content-end py-1">
|
<ul className="pagination pagination-sm justify-content-end py-1">
|
||||||
<li
|
<li className={`page-item ${currentPage === 1 ? "disabled" : ""}`}>
|
||||||
className={`page-item ${
|
<button
|
||||||
currentPage === 1 ? "disabled" : ""
|
className="page-link btn-xs"
|
||||||
}`}
|
onClick={() => paginate(currentPage - 1)}
|
||||||
>
|
>
|
||||||
<button
|
«
|
||||||
className="page-link btn-xs"
|
</button>
|
||||||
onClick={() => paginate(currentPage - 1)}
|
</li>
|
||||||
>
|
{[...Array(totalPages)].map((_, index) => (
|
||||||
«
|
<li
|
||||||
</button>
|
key={index}
|
||||||
</li>
|
className={`page-item ${
|
||||||
{[...Array(totalPages)].map((_, index) => (
|
currentPage === index + 1 ? "active" : ""
|
||||||
<li
|
}`}
|
||||||
key={index}
|
>
|
||||||
className={`page-item ${
|
<button
|
||||||
currentPage === index + 1 ? "active" : ""
|
className="page-link "
|
||||||
}`}
|
onClick={() => paginate(index + 1)}
|
||||||
>
|
>
|
||||||
<button
|
{index + 1}
|
||||||
className="page-link "
|
</button>
|
||||||
onClick={() => paginate(index + 1)}
|
</li>
|
||||||
>
|
))}
|
||||||
{index + 1}
|
<li
|
||||||
</button>
|
className={`page-item ${
|
||||||
</li>
|
currentPage === totalPages ? "disabled" : ""
|
||||||
))}
|
}`}
|
||||||
<li
|
>
|
||||||
className={`page-item ${
|
<button
|
||||||
currentPage === totalPages ? "disabled" : ""
|
className="page-link "
|
||||||
}`}
|
onClick={() => paginate(currentPage + 1)}
|
||||||
>
|
>
|
||||||
<button
|
»
|
||||||
className="page-link "
|
</button>
|
||||||
onClick={() => paginate(currentPage + 1)}
|
</li>
|
||||||
>
|
</ul>
|
||||||
»
|
</nav>
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -52,49 +52,7 @@ const InfraPlanning = () =>
|
|||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{/* <div className={`col-12 text-end mb-1 ${!ManageInfra && 'd-none'} `} >
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="link-button link-button-sm m-1 "
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
data-bs-target="#building-model"
|
|
||||||
// onClick={() => openBuildingModel()}
|
|
||||||
>
|
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
|
||||||
Manage Building
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
className="link-button m-1"
|
|
||||||
data-bs-target="#floor-model"
|
|
||||||
// onClick={() => openFloorModel()}
|
|
||||||
>
|
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
|
||||||
Manage Floors
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
className="link-button m-1"
|
|
||||||
data-bs-target="#work-area-model"
|
|
||||||
// onClick={() => openWorkAreaModel()}
|
|
||||||
>
|
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
|
||||||
Manage Work Areas
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
className="link-button m-1"
|
|
||||||
data-bs-target="#task-model"
|
|
||||||
// onClick={() => openTaskModel()}
|
|
||||||
>
|
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
|
||||||
Manage Tasks
|
|
||||||
</button>
|
|
||||||
</div> */}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="row ">
|
<div className="row ">
|
||||||
{project_deatilsLoader && ( <p>Loading...</p> )}
|
{project_deatilsLoader && ( <p>Loading...</p> )}
|
||||||
|
|||||||
@ -23,11 +23,11 @@ const Regularization = ({ handleRequest }) => {
|
|||||||
return nameA.localeCompare(nameB);
|
return nameA.localeCompare(nameB);
|
||||||
};
|
};
|
||||||
|
|
||||||
const filteredData = regularizesList.sort(sortByName)
|
const filteredData = regularizesList.sort(sortByName);
|
||||||
|
|
||||||
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
||||||
filteredData,
|
filteredData,
|
||||||
5
|
10
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -94,50 +94,46 @@ const Regularization = ({ handleRequest }) => {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{!loading && (
|
{!loading && (
|
||||||
<nav aria-label="Page ">
|
<nav aria-label="Page ">
|
||||||
<ul className="pagination pagination-sm justify-content-end py-1">
|
<ul className="pagination pagination-sm justify-content-end py-1">
|
||||||
<li
|
<li className={`page-item ${currentPage === 1 ? "disabled" : ""}`}>
|
||||||
className={`page-item ${
|
<button
|
||||||
currentPage === 1 ? "disabled" : ""
|
className="page-link btn-xs"
|
||||||
}`}
|
onClick={() => paginate(currentPage - 1)}
|
||||||
>
|
>
|
||||||
<button
|
«
|
||||||
className="page-link btn-xs"
|
</button>
|
||||||
onClick={() => paginate(currentPage - 1)}
|
</li>
|
||||||
>
|
{[...Array(totalPages)].map((_, index) => (
|
||||||
«
|
<li
|
||||||
</button>
|
key={index}
|
||||||
</li>
|
className={`page-item ${
|
||||||
{[...Array(totalPages)].map((_, index) => (
|
currentPage === index + 1 ? "active" : ""
|
||||||
<li
|
}`}
|
||||||
key={index}
|
>
|
||||||
className={`page-item ${
|
<button
|
||||||
currentPage === index + 1 ? "active" : ""
|
className="page-link "
|
||||||
}`}
|
onClick={() => paginate(index + 1)}
|
||||||
>
|
>
|
||||||
<button
|
{index + 1}
|
||||||
className="page-link "
|
</button>
|
||||||
onClick={() => paginate(index + 1)}
|
</li>
|
||||||
>
|
))}
|
||||||
{index + 1}
|
<li
|
||||||
</button>
|
className={`page-item ${
|
||||||
</li>
|
currentPage === totalPages ? "disabled" : ""
|
||||||
))}
|
}`}
|
||||||
<li
|
>
|
||||||
className={`page-item ${
|
<button
|
||||||
currentPage === totalPages ? "disabled" : ""
|
className="page-link "
|
||||||
}`}
|
onClick={() => paginate(currentPage + 1)}
|
||||||
>
|
>
|
||||||
<button
|
»
|
||||||
className="page-link "
|
</button>
|
||||||
onClick={() => paginate(currentPage + 1)}
|
</li>
|
||||||
>
|
</ul>
|
||||||
»
|
</nav>
|
||||||
</button>
|
)}
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,8 +5,7 @@ const EmployeeNav = ({ onPillClick, activePill }) => {
|
|||||||
<div className="col-md-12">
|
<div className="col-md-12">
|
||||||
<div className="nav-align-top ">
|
<div className="nav-align-top ">
|
||||||
<ul className="nav nav-tabs">
|
<ul className="nav nav-tabs">
|
||||||
|
<li className="nav-item" style={{ padding: "10px 10px 0 10px" }}>
|
||||||
<li className="nav-item">
|
|
||||||
<a
|
<a
|
||||||
className={`nav-link py-1 px-2 small ${
|
className={`nav-link py-1 px-2 small ${
|
||||||
activePill === "attendance" ? "active" : ""
|
activePill === "attendance" ? "active" : ""
|
||||||
@ -20,7 +19,7 @@ const EmployeeNav = ({ onPillClick, activePill }) => {
|
|||||||
<i className="bx bx-group bx-sm me-1_5"></i> Attendances
|
<i className="bx bx-group bx-sm me-1_5"></i> Attendances
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav-item">
|
<li className="nav-item" style={{ padding: "10px 10px 0 10px" }}>
|
||||||
<a
|
<a
|
||||||
className={`nav-link py-1 px-2 small ${
|
className={`nav-link py-1 px-2 small ${
|
||||||
activePill === "account" ? "active" : ""
|
activePill === "account" ? "active" : ""
|
||||||
@ -35,7 +34,7 @@ const EmployeeNav = ({ onPillClick, activePill }) => {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li className="nav-item">
|
<li className="nav-item" style={{ padding: "10px 10px 0 10px" }}>
|
||||||
<a
|
<a
|
||||||
className={`nav-link py-1 px-2 small ${
|
className={`nav-link py-1 px-2 small ${
|
||||||
activePill === "activities" ? "active" : ""
|
activePill === "activities" ? "active" : ""
|
||||||
|
|||||||
@ -54,7 +54,7 @@ const Header = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleProfilePage = () => {
|
const handleProfilePage = () => {
|
||||||
navigate(`/employee/${profile?.employeeInfo?.id}?for=account`);
|
navigate(`/employee/${profile?.employeeInfo?.id}?for=attendance`);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
@ -120,7 +120,7 @@ const Header = () => {
|
|||||||
className="nav-link dropdown-toggle hide-arrow"
|
className="nav-link dropdown-toggle hide-arrow"
|
||||||
href="#;"
|
href="#;"
|
||||||
data-bs-toggle="dropdown"
|
data-bs-toggle="dropdown"
|
||||||
data-bs-auto-close="outside"
|
data-bs-auto-close="true"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
>
|
>
|
||||||
<i className="icon-base bx bx-grid-alt icon-md"></i>
|
<i className="icon-base bx bx-grid-alt icon-md"></i>
|
||||||
@ -143,39 +143,53 @@ const Header = () => {
|
|||||||
<div className="dropdown-shortcuts-list scrollable-container ps">
|
<div className="dropdown-shortcuts-list scrollable-container ps">
|
||||||
<div className="row row-bordered overflow-visible g-0">
|
<div className="row row-bordered overflow-visible g-0">
|
||||||
<div className="dropdown-shortcuts-item col">
|
<div className="dropdown-shortcuts-item col">
|
||||||
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
<a
|
||||||
<i className="icon-base bx bx-home icon-26px text-heading"></i>
|
onClick={() => navigate(`/dashboard`)}
|
||||||
</span>
|
className="text-heading text-truncate cursor-pointer"
|
||||||
<a href="/dashboard" className="stretched-link">
|
>
|
||||||
|
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
||||||
|
<i className="icon-base bx bx-home icon-26px text-heading"></i>
|
||||||
|
</span>
|
||||||
Dashboard
|
Dashboard
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<small>User Dashboard</small>
|
<small>User Dashboard</small>
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-shortcuts-item col">
|
<div className="dropdown-shortcuts-item col">
|
||||||
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
<a
|
||||||
<i className="icon-base bx bx-building-house icon-26px text-heading"></i>
|
onClick={() => navigate(`/projects`)}
|
||||||
</span>
|
className="text-heading text-truncate cursor-pointer"
|
||||||
<a href="/projects" className="stretched-link">
|
>
|
||||||
|
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
||||||
|
<i className="icon-base bx bx-building-house icon-26px text-heading"></i>
|
||||||
|
</span>
|
||||||
Projects
|
Projects
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<small>Projects List</small>
|
<small>Projects List</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="row row-bordered overflow-visible g-0">
|
<div className="row row-bordered overflow-visible g-0">
|
||||||
<div className="dropdown-shortcuts-item col">
|
<div className="dropdown-shortcuts-item col">
|
||||||
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
<a
|
||||||
<i className="icon-base bx bxs-user-account icon-26px text-heading"></i>
|
onClick={() => navigate(`/employees`)}
|
||||||
</span>
|
className="text-heading text-truncate cursor-pointer"
|
||||||
<a href="/employees" className="stretched-link">
|
>
|
||||||
|
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
||||||
|
<i className="icon-base bx bxs-user-account icon-26px text-heading"></i>
|
||||||
|
</span>
|
||||||
Employees
|
Employees
|
||||||
</a>
|
</a>
|
||||||
<small>Manage Employees</small>
|
<small>Manage Employees</small>
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-shortcuts-item col">
|
<div className="dropdown-shortcuts-item col">
|
||||||
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
<a
|
||||||
<i className="icon-base bx bx-user-check icon-26px text-heading"></i>
|
onClick={() => navigate(`/activities/attendance`)}
|
||||||
</span>
|
className="text-heading text-truncate cursor-pointer"
|
||||||
<a href="/activities/attendance" className="stretched-link">
|
>
|
||||||
|
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
||||||
|
<i className="icon-base bx bx-user-check icon-26px text-heading"></i>
|
||||||
|
</span>
|
||||||
Attendance
|
Attendance
|
||||||
</a>
|
</a>
|
||||||
<small>Manage Attendance</small>
|
<small>Manage Attendance</small>
|
||||||
@ -183,21 +197,29 @@ const Header = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="row row-bordered overflow-visible g-0">
|
<div className="row row-bordered overflow-visible g-0">
|
||||||
<div className="dropdown-shortcuts-item col">
|
<div className="dropdown-shortcuts-item col">
|
||||||
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
<a
|
||||||
<i className="icon-base bx bxs-wrench icon-26px text-heading"></i>
|
onClick={() => navigate(`/activities/task`)}
|
||||||
</span>
|
className="text-heading text-truncate cursor-pointer"
|
||||||
<a href="/activities/task" className="stretched-link">
|
>
|
||||||
|
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
||||||
|
<i className="icon-base bx bxs-wrench icon-26px text-heading"></i>
|
||||||
|
</span>
|
||||||
Allocate Work
|
Allocate Work
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<small>Work Allocations</small>
|
<small>Work Allocations</small>
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-shortcuts-item col">
|
<div className="dropdown-shortcuts-item col">
|
||||||
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
<a
|
||||||
<i className="icon-base bx bx-list-ul icon-26px text-heading"></i>
|
onClick={() => navigate(`/activities/records`)}
|
||||||
</span>
|
className="text-heading text-truncate cursor-pointer"
|
||||||
<a href="/activities/records" className="stretched-link">
|
>
|
||||||
|
<span className="dropdown-shortcuts-icon rounded-circle mb-3">
|
||||||
|
<i className="icon-base bx bx-list-ul icon-26px text-heading"></i>
|
||||||
|
</span>
|
||||||
Daily Work Log
|
Daily Work Log
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<small>Daily Work Allocations</small>
|
<small>Daily Work Allocations</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,104 +0,0 @@
|
|||||||
import React, {useState} from 'react'
|
|
||||||
import ProjectRepository from '../../../repositories/ProjectRepository'
|
|
||||||
import {useProjectDetails} from '../../../hooks/useProjects'
|
|
||||||
|
|
||||||
const DleleteActivity = ( {workItem, workArea, building, floor, onClose} ) =>
|
|
||||||
{
|
|
||||||
const {projects_Details, refetch} = useProjectDetails()
|
|
||||||
const [loading,setLoading] = useState(false)
|
|
||||||
|
|
||||||
|
|
||||||
const handleDeleteActivity =async () =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
setLoading(false)
|
|
||||||
const updatedProject = { ...projects_Details };
|
|
||||||
const response = await ProjectRepository.deleteProjectTask( workItem.workItemId );
|
|
||||||
const newProject = {
|
|
||||||
...updatedProject,
|
|
||||||
buildings: updatedProject.buildings.map((building) =>
|
|
||||||
building.id === building.buildingID
|
|
||||||
? {
|
|
||||||
...building,
|
|
||||||
floors: building.floors.map((floor) =>
|
|
||||||
floor.id === building.floorId
|
|
||||||
? {
|
|
||||||
...floor,
|
|
||||||
workAreas: floor.workAreas.map((workArea) =>
|
|
||||||
workArea.id === workItem?.workAreaId
|
|
||||||
? {
|
|
||||||
...workArea,
|
|
||||||
workItems: (() => {
|
|
||||||
const exists = workArea.workItems.some(
|
|
||||||
(item) =>
|
|
||||||
String(
|
|
||||||
item?.workItem?.id ?? item?.id
|
|
||||||
) === String(finalData.id)
|
|
||||||
);
|
|
||||||
|
|
||||||
finalUpdatedWorkItem = workItem;
|
|
||||||
|
|
||||||
return exists
|
|
||||||
? workArea.workItems.map((item) =>
|
|
||||||
String(
|
|
||||||
item?.workItem?.id ?? item?.id
|
|
||||||
) === String(finalData.id)
|
|
||||||
? workItem
|
|
||||||
: item
|
|
||||||
)
|
|
||||||
: [...workArea.workItems, workItem];
|
|
||||||
})(),
|
|
||||||
}
|
|
||||||
: workArea
|
|
||||||
),
|
|
||||||
}
|
|
||||||
: floor
|
|
||||||
),
|
|
||||||
}
|
|
||||||
: building
|
|
||||||
),
|
|
||||||
};
|
|
||||||
cacheData("projectInfo", {
|
|
||||||
projectId: newProject.id,
|
|
||||||
data: newProject,
|
|
||||||
});
|
|
||||||
resetForm();
|
|
||||||
dispatch( refreshData( true ) );
|
|
||||||
setLoading(false)
|
|
||||||
showToast("Activity Updated Successfully","success")
|
|
||||||
|
|
||||||
onClose();
|
|
||||||
} catch ( error )
|
|
||||||
{
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className="modal-dialog modal-md modal-simple modal-edit-user">
|
|
||||||
<div className='modal-dialog modal-dialog-centered'>
|
|
||||||
<div className="modal-content">
|
|
||||||
<div className="modal-body">
|
|
||||||
<div className="row">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn-close"
|
|
||||||
aria-label="Close"
|
|
||||||
onClick={()=>onClose}
|
|
||||||
/>
|
|
||||||
<div className="text-center mb-1">
|
|
||||||
<h5>Are you sure you want delete this Activity { workItem.id}</h5>
|
|
||||||
<div className='d-flex justify-content-evenly'>
|
|
||||||
<button className='btn btn-primary btn-xs' onClick={handleDeleteActivity}>{ loading ? "Please Wait ":"Yes"}</button>
|
|
||||||
<button className='btn btn-secondary btn-xs' onClick={()=>onClose}>Cancel</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DleleteActivity
|
|
||||||
@ -19,7 +19,7 @@ const taskSchema = z
|
|||||||
.object({
|
.object({
|
||||||
activityID: z.string().min(1, "Activity is required"),
|
activityID: z.string().min(1, "Activity is required"),
|
||||||
plannedWork: z.number().min(1, "Planned Work must be greater than 0"),
|
plannedWork: z.number().min(1, "Planned Work must be greater than 0"),
|
||||||
completedWork: z.number().optional(),
|
completedWork: z.number().min(0, "Completed Work must be greater than 0"),
|
||||||
})
|
})
|
||||||
.refine(
|
.refine(
|
||||||
(data) =>
|
(data) =>
|
||||||
|
|||||||
@ -205,7 +205,7 @@ const FloorModel = ({
|
|||||||
|
|
||||||
{formData.buildingId !== "0" && (
|
{formData.buildingId !== "0" && (
|
||||||
<div className="col-12 col-md-12">
|
<div className="col-12 col-md-12">
|
||||||
<label className="form-label" htmlFor="floorName">
|
<label className="form-label" >
|
||||||
{formData.id !== "0" ? "Modify " : "Enter "} Floor Name
|
{formData.id !== "0" ? "Modify " : "Enter "} Floor Name
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@ -68,7 +68,7 @@ const InfraTable = ({ buildings }) => {
|
|||||||
showToast("Failed to save floor", "error");
|
showToast("Failed to save floor", "error");
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error adding floor", err);
|
|
||||||
showToast("Error occurred while saving floor", "error");
|
showToast("Error occurred while saving floor", "error");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,7 +10,7 @@ const taskSchema = z.object({
|
|||||||
workAreaId: z.string().min(1, "Work Area is required"),
|
workAreaId: z.string().min(1, "Work Area is required"),
|
||||||
activityID: z.string().min(1, "Activity is required"),
|
activityID: z.string().min(1, "Activity is required"),
|
||||||
plannedWork: z.number().min(1, "Planned Work must be greater than 0"),
|
plannedWork: z.number().min(1, "Planned Work must be greater than 0"),
|
||||||
completedWork: z.number().optional(),
|
completedWork: z.number().min(0, "Completed Work must be greater than 0"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultModel = {
|
const defaultModel = {
|
||||||
|
|||||||
@ -29,7 +29,7 @@ const WorkArea = ({ workArea, floor, forBuilding }) => {
|
|||||||
<span className="fw-semibold text-primary">
|
<span className="fw-semibold text-primary">
|
||||||
Floor:
|
Floor:
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
<span class="fw-normal text-darkgreen">
|
<span className="fw-normal text-darkgreen">
|
||||||
{floor.floorName}
|
{floor.floorName}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -37,7 +37,7 @@ const WorkArea = ({ workArea, floor, forBuilding }) => {
|
|||||||
<span className="ms-10 fw-semibold text-primary">
|
<span className="ms-10 fw-semibold text-primary">
|
||||||
Work Area:
|
Work Area:
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
<span class=" fw-normal text-darkgreen">
|
<span className=" fw-normal text-darkgreen">
|
||||||
{workArea.areaName}
|
{workArea.areaName}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,12 +4,12 @@ import { useParams } from "react-router-dom";
|
|||||||
import EditActivityModal from "./EditActivityModal";
|
import EditActivityModal from "./EditActivityModal";
|
||||||
import { useHasUserPermission } from "../../../hooks/useHasUserPermission";
|
import { useHasUserPermission } from "../../../hooks/useHasUserPermission";
|
||||||
import { MANAGE_PROJECT_INFRA, MANAGE_TASK } from "../../../utils/constants";
|
import { MANAGE_PROJECT_INFRA, MANAGE_TASK } from "../../../utils/constants";
|
||||||
import DleleteActivity from "./DleleteActivity";
|
|
||||||
import ConfirmModal from "../../common/ConfirmModal";
|
import ConfirmModal from "../../common/ConfirmModal";
|
||||||
import ProjectRepository from '../../../repositories/ProjectRepository'
|
import ProjectRepository from '../../../repositories/ProjectRepository'
|
||||||
import {useProjectDetails} from '../../../hooks/useProjects'
|
import {useProjectDetails} from '../../../hooks/useProjects'
|
||||||
import showToast from "../../../services/toastService";
|
import showToast from "../../../services/toastService";
|
||||||
import {cacheData} from "../../../slices/apiDataManager";
|
import {cacheData, getCachedData} from "../../../slices/apiDataManager";
|
||||||
import {useDispatch} from "react-redux";
|
import {useDispatch} from "react-redux";
|
||||||
import {refreshData} from "../../../slices/localVariablesSlice";
|
import {refreshData} from "../../../slices/localVariablesSlice";
|
||||||
|
|
||||||
@ -23,9 +23,10 @@ const WorkItem = ({ workItem, forBuilding, forFloor, forWorkArea }) => {
|
|||||||
const ManageTasks = useHasUserPermission(MANAGE_TASK);
|
const ManageTasks = useHasUserPermission(MANAGE_TASK);
|
||||||
const ManageInfra = useHasUserPermission( MANAGE_PROJECT_INFRA );
|
const ManageInfra = useHasUserPermission( MANAGE_PROJECT_INFRA );
|
||||||
const [ loadingDelete, setLoadingDelete ] = useState( false )
|
const [ loadingDelete, setLoadingDelete ] = useState( false )
|
||||||
|
const project = getCachedData("projectInfo");
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
const {projects_Details} = useProjectDetails(projectId)
|
const {projects_Details} = useProjectDetails(projectId || project?.projectId)
|
||||||
|
|
||||||
const openModal = () => setIsModalOpen(true);
|
const openModal = () => setIsModalOpen(true);
|
||||||
const closeModal = () => setIsModalOpen(false);
|
const closeModal = () => setIsModalOpen(false);
|
||||||
@ -63,7 +64,6 @@ const WorkItem = ({ workItem, forBuilding, forFloor, forWorkArea }) => {
|
|||||||
const showModalDelete = () => setShowModal2(true);
|
const showModalDelete = () => setShowModal2(true);
|
||||||
const closeModalDelete = () => setShowModal2( false );
|
const closeModalDelete = () => setShowModal2( false );
|
||||||
|
|
||||||
console.log(workItem)
|
|
||||||
|
|
||||||
const handleSubmit = async() => {
|
const handleSubmit = async() => {
|
||||||
setLoadingDelete(true);
|
setLoadingDelete(true);
|
||||||
@ -103,27 +103,25 @@ console.log(workItem)
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(newProject)
|
|
||||||
cacheData("projectInfo", {
|
cacheData("projectInfo", {
|
||||||
projectId: newProject.id,
|
projectId: newProject.id,
|
||||||
data: newProject,
|
data: newProject,
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatch( refreshData( true ) );
|
dispatch( refreshData( true ) );
|
||||||
|
closeModalDelete()
|
||||||
setLoadingDelete(false)
|
setLoadingDelete(false)
|
||||||
showToast("Activity Updated Successfully","success")
|
showToast("Activity Deleted Successfully","success")
|
||||||
|
|
||||||
|
|
||||||
} catch ( error )
|
} catch ( error )
|
||||||
{
|
{
|
||||||
setLoadingDelete(false)
|
setLoadingDelete( false )
|
||||||
|
closeModalDelete()
|
||||||
const message =
|
const message =
|
||||||
error.response?.data?.message ||
|
error.response?.data?.message ||
|
||||||
error.message ||
|
error.message ||
|
||||||
"An unexpected error occurred";
|
"An unexpected error occurred";
|
||||||
showToast( message, "error" );
|
showToast( message, "error" );
|
||||||
console.log(error)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
@ -156,6 +154,7 @@ console.log(workItem)
|
|||||||
/>
|
/>
|
||||||
</div>}
|
</div>}
|
||||||
|
|
||||||
|
|
||||||
{showModal2 && <div
|
{showModal2 && <div
|
||||||
className={`modal fade ${showModal2 ? "show" : ""}`}
|
className={`modal fade ${showModal2 ? "show" : ""}`}
|
||||||
tabIndex="-1"
|
tabIndex="-1"
|
||||||
@ -163,14 +162,7 @@ console.log(workItem)
|
|||||||
style={{ display: showModal2 ? "block" : "none" }}
|
style={{ display: showModal2 ? "block" : "none" }}
|
||||||
aria-hidden='false'
|
aria-hidden='false'
|
||||||
>
|
>
|
||||||
{/* <DleleteActivity
|
<ConfirmModal type={"delete"} header={"Delete Activity"} message={"Are you sure you want delete"} onSubmit={ handleSubmit} onClose={closeModalDelete} loading={loadingDelete}/>
|
||||||
workItem={workItem}
|
|
||||||
workArea={forWorkArea}
|
|
||||||
building={forBuilding}
|
|
||||||
floor={forFloor}
|
|
||||||
onClose={closeModalDelete}
|
|
||||||
/> */}
|
|
||||||
<ConfirmModal type={"delete"} message={"Are you sure you want delete"} onSubmit={ handleSubmit} onClose={closeModalDelete} loading={loadingDelete}/>
|
|
||||||
</div> }
|
</div> }
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
const ConfirmModal = ({ type, onSubmit, onClose, message, loading }) => {
|
const ConfirmModal = ({ type, onSubmit, onClose, message, loading ,header}) => {
|
||||||
|
|
||||||
const TypeofIcon = (type) => {
|
const TypeofIcon = (type) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "delete":
|
case "delete":
|
||||||
return <i className='bx bx-x-circle text-danger bx-lg'></i>;
|
return <i className='bx bx-x-circle text-danger ' style={{fontSize:"60px"}} ></i>;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -34,9 +34,15 @@ const ConfirmModal = ({ type, onSubmit, onClose, message, loading }) => {
|
|||||||
aria-label="Close"
|
aria-label="Close"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
/>
|
/>
|
||||||
<div className="text-center mb-1">
|
<div className="text-start mb-1">
|
||||||
<p className='fs-6'>{TypeofIcon(type)} <span className='fs-6'>{message}</span></p>
|
|
||||||
<div className='d-flex justify-content-evenly'>
|
|
||||||
|
{header && < strong className='mb-0 font-weight-bold'>{header }</strong>}
|
||||||
|
<div className='row'>
|
||||||
|
<div className='col-4 col-sm-2'> {TypeofIcon(type)}</div>
|
||||||
|
<div className='col-8 col-sm-10 py-sm-2 py-1 text-sm-end'>
|
||||||
|
<span className='fs-6 text'>{message}</span>
|
||||||
|
<div className='d-flex justify-content-center mt-4'>
|
||||||
<button
|
<button
|
||||||
className='btn btn-primary btn-sm'
|
className='btn btn-primary btn-sm'
|
||||||
onClick={onSubmit}
|
onClick={onSubmit}
|
||||||
@ -45,13 +51,17 @@ const ConfirmModal = ({ type, onSubmit, onClose, message, loading }) => {
|
|||||||
{loading ? "Please Wait..." : "Yes"}
|
{loading ? "Please Wait..." : "Yes"}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className='btn btn-secondary btn-sm'
|
className='btn btn-secondary ms-4 btn-sm'
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -204,7 +204,7 @@ const CreateActivity = ({ onClose }) => {
|
|||||||
onClick={() => removeChecklistItem(index)}
|
onClick={() => removeChecklistItem(index)}
|
||||||
className="btn btn-xs btn-icon btn-text-secondary"
|
className="btn btn-xs btn-icon btn-text-secondary"
|
||||||
>
|
>
|
||||||
<i class="bx bxs-minus-circle text-danger" data-bs-toggle="tooltip"
|
<i className="bx bxs-minus-circle text-danger" data-bs-toggle="tooltip"
|
||||||
title="Remove Check"
|
title="Remove Check"
|
||||||
data-bs-original-title="Remove check"></i>
|
data-bs-original-title="Remove check"></i>
|
||||||
</button>
|
</button>
|
||||||
@ -219,7 +219,7 @@ const CreateActivity = ({ onClose }) => {
|
|||||||
className="btn btn-xs btn-primary mt-2"
|
className="btn btn-xs btn-primary mt-2"
|
||||||
onClick={addChecklistItem}
|
onClick={addChecklistItem}
|
||||||
>
|
>
|
||||||
<i class="bx bx-plus-circle" data-bs-toggle="tooltip"
|
<i className="bx bx-plus-circle" data-bs-toggle="tooltip"
|
||||||
title="Add Check"
|
title="Add Check"
|
||||||
data-bs-original-title="Add check" ></i>
|
data-bs-original-title="Add check" ></i>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -62,7 +62,7 @@ const AttendancePage = () => {
|
|||||||
modalElement.classList.remove("show");
|
modalElement.classList.remove("show");
|
||||||
modalElement.style.display = "none";
|
modalElement.style.display = "none";
|
||||||
document.body.classList.remove("modal-open");
|
document.body.classList.remove("modal-open");
|
||||||
document.querySelector(".modal-backdrop").remove();
|
document.querySelector(".modal-backdrop")?.remove();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -93,11 +93,10 @@ const AttendancePage = () => {
|
|||||||
}, [modelConfig, isCreateModalOpen]);
|
}, [modelConfig, isCreateModalOpen]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setAttendances(attendance);
|
setAttendances(attendance);
|
||||||
}, [ attendance ] );
|
}, [attendance]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedProject === 1 || selectedProject === undefined ) {
|
if (selectedProject === 1 || selectedProject === undefined) {
|
||||||
dispatch(setProjectId(loginUser?.projects[0]));
|
dispatch(setProjectId(loginUser?.projects[0]));
|
||||||
}
|
}
|
||||||
}, [selectedProject, loginUser?.projects]);
|
}, [selectedProject, loginUser?.projects]);
|
||||||
@ -108,7 +107,7 @@ const AttendancePage = () => {
|
|||||||
className="modal fade show"
|
className="modal fade show"
|
||||||
style={{ display: "block" }}
|
style={{ display: "block" }}
|
||||||
id="check-Out-modal"
|
id="check-Out-modal"
|
||||||
tabindex="-1"
|
tabIndex="-1"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<AttendanceModel
|
<AttendanceModel
|
||||||
|
|||||||
@ -87,7 +87,6 @@ const DailyTask = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
popoverRefs.current.forEach((el) => {
|
popoverRefs.current.forEach((el) => {
|
||||||
console.log(el);
|
|
||||||
if (el) {
|
if (el) {
|
||||||
new bootstrap.Popover(el, {
|
new bootstrap.Popover(el, {
|
||||||
trigger: "focus",
|
trigger: "focus",
|
||||||
@ -200,7 +199,6 @@ const DailyTask = () => {
|
|||||||
task.assignmentDate.includes(date)
|
task.assignmentDate.includes(date)
|
||||||
).map((task, index) => {
|
).map((task, index) => {
|
||||||
const refIndex = index * 10 + i;
|
const refIndex = index * 10 + i;
|
||||||
console.log(refIndex);
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={index}>
|
<React.Fragment key={index}>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { useProfile } from "../../hooks/useProfile";
|
|||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { useProjectDetails, useProjects } from "../../hooks/useProjects";
|
import { useProjectDetails, useProjects } from "../../hooks/useProjects";
|
||||||
import { setProjectId } from "../../slices/localVariablesSlice";
|
import { setProjectId } from "../../slices/localVariablesSlice";
|
||||||
|
import showToast from "../../services/toastService";
|
||||||
|
|
||||||
const TaskPlannng = () => {
|
const TaskPlannng = () => {
|
||||||
const { profile } = useProfile();
|
const { profile } = useProfile();
|
||||||
@ -22,6 +23,7 @@ const TaskPlannng = () => {
|
|||||||
(store) => store.localVariables.projectId
|
(store) => store.localVariables.projectId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
const [project, setProject] = useState(null);
|
const [project, setProject] = useState(null);
|
||||||
const [projectDetails, setProjectDetails] = useState(null);
|
const [projectDetails, setProjectDetails] = useState(null);
|
||||||
const [activities, setActivities] = useState(null);
|
const [activities, setActivities] = useState(null);
|
||||||
@ -66,14 +68,22 @@ const TaskPlannng = () => {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error(error);
|
const message =
|
||||||
setError("Failed to fetch data.");
|
error.response?.data?.message ||
|
||||||
|
error.message ||
|
||||||
|
"An unexpected error occurred";
|
||||||
|
showToast( message, "error" );
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setProjectDetails(project_cache);
|
setProjectDetails(project_cache);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError("Failed to fetch data.");
|
setError( "Failed to fetch data." );
|
||||||
|
const message =
|
||||||
|
error.response?.data?.message ||
|
||||||
|
error.message ||
|
||||||
|
"An unexpected error occurred";
|
||||||
|
showToast( message, "error" );
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,7 +70,7 @@ const AttendancesEmployeeRecords = ({ employee }) => {
|
|||||||
const currentDate = new Date().toLocaleDateString("en-CA");
|
const currentDate = new Date().toLocaleDateString("en-CA");
|
||||||
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
||||||
sortedFinalList,
|
sortedFinalList,
|
||||||
5
|
10
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -84,7 +84,7 @@ const AttendancesEmployeeRecords = ({ employee }) => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [dateRange, employee,isRefreshing]);
|
}, [dateRange, employee, isRefreshing]);
|
||||||
|
|
||||||
const openModal = (id) => {
|
const openModal = (id) => {
|
||||||
setAttendanecId(id);
|
setAttendanecId(id);
|
||||||
@ -132,7 +132,7 @@ const AttendancesEmployeeRecords = ({ employee }) => {
|
|||||||
<i
|
<i
|
||||||
className={`bx bx-refresh cursor-pointer fs-4 ${
|
className={`bx bx-refresh cursor-pointer fs-4 ${
|
||||||
loading ? "spin" : ""
|
loading ? "spin" : ""
|
||||||
}`}
|
}`}
|
||||||
data-toggle="tooltip"
|
data-toggle="tooltip"
|
||||||
title="Refresh"
|
title="Refresh"
|
||||||
onClick={() => setIsRefreshing(!isRefreshing)}
|
onClick={() => setIsRefreshing(!isRefreshing)}
|
||||||
@ -140,12 +140,10 @@ const AttendancesEmployeeRecords = ({ employee }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="table-responsive text-nowrap">
|
<div className="table-responsive text-nowrap">
|
||||||
{(!loading && data.length === 0) &&
|
{!loading && data.length === 0 && <span>No employee logs</span>}
|
||||||
<span>No employee logs</span>
|
{error && <div className="text-center">{error}</div>}
|
||||||
}
|
{loading && !data && <div className="text-center">Loading...</div>}
|
||||||
{error && <div className="text-center">{error }</div>}
|
{data && data.length > 0 && (
|
||||||
{(loading && !data ) && <div className="text-center">Loading...</div>}
|
|
||||||
{(data && data.length > 0 ) && (
|
|
||||||
<table className="table mb-0">
|
<table className="table mb-0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -165,7 +163,7 @@ const AttendancesEmployeeRecords = ({ employee }) => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{currentItems?.map( ( attendance, index ) => (
|
{currentItems?.map((attendance, index) => (
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
<td colSpan={2}>
|
<td colSpan={2}>
|
||||||
<div className="d-flex justify-content-start align-items-center">
|
<div className="d-flex justify-content-start align-items-center">
|
||||||
@ -184,12 +182,12 @@ const AttendancesEmployeeRecords = ({ employee }) => {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{" "}
|
{" "}
|
||||||
{moment( attendance.checkInTime ).format( "DD-MMM-YYYY" )}
|
{moment(attendance.checkInTime).format("DD-MMM-YYYY")}
|
||||||
</td>
|
</td>
|
||||||
<td>{convertShortTime( attendance.checkInTime )}</td>
|
<td>{convertShortTime(attendance.checkInTime)}</td>
|
||||||
<td>
|
<td>
|
||||||
{attendance.checkOutTime
|
{attendance.checkOutTime
|
||||||
? convertShortTime( attendance.checkOutTime )
|
? convertShortTime(attendance.checkOutTime)
|
||||||
: "--"}
|
: "--"}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
@ -200,18 +198,18 @@ const AttendancesEmployeeRecords = ({ employee }) => {
|
|||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
aria-controls="DataTables_Table_0"
|
aria-controls="DataTables_Table_0"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
onClick={() => openModal( attendance.id )}
|
onClick={() => openModal(attendance.id)}
|
||||||
>
|
>
|
||||||
View
|
View
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
) )}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
) }
|
)}
|
||||||
</div>
|
</div>
|
||||||
{(!loading && data.length > 5) && (
|
{!loading && data.length > 5 && (
|
||||||
<nav aria-label="Page ">
|
<nav aria-label="Page ">
|
||||||
<ul className="pagination pagination-sm justify-content-end py-1">
|
<ul className="pagination pagination-sm justify-content-end py-1">
|
||||||
<li
|
<li
|
||||||
|
|||||||
@ -3,9 +3,13 @@ import EmpProfile from "../../components/Employee/EmpProfile";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||||
import EmployeeNav from "../../components/Employee/EmployeeNav";
|
import EmployeeNav from "../../components/Employee/EmployeeNav";
|
||||||
import { useSearchParams,useParams } from "react-router-dom";
|
import { useSearchParams, useParams } from "react-router-dom";
|
||||||
import { getCachedData } from "../../slices/apiDataManager";
|
import { getCachedData } from "../../slices/apiDataManager";
|
||||||
import { useEmployeeProfile, useEmployees, useEmployeesByProject } from "../../hooks/useEmployees";
|
import {
|
||||||
|
useEmployeeProfile,
|
||||||
|
useEmployees,
|
||||||
|
useEmployeesByProject,
|
||||||
|
} from "../../hooks/useEmployees";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import EmployeeRepository from "../../repositories/EmployeeRepository";
|
import EmployeeRepository from "../../repositories/EmployeeRepository";
|
||||||
import { ComingSoonPage } from "../Misc/ComingSoonPage";
|
import { ComingSoonPage } from "../Misc/ComingSoonPage";
|
||||||
@ -13,41 +17,33 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import Avatar from "../../components/common/Avatar";
|
import Avatar from "../../components/common/Avatar";
|
||||||
import AttendancesEmployeeRecords from "./AttendancesEmployeeRecords";
|
import AttendancesEmployeeRecords from "./AttendancesEmployeeRecords";
|
||||||
const EmployeeProfile = () => {
|
const EmployeeProfile = () => {
|
||||||
|
const projectID = useSelector((store) => store.localVariables.projectId);
|
||||||
const projectID = useSelector((store)=>store.localVariables.projectId)
|
const { employeeId } = useParams();
|
||||||
const {employeeId} = useParams();
|
|
||||||
// const {employee,loading} = useEmployeeProfile(employeeId)
|
// const {employee,loading} = useEmployeeProfile(employeeId)
|
||||||
const [loading,setLoading] = useState(true)
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
const [SearchParams] = useSearchParams()
|
const [SearchParams] = useSearchParams();
|
||||||
const tab = SearchParams.get( "for" )
|
const tab = SearchParams.get("for");
|
||||||
const [activePill, setActivePill] = useState(tab);
|
const [activePill, setActivePill] = useState(tab);
|
||||||
const[currentEmployee,setCurrentEmployee] = useState()
|
const [currentEmployee, setCurrentEmployee] = useState();
|
||||||
|
|
||||||
|
|
||||||
const handlePillClick = (pillKey) => {
|
const handlePillClick = (pillKey) => {
|
||||||
setActivePill(pillKey);
|
setActivePill(pillKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchEmployeeProfile = async( employeeID ) =>
|
const fetchEmployeeProfile = async (employeeID) => {
|
||||||
{
|
try {
|
||||||
try
|
const resp = await EmployeeRepository.getEmployeeProfile(employeeID);
|
||||||
{
|
setCurrentEmployee(resp.data);
|
||||||
const resp = await EmployeeRepository.getEmployeeProfile( employeeID )
|
setLoading(false);
|
||||||
setCurrentEmployee( resp.data )
|
} catch (err) {
|
||||||
setLoading(false)
|
setLoading(false);
|
||||||
|
|
||||||
} catch ( err )
|
|
||||||
{
|
|
||||||
setLoading(false)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if ( employeeId )
|
if (employeeId) {
|
||||||
{
|
fetchEmployeeProfile(employeeId);
|
||||||
fetchEmployeeProfile(employeeId)
|
|
||||||
}
|
}
|
||||||
}, [employeeId]);
|
}, [employeeId]);
|
||||||
|
|
||||||
@ -58,42 +54,40 @@ const EmployeeProfile = () => {
|
|||||||
case "attendance": {
|
case "attendance": {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AttendancesEmployeeRecords employee={employeeId } />
|
<AttendancesEmployeeRecords employee={employeeId} />
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "dcoument": {
|
case "dcoument": {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ComingSoonPage/>
|
<ComingSoonPage />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "activities": {
|
case "activities": {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ComingSoonPage/>
|
<ComingSoonPage />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return <>
|
return (
|
||||||
<ComingSoonPage/>
|
<>
|
||||||
</>;
|
<ComingSoonPage />
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <div>Loading...</div>;
|
return <div>Loading...</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container-xxl flex-grow-1 container-p-y">
|
<div className="container-xxl flex-grow-1 container-p-y">
|
||||||
<Breadcrumb
|
<Breadcrumb
|
||||||
@ -123,75 +117,127 @@ const EmployeeProfile = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="w-100 d-flex flex-column justify-content-start">
|
<div className="w-100 d-flex flex-column justify-content-start">
|
||||||
<div className="mt-3 w-100">
|
<div className="mt-3 w-100">
|
||||||
<h6 className="mb-2 text-muted text-start">Employee Info</h6>
|
<h6 className="mb-2 text-muted text-start">
|
||||||
|
Employee Info
|
||||||
|
</h6>
|
||||||
<table className="table table-borderless mb-3">
|
<table className="table table-borderless mb-3">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="fw-medium text-start">Email:</td>
|
<td className="fw-medium text-start">Email:</td>
|
||||||
<td className="text-start">{currentEmployee?.email || <em>NA</em>}</td>
|
<td className="text-start">
|
||||||
|
{currentEmployee?.email || <em>NA</em>}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="fw-medium text-start">Phone Number:</td>
|
<td className="fw-medium text-start">
|
||||||
<td className="text-start">{currentEmployee?.phoneNumber || <em>NA</em>}</td>
|
Phone Number:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.phoneNumber || <em>NA</em>}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="fw-medium text-start">Emergency Contact Person:</td>
|
<td className="fw-medium text-start">
|
||||||
<td className="text-start">{currentEmployee?.emergencyContactPerson || <em>NA</em>}</td>
|
Emergency Contact Person:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.emergencyContactPerson || (
|
||||||
|
<em>NA</em>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="fw-medium text-start">Emergency Contact Number:</td>
|
<td className="fw-medium text-start">
|
||||||
<td className="text-start">{currentEmployee?.emergencyPhoneNumber || <em>NA</em>}</td>
|
Emergency Contact Number:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.emergencyPhoneNumber || (
|
||||||
|
<em>NA</em>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td className="fw-medium text-start">Gender:</td>
|
<td className="fw-medium text-start">Gender:</td>
|
||||||
<td className="text-start">{currentEmployee?.gender || <em>NA</em>}</td>
|
<td className="text-start">
|
||||||
|
{currentEmployee?.gender || <em>NA</em>}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="fw-medium text-start">Birth Date:</td>
|
<td className="fw-medium text-start">
|
||||||
<td className="text-start">{currentEmployee?.birthDate ? new Date(currentEmployee.birthDate).toLocaleDateString() : <em>NA</em>}</td>
|
Birth Date:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.birthDate ? (
|
||||||
|
new Date(
|
||||||
|
currentEmployee.birthDate
|
||||||
|
).toLocaleDateString()
|
||||||
|
) : (
|
||||||
|
<em>NA</em>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td className="fw-medium text-start">Joining Date:</td>
|
<td className="fw-medium text-start">
|
||||||
<td className="text-start">{currentEmployee?.joiningDate ? new Date(currentEmployee.joiningDate).toLocaleDateString() : <em>NA</em>}</td>
|
Joining Date:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.joiningDate ? (
|
||||||
|
new Date(
|
||||||
|
currentEmployee.joiningDate
|
||||||
|
).toLocaleDateString()
|
||||||
|
) : (
|
||||||
|
<em>NA</em>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="fw-medium text-start">Job Role:</td>
|
<td className="fw-medium text-start">
|
||||||
<td className="text-start">{currentEmployee?.jobRole || <em>NA</em>}</td>
|
Job Role:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.jobRole || <em>NA</em>}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="fw-medium text-start">Address:</td>
|
<td className="fw-medium text-start">Address:</td>
|
||||||
<td className="text-start">{currentEmployee?.currentAddress || <em>NA</em>}</td>
|
<td className="text-start">
|
||||||
|
{currentEmployee?.currentAddress || <em>NA</em>}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<button className="btn btn-primary btn-block" onClick={() => navigate(`/employee/manage/${currentEmployee?.id}`)}>
|
<button
|
||||||
|
className="btn btn-primary btn-block"
|
||||||
|
onClick={() =>
|
||||||
|
navigate(`/employee/manage/${currentEmployee?.id}`)
|
||||||
|
}
|
||||||
|
>
|
||||||
Edit Profile
|
Edit Profile
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12 col-lg-8 order-2 order-lg-2 mb-4">
|
<div className="col-12 col-lg-8 order-2 order-lg-2 mb-4">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<EmployeeNav onPillClick={handlePillClick} activePill={activePill} />
|
<EmployeeNav
|
||||||
</div>
|
onPillClick={handlePillClick}
|
||||||
<div className="card">
|
activePill={activePill}
|
||||||
<div className="row row-bordered g-0">
|
/>
|
||||||
{renderContent()}
|
</div>
|
||||||
|
<div className="card">
|
||||||
|
<div className="row row-bordered g-0">{renderContent()}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -83,7 +83,7 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => {
|
|||||||
currentItems.map((item, index) => (
|
currentItems.map((item, index) => (
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
<td style={{ width: "20px" }}>
|
<td style={{ width: "20px" }}>
|
||||||
<i class="bx bx-right-arrow-alt"></i>
|
<i className="bx bx-right-arrow-alt"></i>
|
||||||
</td>
|
</td>
|
||||||
{updatedColumns.map((col) => (
|
{updatedColumns.map((col) => (
|
||||||
<td className="text-start mx-2" key={col.key}>
|
<td className="text-start mx-2" key={col.key}>
|
||||||
|
|||||||
@ -21,8 +21,7 @@ axiosClient.interceptors.request.use(
|
|||||||
if (token) {
|
if (token) {
|
||||||
config.headers["Authorization"] = `Bearer ${token}`;
|
config.headers["Authorization"] = `Bearer ${token}`;
|
||||||
config._retry = true;
|
config._retry = true;
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
config._retry = false;
|
config._retry = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,7 +36,6 @@ axiosClient.interceptors.response.use(
|
|||||||
(response) => response,
|
(response) => response,
|
||||||
|
|
||||||
async (error) => {
|
async (error) => {
|
||||||
|
|
||||||
const originalRequest = error.config;
|
const originalRequest = error.config;
|
||||||
|
|
||||||
if (!originalRequest) {
|
if (!originalRequest) {
|
||||||
@ -85,13 +83,13 @@ axiosClient.interceptors.response.use(
|
|||||||
// else {
|
// else {
|
||||||
// // showToast(error.response.data.message, "error"); // repeted toast
|
// // showToast(error.response.data.message, "error"); // repeted toast
|
||||||
// }
|
// }
|
||||||
if (error.response.status === 401 && !originalRequest._retry) {
|
if (error.response.status === 401) {
|
||||||
originalRequest._retry = true;
|
originalRequest._retry = true;
|
||||||
try {
|
try {
|
||||||
// Get the refresh token from secure storage
|
// Get the refresh token from secure storage
|
||||||
const refreshToken = localStorage.getItem("refreshToken");
|
const refreshToken = localStorage.getItem("refreshToken");
|
||||||
|
|
||||||
if (!refreshToken) {
|
if (!refreshToken || error.response.data.errors === "Invalid or expired refresh token.") {
|
||||||
// Redirect to login if refresh token is not available
|
// Redirect to login if refresh token is not available
|
||||||
redirectToLogin();
|
redirectToLogin();
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
@ -116,7 +114,6 @@ axiosClient.interceptors.response.use(
|
|||||||
// Retry the original request
|
// Retry the original request
|
||||||
return axiosClient(originalRequest);
|
return axiosClient(originalRequest);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
||||||
// Redirect to login if token refresh fails
|
// Redirect to login if token refresh fails
|
||||||
redirectToLogin();
|
redirectToLogin();
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
@ -192,5 +189,5 @@ export const api = {
|
|||||||
};
|
};
|
||||||
//export default axiosClient;
|
//export default axiosClient;
|
||||||
function redirectToLogin() {
|
function redirectToLogin() {
|
||||||
// window.location.href = "/auth/login";
|
window.location.href = "/auth/login";
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user