Compare commits
6 Commits
3a2fcf71ee
...
8460460caf
Author | SHA1 | Date | |
---|---|---|---|
8460460caf | |||
c8273070ac | |||
dc4e48ad3b | |||
20b508bebc | |||
05c01d1d34 | |||
073897156e |
@ -223,50 +223,6 @@ const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizat
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
{!loading && finalFilteredData.length > ITEMS_PER_PAGE && (
|
||||
<nav aria-label="Page ">
|
||||
<ul className="pagination pagination-sm justify-content-end py-1">
|
||||
<li
|
||||
className={`page-item ${currentPage === 1 ? "disabled" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className="page-link btn-xs"
|
||||
onClick={() => paginate(currentPage - 1)}
|
||||
>
|
||||
«
|
||||
</button>
|
||||
</li>
|
||||
{[...Array(totalPages)].map((_, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className={`page-item ${currentPage === index + 1 ? "active" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className="page-link "
|
||||
onClick={() => paginate(index + 1)}
|
||||
>
|
||||
{index + 1}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
<li
|
||||
className={`page-item ${currentPage === totalPages ? "disabled" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className="page-link "
|
||||
onClick={() => paginate(currentPage + 1)}
|
||||
>
|
||||
»
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div
|
||||
@ -281,6 +237,48 @@ const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizat
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!loading && finalFilteredData.length > ITEMS_PER_PAGE && (
|
||||
<nav aria-label="Page ">
|
||||
<ul className="pagination pagination-sm justify-content-end py-1">
|
||||
<li
|
||||
className={`page-item ${currentPage === 1 ? "disabled" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className="page-link btn-xs"
|
||||
onClick={() => paginate(currentPage - 1)}
|
||||
>
|
||||
«
|
||||
</button>
|
||||
</li>
|
||||
{[...Array(totalPages)].map((_, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className={`page-item ${currentPage === index + 1 ? "active" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className="page-link "
|
||||
onClick={() => paginate(index + 1)}
|
||||
>
|
||||
{index + 1}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
<li
|
||||
className={`page-item ${currentPage === totalPages ? "disabled" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className="page-link "
|
||||
onClick={() => paginate(currentPage + 1)}
|
||||
>
|
||||
»
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -15,6 +15,7 @@ import AttendanceRepository from "../../repositories/AttendanceRepository";
|
||||
import { useAttendancesLogs } from "../../hooks/useAttendance";
|
||||
import { queryClient } from "../../layouts/AuthLayout";
|
||||
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const usePagination = (data, itemsPerPage) => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
@ -44,6 +45,7 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [showPending, setShowPending] = useState(false);
|
||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
@ -172,15 +174,15 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="dataTables_length text-start py-2 d-flex justify-content-between "
|
||||
className="dataTables_length text-start py-2 d-flex flex-wrap justify-content-between"
|
||||
id="DataTables_Table_0_length"
|
||||
>
|
||||
<div className="d-flex align-items-center my-0 ">
|
||||
<div className="d-flex flex-wrap align-items-center my-0 gap-2">
|
||||
<DateRangePicker
|
||||
onRangeChange={setDateRange}
|
||||
defaultStartDate={yesterday}
|
||||
/>
|
||||
<div className="form-check form-switch text-start ms-1 ms-md-2 align-items-center mb-0">
|
||||
<div className="form-check form-switch text-start d-flex align-items-center mb-0">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="form-check-input"
|
||||
@ -190,10 +192,11 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
||||
checked={showPending}
|
||||
onChange={(e) => setShowPending(e.target.checked)}
|
||||
/>
|
||||
<label className="form-check-label ms-0">Pending Attendance</label>
|
||||
<label className="form-check-label ms-2 mb-0">Pending Attendance</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="table-responsive text-nowrap"
|
||||
style={{ minHeight: "200px" }}
|
||||
@ -260,7 +263,12 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
||||
lastName={attendance.lastName}
|
||||
/>
|
||||
<div className="d-flex flex-column">
|
||||
<a href="#" className="text-heading text-truncate">
|
||||
<a
|
||||
onClick={() =>
|
||||
navigate(`/employee/${attendance.employeeId}?for=attendance`)
|
||||
}
|
||||
className="text-heading text-truncate cursor-pointer"
|
||||
>
|
||||
<span className="fw-normal">
|
||||
{attendance.firstName} {attendance.lastName}
|
||||
</span>
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
} from "../../slices/apiDataManager";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import Pagination from "../../components/common/Pagination";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const Regularization = ({
|
||||
handleRequest,
|
||||
@ -26,6 +27,7 @@ const Regularization = ({
|
||||
// var selectedProject = useSelector((store) => store.localVariables.projectId);
|
||||
const selectedProject = useSelectedProject();
|
||||
const [regularizesList, setregularizedList] = useState([]);
|
||||
const navigate = useNavigate();
|
||||
const { regularizes, loading, error, refetch } = useRegularizationRequests(
|
||||
selectedProject,
|
||||
organizationId,
|
||||
@ -33,9 +35,9 @@ const Regularization = ({
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if(!regularizes) return
|
||||
if(regularizes?.length) {
|
||||
setregularizedList(regularizes);
|
||||
if (!regularizes) return
|
||||
if (regularizes?.length) {
|
||||
setregularizedList(regularizes);
|
||||
|
||||
}
|
||||
}, [regularizes]);
|
||||
@ -102,141 +104,106 @@ const Regularization = ({
|
||||
}, [employeeHandler]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="table-responsive text-nowrap pb-4"
|
||||
style={{ minHeight: "200px" }}
|
||||
>
|
||||
{loading ? (
|
||||
<div
|
||||
className="d-flex justify-content-center align-items-center"
|
||||
style={{ height: "200px" }}
|
||||
>
|
||||
<p className="text-secondary">Loading...</p>
|
||||
</div>
|
||||
) : currentItems?.length > 0 ? (
|
||||
<table className="table mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colSpan={2}>Name</th>
|
||||
<th>Date</th>
|
||||
<th>Organization</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 colSpan={2}>
|
||||
Requested By
|
||||
</th>
|
||||
<th >
|
||||
Requested At
|
||||
</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{currentItems?.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} />
|
||||
<div className="d-flex flex-column">
|
||||
<a href="#" className="text-heading text-truncate">
|
||||
<div>
|
||||
<div
|
||||
className="table-responsive pt-3 text-nowrap pb-4"
|
||||
style={{ minHeight: "200px" }}
|
||||
>
|
||||
{loading ? (
|
||||
<div
|
||||
className="d-flex justify-content-center align-items-center"
|
||||
style={{ height: "200px" }}
|
||||
>
|
||||
<p className="text-secondary">Loading...</p>
|
||||
</div>
|
||||
) : currentItems?.length > 0 ? (
|
||||
<table className="table mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colSpan={2}>Name</th>
|
||||
<th>Date</th>
|
||||
<th>Organization</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 colSpan={2}>
|
||||
Requested By
|
||||
</th>
|
||||
<th >
|
||||
Requested At
|
||||
</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{currentItems?.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} />
|
||||
<div className="d-flex flex-column"> <a
|
||||
onClick={() =>
|
||||
navigate(`/employee/${att.employeeId}?for=attendance`)
|
||||
}
|
||||
className="text-heading text-truncate cursor-pointer" >
|
||||
<span className="fw-normal">
|
||||
{att.firstName} {att.lastName}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>{moment(att.checkOutTime).format("DD-MMM-YYYY")}</td>
|
||||
</td>
|
||||
<td>{moment(att.checkOutTime).format("DD-MMM-YYYY")}</td>
|
||||
|
||||
<td>{att.organizationName || "--"}</td>
|
||||
<td>{att.organizationName || "--"}</td>
|
||||
|
||||
<td>{convertShortTime(att.checkInTime)}</td>
|
||||
<td>
|
||||
{att.requestedAt ? convertShortTime(att.checkOutTime) : "--"}
|
||||
</td>
|
||||
<td>{convertShortTime(att.checkInTime)}</td>
|
||||
<td>
|
||||
{att.requestedAt ? convertShortTime(att.checkOutTime) : "--"}
|
||||
</td>
|
||||
|
||||
<td colSpan={2}>
|
||||
{att.requestedBy ? ( <div className="d-flex justify-content-start align-items-center">
|
||||
<Avatar firstName={att?.requestedBy?.firstName} lastName={att?.requestedBy?.lastName} />
|
||||
<div className="d-flex flex-column">
|
||||
<a href="#" className="text-heading text-truncate">
|
||||
<span className="fw-normal">
|
||||
{att?.requestedBy?.firstName} {att?.requestedBy?.lastName}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>):(<small>--</small>)}
|
||||
</td>
|
||||
{att.requestedBy ? (<div className="d-flex justify-content-start align-items-center">
|
||||
<Avatar firstName={att?.requestedBy?.firstName} lastName={att?.requestedBy?.lastName} />
|
||||
<div className="d-flex flex-column">
|
||||
<a href="#" className="text-heading text-truncate">
|
||||
<span className="fw-normal">
|
||||
{att?.requestedBy?.firstName} {att?.requestedBy?.lastName}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>) : (<small>--</small>)}
|
||||
</td>
|
||||
<td>
|
||||
{att?.requestedAt ? formatUTCToLocalTime(att.requestedAt,true) : "--"}
|
||||
</td>
|
||||
<td className="text-center ">
|
||||
<RegularizationActions
|
||||
attendanceData={att}
|
||||
handleRequest={handleRequest}
|
||||
refresh={refetch}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
) : (
|
||||
<div
|
||||
className="d-flex justify-content-center align-items-center"
|
||||
style={{ height: "200px" }}
|
||||
>
|
||||
<span className="text-secondary">
|
||||
{searchTerm
|
||||
? "No results found for your search."
|
||||
: "No Requests Found !"}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{/* {!loading && totalPages > 1 && (
|
||||
<nav aria-label="Page ">
|
||||
<ul className="pagination pagination-sm justify-content-end py-1 mt-3">
|
||||
<li className={`page-item ${currentPage === 1 ? "disabled" : ""}`}>
|
||||
<button
|
||||
className="page-link btn-xs"
|
||||
onClick={() => paginate(currentPage - 1)}
|
||||
>
|
||||
«
|
||||
</button>
|
||||
</li>
|
||||
{[...Array(totalPages)].map((_, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className={`page-item ${currentPage === index + 1 ? "active" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className="page-link "
|
||||
onClick={() => paginate(index + 1)}
|
||||
>
|
||||
{index + 1}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
<li
|
||||
className={`page-item ${currentPage === totalPages ? "disabled" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className="page-link "
|
||||
onClick={() => paginate(currentPage + 1)}
|
||||
>
|
||||
»
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
)} */}
|
||||
|
||||
{att?.requestedAt ? formatUTCToLocalTime(att.requestedAt, true) : "--"}
|
||||
</td>
|
||||
<td className="text-center ">
|
||||
<RegularizationActions
|
||||
attendanceData={att}
|
||||
handleRequest={handleRequest}
|
||||
refresh={refetch}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
) : (
|
||||
<div
|
||||
className="d-flex justify-content-center align-items-center"
|
||||
style={{ height: "200px" }}
|
||||
>
|
||||
<span className="text-secondary">
|
||||
{searchTerm
|
||||
? "No results found for your search."
|
||||
: "No Requests Found !"}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{totalPages > 0 && (
|
||||
<Pagination
|
||||
currentPage={currentPage}
|
||||
@ -244,6 +211,7 @@ const Regularization = ({
|
||||
onPageChange={paginate}
|
||||
/>
|
||||
)}
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -29,7 +29,7 @@ const TaskReportList = () => {
|
||||
const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK);
|
||||
const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK);
|
||||
|
||||
const { service, openModal, closeModal,filter } = useDailyProgrssContext();
|
||||
const { service, openModal, closeModal, filter } = useDailyProgrssContext();
|
||||
const selectedProject = useSelectedProject();
|
||||
const { projectNames } = useProjectName();
|
||||
|
||||
@ -37,7 +37,7 @@ const TaskReportList = () => {
|
||||
selectedProject,
|
||||
ITEMS_PER_PAGE,
|
||||
currentPage,
|
||||
service,filter
|
||||
service, filter
|
||||
);
|
||||
|
||||
const ProgrssReportColumn = [
|
||||
@ -192,109 +192,114 @@ const TaskReportList = () => {
|
||||
if (isLoading) return <TaskReportListSkeleton />;
|
||||
if (isError) return <div>Loading....</div>;
|
||||
return (
|
||||
<div className="mt-2 table-responsive text-nowrap">
|
||||
<table className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-start">Activity</th>
|
||||
<th>
|
||||
<span>
|
||||
Total Pending{" "}
|
||||
<HoverPopup
|
||||
title="Total Pending Task"
|
||||
content={<p>This shows the total pending tasks for each activity on that date.</p>}
|
||||
>
|
||||
<i className="bx bx-xs ms-1 bx-info-circle cursor-pointer"></i>
|
||||
</HoverPopup>
|
||||
</span>
|
||||
</th>
|
||||
<th>
|
||||
<span>
|
||||
Reported/Planned{" "}
|
||||
<HoverPopup
|
||||
title="Reported and Planned Task"
|
||||
content={<p>This shows the reported versus planned tasks for each activity on that date.</p>}
|
||||
>
|
||||
<i className="bx bx-xs ms-1 bx-info-circle cursor-pointer"></i>
|
||||
</HoverPopup>
|
||||
</span>
|
||||
</th>
|
||||
<th>Assign Date</th>
|
||||
<th>Team</th>
|
||||
<th className="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{groupedTasks.length === 0 && (
|
||||
<div>
|
||||
<div className="mt-2 table-responsive text-nowrap">
|
||||
<table className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td colSpan={6} className="text-center align-middle" style={{ height: "200px", borderBottom: "none" }}>
|
||||
No reports available
|
||||
</td>
|
||||
<th className="text-start">Activity</th>
|
||||
<th>
|
||||
<span>
|
||||
Total Pending{" "}
|
||||
<HoverPopup
|
||||
title="Total Pending Task"
|
||||
content={<p>This shows the total pending tasks for each activity on that date.</p>}
|
||||
>
|
||||
<i className="bx bx-xs ms-1 bx-info-circle cursor-pointer"></i>
|
||||
</HoverPopup>
|
||||
</span>
|
||||
</th>
|
||||
<th>
|
||||
<span>
|
||||
Reported/Planned{" "}
|
||||
<HoverPopup
|
||||
title="Reported and Planned Task"
|
||||
content={<p>This shows the reported versus planned tasks for each activity on that date.</p>}
|
||||
>
|
||||
<i className="bx bx-xs ms-1 bx-info-circle cursor-pointer"></i>
|
||||
</HoverPopup>
|
||||
</span>
|
||||
</th>
|
||||
<th>Assign Date</th>
|
||||
<th>Team</th>
|
||||
<th className="text-center">Actions</th>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
{groupedTasks.map(({ date, tasks }) => (
|
||||
<React.Fragment key={date}>
|
||||
<tr className="table-row-header text-start">
|
||||
<td colSpan={6}>
|
||||
<strong>{formatUTCToLocalTime(date)}</strong>
|
||||
</thead>
|
||||
<tbody>
|
||||
{groupedTasks.length === 0 && (
|
||||
<tr>
|
||||
<td colSpan={6} className="text-center align-middle" style={{ height: "200px", borderBottom: "none" }}>
|
||||
No reports available
|
||||
</td>
|
||||
</tr>
|
||||
{tasks.map((task, idx) => (
|
||||
<tr key={task.id || idx}>
|
||||
<td className="flex-wrap text-start">
|
||||
<div>
|
||||
{task.workItem.activityMaster?.activityName || "No Activity Name"}
|
||||
</div>
|
||||
<div className="text-sm py-2">
|
||||
{task.workItem.workArea?.floor?.building?.name} ›{" "}
|
||||
{task.workItem.workArea?.floor?.floorName} ›{" "}
|
||||
{task.workItem.workArea?.areaName}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{formatNumber(task.workItem.plannedWork)}
|
||||
</td>
|
||||
<td>{`${formatNumber(task.completedTask)} / ${formatNumber(task.plannedTask)}`}</td>
|
||||
<td>{formatUTCToLocalTime(task.assignmentDate)}</td>
|
||||
<td className="text-center">{renderTeamMembers(task, idx)}</td>
|
||||
<td className="text-center">
|
||||
<div className="d-flex justify-content-end gap-2">
|
||||
{ReportTaskRights && !task.reportedDate && (
|
||||
<button className="btn btn-xs btn-primary" onClick={() => openModal("report", task)}>
|
||||
Report
|
||||
</button>
|
||||
)}
|
||||
{ApprovedTaskRights && task.reportedDate && !task.approvedBy && (
|
||||
<button
|
||||
className="btn btn-xs btn-warning"
|
||||
onClick={() => openModal("comments", { task, isActionAllow: true })}
|
||||
>
|
||||
QC
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
className="btn btn-xs btn-primary"
|
||||
onClick={() => openModal("comments", { task, isActionAllow: false })}
|
||||
>
|
||||
Comment
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{groupedTasks.map(({ date, tasks }) => (
|
||||
<React.Fragment key={date}>
|
||||
<tr className="table-row-header text-start">
|
||||
<td colSpan={6}>
|
||||
<strong>{formatUTCToLocalTime(date)}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
{data?.data?.length > 0 && (
|
||||
<Pagination
|
||||
currentPage={currentPage}
|
||||
totalPages={data.totalPages}
|
||||
onPageChange={paginate}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{tasks.map((task, idx) => (
|
||||
<tr key={task.id || idx}>
|
||||
<td className="flex-wrap text-start">
|
||||
<div>
|
||||
{task.workItem.activityMaster?.activityName || "No Activity Name"}
|
||||
</div>
|
||||
<div className="text-sm py-2">
|
||||
{task.workItem.workArea?.floor?.building?.name} ›{" "}
|
||||
{task.workItem.workArea?.floor?.floorName} ›{" "}
|
||||
{task.workItem.workArea?.areaName}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{formatNumber(task.workItem.plannedWork)}
|
||||
</td>
|
||||
<td>{`${formatNumber(task.completedTask)} / ${formatNumber(task.plannedTask)}`}</td>
|
||||
<td>{formatUTCToLocalTime(task.assignmentDate)}</td>
|
||||
<td className="text-center">{renderTeamMembers(task, idx)}</td>
|
||||
<td className="text-center">
|
||||
<div className="d-flex justify-content-end gap-2">
|
||||
{ReportTaskRights && !task.reportedDate && (
|
||||
<button className="btn btn-xs btn-primary" onClick={() => openModal("report", task)}>
|
||||
Report
|
||||
</button>
|
||||
)}
|
||||
{ApprovedTaskRights && task.reportedDate && !task.approvedBy && (
|
||||
<button
|
||||
className="btn btn-xs btn-warning"
|
||||
onClick={() => openModal("comments", { task, isActionAllow: true })}
|
||||
>
|
||||
QC
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
className="btn btn-xs btn-primary"
|
||||
onClick={() => openModal("comments", { task, isActionAllow: false })}
|
||||
>
|
||||
Comment
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
{
|
||||
data?.data?.length > 0 && (
|
||||
<Pagination
|
||||
currentPage={currentPage}
|
||||
totalPages={data.totalPages}
|
||||
onPageChange={paginate}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div >
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -160,8 +160,7 @@ const ListViewContact = ({ data, Pagination }) => {
|
||||
</div>
|
||||
) : (
|
||||
<i
|
||||
className={`bx ${
|
||||
isPending && activeContact === row.id
|
||||
className={`bx ${isPending && activeContact === row.id
|
||||
? "bx-loader-alt bx-spin"
|
||||
: "bx-recycle"
|
||||
} me-1 text-primary cursor-pointer`}
|
||||
@ -188,13 +187,13 @@ const ListViewContact = ({ data, Pagination }) => {
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
{Pagination && (
|
||||
<div className="d-flex justify-content-start">
|
||||
{Pagination}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{Pagination && (
|
||||
<div className="d-flex justify-content-start">
|
||||
{Pagination}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -15,6 +15,7 @@ import { ExpenseTableSkeleton } from "./ExpenseSkeleton";
|
||||
import ConfirmModal from "../common/ConfirmModal";
|
||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
const [deletingId, setDeletingId] = useState(null);
|
||||
@ -24,6 +25,7 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
const IsExpesneApprpve = useHasUserPermission(APPROVE_EXPENSE);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const debouncedSearch = useDebounce(searchText, 500);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { mutate: DeleteExpense, isPending } = useDeleteExpense();
|
||||
const { data, isLoading, isError, isInitialLoading, error } = useExpenseList(
|
||||
@ -67,9 +69,8 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
key = item.status?.displayName || "Unknown";
|
||||
break;
|
||||
case "submittedBy":
|
||||
key = `${item.createdBy?.firstName ?? ""} ${
|
||||
item.createdBy?.lastName ?? ""
|
||||
}`.trim();
|
||||
key = `${item.createdBy?.firstName ?? ""} ${item.createdBy?.lastName ?? ""
|
||||
}`.trim();
|
||||
break;
|
||||
case "project":
|
||||
key = item.project?.name || "Unknown Project";
|
||||
@ -110,11 +111,11 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
label: "Submitted By",
|
||||
align: "text-start",
|
||||
getValue: (e) =>
|
||||
`${e.createdBy?.firstName ?? ""} ${
|
||||
e.createdBy?.lastName ?? ""
|
||||
}`.trim() || "N/A",
|
||||
`${e.createdBy?.firstName ?? ""} ${e.createdBy?.lastName ?? ""
|
||||
}`.trim() || "N/A",
|
||||
customRender: (e) => (
|
||||
<div className="d-flex align-items-center">
|
||||
<div className="d-flex align-items-center cursor-pointer"
|
||||
onClick={() => navigate(`/employee/${e.createdBy?.id}`)}>
|
||||
<Avatar
|
||||
size="xs"
|
||||
classAvatar="m-0"
|
||||
@ -122,9 +123,8 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
lastName={e.createdBy?.lastName}
|
||||
/>
|
||||
<span className="text-truncate">
|
||||
{`${e.createdBy?.firstName ?? ""} ${
|
||||
e.createdBy?.lastName ?? ""
|
||||
}`.trim() || "N/A"}
|
||||
{`${e.createdBy?.firstName ?? ""} ${e.createdBy?.lastName ?? ""
|
||||
}`.trim() || "N/A"}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
@ -152,9 +152,8 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
align: "text-center",
|
||||
getValue: (e) => (
|
||||
<span
|
||||
className={`badge bg-label-${
|
||||
getColorNameFromHex(e?.status?.color) || "secondary"
|
||||
}`}
|
||||
className={`badge bg-label-${getColorNameFromHex(e?.status?.color) || "secondary"
|
||||
}`}
|
||||
>
|
||||
{e.status?.name || "Unknown"}
|
||||
</span>
|
||||
@ -299,15 +298,15 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
{data?.data?.length > 0 && (
|
||||
<Pagination
|
||||
currentPage={currentPage}
|
||||
totalPages={data.totalPages}
|
||||
onPageChange={paginate}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{data?.data?.length > 0 && (
|
||||
<Pagination
|
||||
currentPage={currentPage}
|
||||
totalPages={data.totalPages}
|
||||
onPageChange={paginate}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -179,44 +179,40 @@ const AttendancePage = () => {
|
||||
</div>
|
||||
|
||||
{/* Search + Organization filter */}
|
||||
<div className="col-12 col-md-auto mt-2 mt-md-0 ms-md-auto d-flex gap-2 align-items-center">
|
||||
{/* Organization Dropdown */}
|
||||
<div className="row">
|
||||
<div className="col-12 col-sm-6 mb-2 mb-sm-0">
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
value={appliedFilters.selectedOrganization}
|
||||
onChange={(e) =>
|
||||
setAppliedFilters((prev) => ({
|
||||
...prev,
|
||||
selectedOrganization: e.target.value,
|
||||
}))
|
||||
}
|
||||
disabled={orgLoading}
|
||||
>
|
||||
<option value="">All Organizations</option>
|
||||
{organizations?.map((org, ind) => (
|
||||
<option key={`${org.id}-${ind}`} value={org.id}>
|
||||
{org.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<div className="col-12 col-md-auto mt-2 mt-md-0 ms-md-auto">
|
||||
<div className="row g-2">
|
||||
<div className="col-12 col-sm-6">
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
value={appliedFilters.selectedOrganization}
|
||||
onChange={(e) =>
|
||||
setAppliedFilters((prev) => ({
|
||||
...prev,
|
||||
selectedOrganization: e.target.value,
|
||||
}))
|
||||
}
|
||||
disabled={orgLoading}
|
||||
>
|
||||
<option value="">All Organizations</option>
|
||||
{organizations?.map((org, ind) => (
|
||||
<option key={`${org.id}-${ind}`} value={org.id}>
|
||||
{org.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="col-12 col-sm-6">
|
||||
{/* Search Input */}
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search Employee..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search Employee..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -224,7 +220,7 @@ const AttendancePage = () => {
|
||||
{selectedProject ? (
|
||||
<>
|
||||
{activeTab === "all" && (
|
||||
<div className="tab-pane fade show active py-0 mx-5">
|
||||
<div className="tab-pane fade show active py-0 mx-2">
|
||||
<Attendance
|
||||
handleModalData={handleModalData}
|
||||
getRole={getRole}
|
||||
@ -234,7 +230,7 @@ const AttendancePage = () => {
|
||||
</div>
|
||||
)}
|
||||
{activeTab === "logs" && (
|
||||
<div className="tab-pane fade show active py-0">
|
||||
<div className="tab-pane fade p-3 show active py-0">
|
||||
<AttendanceLog
|
||||
handleModalData={handleModalData}
|
||||
searchTerm={searchTerm}
|
||||
@ -243,7 +239,7 @@ const AttendancePage = () => {
|
||||
</div>
|
||||
)}
|
||||
{activeTab === "regularization" && DoRegularized && (
|
||||
<div className="tab-pane fade show active py-0">
|
||||
<div className="tab-pane fade p-3 show active py-0">
|
||||
<Regularization
|
||||
searchTerm={searchTerm}
|
||||
organizationId={appliedFilters.selectedOrganization}
|
||||
|
@ -650,16 +650,15 @@ const EmployeeList = () => {
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{displayData?.length > 0 && (
|
||||
</div>
|
||||
</div>
|
||||
{displayData?.length > 0 && (
|
||||
<Pagination
|
||||
currentPage={currentPage}
|
||||
totalPages={totalPages}
|
||||
onPageChange={paginate}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="card">
|
||||
|
Loading…
x
Reference in New Issue
Block a user