212 lines
7.7 KiB
JavaScript
212 lines
7.7 KiB
JavaScript
import React, { createContext, useContext, useEffect, useState } from "react";
|
|
import Breadcrumb from "../../components/common/Breadcrumb";
|
|
import {
|
|
ITEMS_PER_PAGE,
|
|
MANAGE_PROJECT,
|
|
PROJECT_STATUS,
|
|
} from "../../utils/constants";
|
|
import ProjectListView from "../../components/Project/ProjectListView";
|
|
import GlobalModel from "../../components/common/GlobalModel";
|
|
import ManageProjectInfo from "../../components/Project/ManageProjectInfo";
|
|
import ProjectCardView from "../../components/Project/ProjectCardView";
|
|
import usePagination from "../../hooks/usePagination";
|
|
import { useProjects } from "../../hooks/useProjects";
|
|
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
|
import { SpinnerLoader } from "../../components/common/Loader";
|
|
import { useServiceProjects } from "../../hooks/useServiceProject";
|
|
import ManageServiceProject from "../../components/ServiceProject/ManageServiceProject";
|
|
import ProjectsDisplay from "./ProjectsDisplay";
|
|
import ServiceProjectDisplay from "../ServiceProject/ServiceProjectDisplay";
|
|
|
|
const ProjectContext = createContext();
|
|
export const useProjectContext = () => {
|
|
const context = useContext(ProjectContext);
|
|
if (!context) {
|
|
throw new Error("useProjectContext must be used within an ProjectProvider");
|
|
}
|
|
return context;
|
|
};
|
|
|
|
const ProjectPage = () => {
|
|
const [manageProject, setMangeProject] = useState({
|
|
isOpen: false,
|
|
project: null,
|
|
});
|
|
const [manageServiceProject, setManageServiceProject] = useState({
|
|
isOpen: false,
|
|
project: null,
|
|
});
|
|
|
|
const [projectList, setProjectList] = useState([]);
|
|
const [listView, setListView] = useState(false);
|
|
const [searchTerm, setSearchTerm] = useState("");
|
|
const [coreProjects, setCoreProjects] = useState(() => {
|
|
const storedValue = sessionStorage.getItem('whichProjectDisplay');
|
|
return storedValue === 'true';
|
|
});
|
|
const HasManageProject = useHasUserPermission(MANAGE_PROJECT);
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
|
|
|
|
const [selectedStatuses, setSelectedStatuses] = useState(
|
|
PROJECT_STATUS.map((s) => s.id)
|
|
);
|
|
const handleStatusChange = (statusId) => {
|
|
setSelectedStatuses((prev) =>
|
|
prev.includes(statusId)
|
|
? prev.filter((id) => id !== statusId)
|
|
: [...prev, statusId]
|
|
);
|
|
};
|
|
|
|
const contextDispatcher = {
|
|
setMangeProject,
|
|
setManageServiceProject,
|
|
manageProject,
|
|
manageServiceProject,
|
|
};
|
|
|
|
|
|
const handleToggleProject = (value) => {
|
|
setCoreProjects(value);
|
|
sessionStorage.setItem("whichProjectDisplay", String(value));
|
|
};
|
|
|
|
|
|
return (
|
|
<ProjectContext.Provider value={contextDispatcher}>
|
|
<div className="container-fluid">
|
|
<Breadcrumb
|
|
data={[
|
|
{ label: "Home", link: "/dashboard" },
|
|
{ label: "Projects", link: null },
|
|
]}
|
|
/>
|
|
|
|
<div className="card cursor-pointer mb-5">
|
|
<div className="card-body py-3 px-6 pb-1">
|
|
<div className="d-flex flex-wrap justify-content-between align-items-center">
|
|
{/* LEFT SIDE — DATE TOGGLE BUTTONS */}
|
|
<div className="mb-2">
|
|
<div className="d-inline-flex border rounded-pill overflow-hidden shadow-none">
|
|
{/* Service Project Button */}
|
|
<button
|
|
type="button"
|
|
className={`btn px-2 py-1 rounded-0 text-tiny ${!coreProjects ? "btn-primary text-white" : ""
|
|
}`}
|
|
onClick={() => handleToggleProject(false)}
|
|
>
|
|
Service Project
|
|
</button>
|
|
{/* Organization Project Button */}
|
|
<button
|
|
type="button"
|
|
className={`btn px-2 py-1 rounded-0 text-tiny ${coreProjects ? "btn-primary text-white" : ""
|
|
}`}
|
|
onClick={() => handleToggleProject(true)}
|
|
>
|
|
Infra Project
|
|
</button>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
{/* RIGHT SIDE — SEARCH + CARD/LIST + DROPDOWN */}
|
|
<div className="d-flex flex-wrap align-items-center justify-content-end">
|
|
|
|
{/* Search */}
|
|
<div className="me-2" style={{ minWidth: "200px" }}>
|
|
<input
|
|
type="search"
|
|
className="form-control form-control-sm"
|
|
placeholder="Search projects..."
|
|
value={searchTerm}
|
|
onChange={(e) => {
|
|
setSearchTerm(e.target.value);
|
|
setCurrentPage(1);
|
|
}}
|
|
/>
|
|
</div>
|
|
|
|
{/* Card/List Buttons */}
|
|
<div className="d-flex gap-2">
|
|
<button
|
|
type="button"
|
|
className={`btn btn-sm p-1 ${!listView ? "btn-primary" : "btn-outline-primary"}`}
|
|
onClick={() => setListView(false)}
|
|
title="Card View"
|
|
>
|
|
<i className="bx bx-grid-alt fs-5"></i>
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className={`btn btn-sm p-1 ${listView ? "btn-primary" : "btn-outline-primary"}`}
|
|
onClick={() => setListView(true)}
|
|
title="List View"
|
|
>
|
|
<i className="bx bx-list-ul fs-5"></i>
|
|
</button>
|
|
</div>
|
|
|
|
{/* Dropdown Filter */}
|
|
<div className="dropdown me-2">
|
|
<a
|
|
className="dropdown-toggle hide-arrow cursor-pointer p-1"
|
|
data-bs-toggle="dropdown"
|
|
aria-expanded="false"
|
|
title="Filter"
|
|
>
|
|
<i className="bx bx-slider-alt fs-5"></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>
|
|
|
|
{HasManageProject && (
|
|
<button
|
|
type="button"
|
|
className="btn btn-primary btn-sm d-flex align-items-center my-2"
|
|
onClick={() =>
|
|
coreProjects
|
|
? setMangeProject({ isOpen: true, Project: null }) // Organization Project → Infra
|
|
: setManageServiceProject({ isOpen: true, Project: null }) // Service Project
|
|
}
|
|
>
|
|
<i className="bx bx-plus-circle me-2"></i>
|
|
New Project
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{coreProjects ? <ProjectsDisplay listView={listView}
|
|
searchTerm={searchTerm}
|
|
selectedStatuses={selectedStatuses}
|
|
handleStatusChange={handleStatusChange} currentPage={currentPage}
|
|
setCurrentPage={setCurrentPage} /> : <ServiceProjectDisplay listView={listView} searchTerm={searchTerm}
|
|
selectedStatuses={selectedStatuses} />}
|
|
</div>
|
|
</ProjectContext.Provider>
|
|
);
|
|
};
|
|
|
|
export default ProjectPage;
|