marco.pms.web/src/components/Project/ProjectListView.jsx

282 lines
9.4 KiB
JavaScript

import React, { useState } from "react";
import { MANAGE_PROJECT, PROJECT_STATUS } from "../../utils/constants";
import { useProjects } from "../../hooks/useProjects";
import { formatNumber, formatUTCToLocalTime } from "../../utils/dateUtils";
import ProgressBar from "../common/ProgressBar";
import {
getProjectStatusColor,
getProjectStatusName,
} from "../../utils/projectStatus";
import { useDispatch } from "react-redux";
import { setProjectId } from "../../slices/localVariablesSlice";
import { useNavigate } from "react-router-dom";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { useProjectContext } from "../../pages/project/ProjectPage";
import usePagination from "../../hooks/usePagination";
const ProjectListView = ({
currentItems,
selectedStatuses,
handleStatusChange,
setCurrentPage,
totalPages,
isLoading,
}) => {
const dispatch = useDispatch();
const navigate = useNavigate();
const { setMangeProject } = useProjectContext();
// const { data, isLoading, isError, error } = useProjects();
// check Permissions
// const canManageProject = useHasUserPermission(MANAGE_PROJECT);
const projectColumns = [
{
key: "projectName",
label: "Project Name",
className: "text-start py-3",
getValue: (p) => (
<div
className="text-primary cursor-pointer fw-bold py-3"
onClick={() => {
dispatch(setProjectId(p.id));
navigate(`/projects/details`);
}}
>
{p.shortName ? `${p.name} (${p.shortName})` : p.name}
</div>
),
},
{
key: "contactPerson",
label: "Contact Person",
className: "text-start small",
getValue: (p) => `${p?.contactPerson ?? ""}`.trim() || "N/A",
},
{
key: "startDate",
label: "Start Date",
className: "text-center small",
getValue: (p) => formatUTCToLocalTime(p?.startDate) || "N/A",
},
{
key: "deadline",
label: "Deadline",
className: "text-center small",
getValue: (p) => formatUTCToLocalTime(p?.endDate) || "N/A",
},
{
key: "task",
label: "Task",
colSpan: 2,
className: "text-center small",
getValue: (p) => formatNumber(p?.plannedWork) || "0",
},
{
key: "progress",
label: "Progress",
className: "text-start small",
getValue: (p) => (
<ProgressBar
plannedWork={p.plannedWork}
completedWork={p.completedWork}
className="mb-0"
height="6px"
/>
),
},
{
key: "status",
label: "Status",
className: "text-center small",
isFilter: true,
customRender: (_, selectedStatuses, handleStatusChange) => (
<div className="dropdown">
<a
className="dropdown-toggle hide-arrow cursor-pointer"
data-bs-toggle="dropdown"
aria-expanded="false"
>
Status <i className="bx bx-filter bx-sm"></i>
</a>
<ul className="dropdown-menu p-2 text-capitalize">
{PROJECT_STATUS.map(({ id, label }) => (
<li key={id}>
<div className="form-check">
<input
className="form-check-input"
type="checkbox"
checked={selectedStatuses.includes(id)}
onChange={() => handleStatusChange(id)}
/>
<label className="form-check-label">{label}</label>
</div>
</li>
))}
</ul>
</div>
),
getValue: (p) => (
<span className={`badge ${getProjectStatusColor(p.projectStatusId)}`}>
{getProjectStatusName(p.projectStatusId)}
</span>
),
},
];
// const handleViewActivities = (project) => {
// dispatch(setProjectId(project));
// navigate(`/activities/records?project=${project}`);
// };
const handleMoveDetails = (project) => {
dispatch(setProjectId(project));
localStorage.setItem("lastActiveProjectTab", "profile")
navigate("/projects/details");
};
return (
<div className="card page-min-h py-4 px-6 shadow-sm">
<div className="table-responsive text-nowrap">
<table className="table table-hover align-middle m-0">
<thead className="border-bottom">
<tr>
{projectColumns.map((col) => (
<th key={col.key} colSpan={col.colSpan} className={col.className}>
{col.label}
</th>
))}
<th className="text-center py-3">Action</th>
</tr>
</thead>
<tbody>
{currentItems?.map((project) => (
<tr key={project.id}>
{projectColumns.map((col) => (
<td
key={col.key}
colSpan={col.colSpan}
className={`${col.className} py-5`}
style={{ paddingTop: "20px", paddingBottom: "20px" }}
>
{col.getValue
? col.getValue(project)
: project[col.key] || "N/A"}
</td>
))}
<td className={`mx-2 ${"d-sm-table-cell"}`}>
<div className="dropdown z-2">
<button
type="button"
className="btn btn-icon btn-text-secondary rounded-pill dropdown-toggle hide-arrow p-0"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<i
className="bx bx-dots-vertical-rounded bx-sm text-muted"
data-bs-toggle="tooltip"
data-bs-offset="0,8"
data-bs-placement="top"
data-bs-custom-class="tooltip-dark"
title="More Action"
></i>
</button>
<ul className="dropdown-menu dropdown-menu-end">
<li onClick={() => handleMoveDetails(project.id)}>
<a
aria-label="click to View details"
className="dropdown-item cursor-pointer"
>
<i className="bx bx-detail me-2"></i>
<span className="align-left">View details</span>
</a>
</li>
<li>
<a
className="dropdown-item cursor-pointer"
onClick={() =>
setMangeProject({
isOpen: true,
Project: project.id,
})
}
>
<i className="bx bx-pencil me-2"></i>
<span className="align-left">Modify</span>
</a>
</li>
{/* <li onClick={() => handleViewActivities(project.id)}>
<a className="dropdown-item cursor-pointer">
<i className="bx bx-task me-2"></i>
<span className="align-left">Activities</span>
</a>
</li> */}
</ul>
</div>
</td>
</tr>
))}
</tbody>
</table>
{isLoading && (
<div className="py-4">
{" "}
{isLoading && <p className="text-center">Loading...</p>}
{!isLoading && filteredProjects.length === 0 && (
<p className="text-center text-muted">No projects found.</p>
)}
</div>
)}
{!isLoading && currentItems.length === 0 && (
<div className="py-6">
<p className="text-center text-muted">No projects found.</p>
</div>
)}
{!isLoading && totalPages > 1 && (
<nav>
<ul className="pagination pagination-sm justify-content-end py-2">
<li className={`page-item ${currentPage === 1 && "disabled"}`}>
<button
className="page-link"
onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}
>
&laquo;
</button>
</li>
{[...Array(totalPages)].map((_, i) => (
<li
key={i}
className={`page-item ${currentPage === i + 1 && "active"}`}
>
<button
className="page-link"
onClick={() => setCurrentPage(i + 1)}
>
{i + 1}
</button>
</li>
))}
<li
className={`page-item ${currentPage === totalPages && "disabled"
}`}
>
<button
className="page-link"
onClick={() =>
setCurrentPage((p) => Math.min(totalPages, p + 1))
}
>
&raquo;
</button>
</li>
</ul>
</nav>
)}
</div>
</div>
);
};
export default ProjectListView;