added list view component
This commit is contained in:
parent
d9f4bc47f6
commit
c38a92b8b7
@ -17,42 +17,39 @@ const ProjectList = () => {
|
||||
const [listView, setListView] = useState(true);
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const { projects, loading, error, refetch } = useProjects();
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const [projectList, setProjectList] = useState([]);
|
||||
const HasManageProjectPermission = useHasUserPermission(MANAGE_PROJECT);
|
||||
const [HasManageProject, setHasManageProject] = useState(
|
||||
HasManageProjectPermission
|
||||
);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [itemsPerPage] = useState(6);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [selectedStatuses, setSelectedStatuses] = useState([1, 2, 3, 4]);
|
||||
|
||||
const handleShow = () => setShowModal(true);
|
||||
const handleClose = () => setShowModal(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && Array.isArray(projects)) {
|
||||
// Step 1: Group projects by statusId
|
||||
const grouped = {};
|
||||
|
||||
projects.forEach((project) => {
|
||||
const statusId = project.projectStatusId;
|
||||
if (!grouped[statusId]) {
|
||||
grouped[statusId] = [];
|
||||
}
|
||||
if (!grouped[statusId]) grouped[statusId] = [];
|
||||
grouped[statusId].push(project);
|
||||
});
|
||||
|
||||
// Step 2: Sort each group by name
|
||||
const sortedGrouped = Object.keys(grouped)
|
||||
.sort() // sort group keys (status IDs)
|
||||
.sort()
|
||||
.flatMap((statusId) =>
|
||||
grouped[statusId].sort((a, b) =>
|
||||
a.name.toLowerCase().localeCompare(b.name.toLowerCase())
|
||||
)
|
||||
);
|
||||
|
||||
setProjectList(sortedGrouped); // final sorted flat list
|
||||
setProjectList(sortedGrouped);
|
||||
}
|
||||
}, [projects, loginUser?.projects, loading]);
|
||||
|
||||
@ -67,22 +64,16 @@ const ProjectList = () => {
|
||||
const handleSubmitForm = (newProject) => {
|
||||
ProjectRepository.manageProject(newProject)
|
||||
.then((response) => {
|
||||
const cachedProjects_list = getCachedData("projectslist") || [];
|
||||
|
||||
const updated_Projects_list = [...cachedProjects_list, response.data];
|
||||
|
||||
cacheData("projectslist", updated_Projects_list);
|
||||
setProjectList((prevProjectList) => [
|
||||
...prevProjectList,
|
||||
response.data,
|
||||
]);
|
||||
|
||||
const cachedProjects = getCachedData("projectslist") || [];
|
||||
const updatedProjects = [...cachedProjects, response.data];
|
||||
cacheData("projectslist", updatedProjects);
|
||||
setProjectList((prev) => [...prev, response.data]);
|
||||
showToast("Project Created successfully.", "success");
|
||||
setShowModal(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
closeModal();
|
||||
showToast(error.message, "error");
|
||||
setShowModal(false);
|
||||
});
|
||||
};
|
||||
|
||||
@ -90,19 +81,41 @@ const ProjectList = () => {
|
||||
if (!projects || projects.length === 0) {
|
||||
refetch();
|
||||
}
|
||||
setRefresh((prev) => !prev);
|
||||
};
|
||||
|
||||
const handleStatusChange = (statusId) => {
|
||||
setCurrentPage(1);
|
||||
setSelectedStatuses((prev) =>
|
||||
prev.includes(statusId)
|
||||
? prev.filter((id) => id !== statusId)
|
||||
: [...prev, statusId]
|
||||
);
|
||||
};
|
||||
|
||||
const handleStatusFilterFromChild = (statusesFromChild) => {
|
||||
setSelectedStatuses(statusesFromChild);
|
||||
};
|
||||
|
||||
const filteredProjects = projectList.filter((project) => {
|
||||
const matchesStatus = selectedStatuses.includes(project.projectStatusId);
|
||||
const matchesSearch = project.name
|
||||
.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase());
|
||||
return matchesStatus && matchesSearch;
|
||||
});
|
||||
|
||||
const indexOfLastItem = currentPage * itemsPerPage;
|
||||
const indexOfFirstItem = indexOfLastItem - itemsPerPage;
|
||||
const currentItems = Array.isArray(projectList)
|
||||
? projectList.slice(indexOfFirstItem, indexOfLastItem)
|
||||
: [];
|
||||
const currentItems = filteredProjects.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
);
|
||||
const totalPages = Math.ceil( filteredProjects.length / itemsPerPage );
|
||||
|
||||
const paginate = (pageNumber) => setCurrentPage(pageNumber);
|
||||
const totalPages = Array.isArray(projectList)
|
||||
? Math.ceil(projectList.length / itemsPerPage)
|
||||
: 0;
|
||||
useEffect(() => {
|
||||
const tooltipTriggerList = Array.from(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
tooltipTriggerList.forEach((el) => new bootstrap.Tooltip(el));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -117,7 +130,7 @@ const ProjectList = () => {
|
||||
project={null}
|
||||
handleSubmitForm={handleSubmitForm}
|
||||
onClose={handleClose}
|
||||
></ManageProjectInfo>
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="container-xxl flex-grow-1 container-p-y">
|
||||
@ -126,55 +139,54 @@ const ProjectList = () => {
|
||||
{ label: "Home", link: "/dashboard" },
|
||||
{ label: "Projects", link: null },
|
||||
]}
|
||||
></Breadcrumb>
|
||||
/>
|
||||
|
||||
<div className="d-flex justify-content-between mb-4">
|
||||
{/* <div
|
||||
className={`col-md-12 col-lg-12 col-xl-12 order-0 mb-4 ${
|
||||
!error && !projects ? "text-center" : "text-end"
|
||||
}`}
|
||||
>
|
||||
<div className="d-flex flex-wrap justify-content-between align-items-start mb-4">
|
||||
<div className="d-flex flex-wrap align-items-start">
|
||||
<div className="flex-grow-1 me-2 mb-2">
|
||||
<input
|
||||
type="search"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search projects..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => {
|
||||
setSearchTerm(e.target.value);
|
||||
setCurrentPage(1);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
</div> */}
|
||||
|
||||
<div>
|
||||
<div
|
||||
id="DataTables_Table_0_filter"
|
||||
className="dataTables_filter d-flex justify-content-start"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
type="search"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search"
|
||||
aria-controls="DataTables_Table_0"
|
||||
></input>
|
||||
</label>
|
||||
<div className="d-flex gap-2 mb-2">
|
||||
<button
|
||||
type="button"
|
||||
className={`btn btn-icon btn-sm ms-2 p-0 ${ listView ? "btn-secondary" : "btn-label-secondary" }`}
|
||||
onClick={()=>setListView(!listView)}
|
||||
className={`btn btn-sm ${
|
||||
listView ? "btn-primary" : "btn-outline-primary"
|
||||
}`}
|
||||
onClick={() => setListView( true )}
|
||||
data-bs-toggle="tooltip" data-bs-offset="0,8" data-bs-placement="top" data-bs-custom-class="tooltip" title="List View"
|
||||
>
|
||||
<span class="bx bx-list-ul"></span>
|
||||
<i className="bx bx-list-ul"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className={`btn btn-icon btn-sm ms-2 p-0 ${ listView ? "btn-label-secondary" : "btn-secondary" }`}
|
||||
onClick={()=>setListView(!listView)}
|
||||
className={`btn btn-sm ${
|
||||
!listView ? "btn-primary" : "btn-outline-primary"
|
||||
}`}
|
||||
onClick={() => setListView( false )}
|
||||
data-bs-toggle="tooltip" data-bs-offset="0,8" data-bs-placement="top" data-bs-custom-class="tooltip" title="Card View"
|
||||
>
|
||||
<span class="bx bx-grid-alt"></span>
|
||||
<i className="bx bx-grid-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
className={`btn btn-xs btn-primary ${
|
||||
className={`btn btn-sm btn-primary ${
|
||||
!HasManageProject && "d-none"
|
||||
}`}
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#create-project-model"
|
||||
onClick={handleShow}
|
||||
>
|
||||
<i className="bx bx-plus-circle me-2"></i>
|
||||
@ -183,82 +195,58 @@ const ProjectList = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{((error && !loading) || !projects) && (
|
||||
<p className="text-center text-body-secondary">
|
||||
There was an error loading the projects. Please try again.
|
||||
</p>
|
||||
{loading && <p className="text-center">Loading...</p>}
|
||||
{!loading && filteredProjects.length === 0 && !listView && (
|
||||
<p className="text-center text-muted">No projects found.</p>
|
||||
)}
|
||||
|
||||
{(!projects || projects.length === 0 || projectList.length == 0) &&
|
||||
!loading &&
|
||||
error && (
|
||||
<div className="text-center">
|
||||
<button
|
||||
className="btn btn-xs btn-label-secondary"
|
||||
onClick={handleReFresh}
|
||||
>
|
||||
Retry Fetching Projects
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="row">
|
||||
{loading && <p className="text-center">Loading...</p>}
|
||||
|
||||
{listView ? <ProjectListView/> :
|
||||
currentItems &&
|
||||
currentItems.map((item) => (
|
||||
<ProjectCard projectData={item} key={item.id}></ProjectCard>
|
||||
))}
|
||||
=======
|
||||
|
||||
|
||||
{Array.isArray(currentItems) && loginUser?.projects && (
|
||||
currentItems
|
||||
.filter((item) => loginUser.projects.includes(String(item.id)))
|
||||
.map((item) => (
|
||||
<ProjectCard projectData={item} key={item.id} />
|
||||
))
|
||||
)}
|
||||
>>>>>>> 148058d1d22430d0c2a314cdade3509b38c5d090
|
||||
{listView ? (
|
||||
<ProjectListView
|
||||
projectsData={currentItems}
|
||||
onStatusFilterChange={handleStatusFilterFromChild}
|
||||
/>
|
||||
) : (
|
||||
currentItems.map((project) => (
|
||||
<ProjectCard key={project.id} projectData={project} />
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
{/* Pagination */}
|
||||
{!loading && (
|
||||
<nav aria-label="Page ">
|
||||
<ul className="pagination pagination-sm justify-content-end py-1">
|
||||
<li
|
||||
className={`page-item ${currentPage === 1 ? "disabled" : ""}`}
|
||||
>
|
||||
|
||||
{!loading && totalPages > 1 && (
|
||||
<nav>
|
||||
<ul className="pagination pagination-sm justify-content-end py-2">
|
||||
<li className={`page-item ${currentPage === 1 && "disabled"}`}>
|
||||
<button
|
||||
className="page-link btn-xs"
|
||||
onClick={() => paginate(currentPage - 1)}
|
||||
className="page-link"
|
||||
onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}
|
||||
>
|
||||
«
|
||||
</button>
|
||||
</li>
|
||||
{[...Array(totalPages)]?.map((_, index) => (
|
||||
{[...Array(totalPages)].map((_, i) => (
|
||||
<li
|
||||
key={index}
|
||||
className={`page-item ${
|
||||
currentPage === index + 1 ? "active" : ""
|
||||
}`}
|
||||
key={i}
|
||||
className={`page-item ${currentPage === i + 1 && "active"}`}
|
||||
>
|
||||
<button
|
||||
className="page-link "
|
||||
onClick={() => paginate(index + 1)}
|
||||
className="page-link"
|
||||
onClick={() => setCurrentPage(i + 1)}
|
||||
>
|
||||
{index + 1}
|
||||
{i + 1}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
<li
|
||||
className={`page-item ${
|
||||
currentPage === totalPages ? "disabled" : ""
|
||||
currentPage === totalPages && "disabled"
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className="page-link "
|
||||
onClick={() => paginate(currentPage + 1)}
|
||||
className="page-link"
|
||||
onClick={() =>
|
||||
setCurrentPage((p) => Math.min(totalPages, p + 1))
|
||||
}
|
||||
>
|
||||
»
|
||||
</button>
|
||||
|
Loading…
x
Reference in New Issue
Block a user