From 1cdfb47c39dac482f34a668635299e897341c619 Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Tue, 22 Apr 2025 10:44:41 +0530 Subject: [PATCH 01/10] created new projectListView component --- src/pages/project/ProjectListView.jsx | 196 ++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 src/pages/project/ProjectListView.jsx diff --git a/src/pages/project/ProjectListView.jsx b/src/pages/project/ProjectListView.jsx new file mode 100644 index 00000000..69b7d0f8 --- /dev/null +++ b/src/pages/project/ProjectListView.jsx @@ -0,0 +1,196 @@ +import React from "react"; +import moment from "moment"; +import { useProjects } from "../../hooks/useProjects"; + +const ProjectListView = () => { + const { projects } = useProjects(); + + const getProgress = (planned, completed) => { + return (completed * 100) / planned + "%"; + }; + const getProgressInNumber = (planned, completed) => { + return (completed * 100) / planned; + }; + + const getProjectStatusName = (statusId) => { + switch (statusId) { + case 1: + return "Active"; + case 2: + return "On Hold"; + // case 3: + // return "Suspended"; + case 3: + return "Inactive"; + case 4: + return "Completed"; + } + }; + + const getProjectStatusColor = (statusId) => { + switch (statusId) { + case 1: + return "bg-label-success"; + case 2: + return "bg-label-warning"; + case 3: + return "bg-label-info"; + case 4: + return "bg-label-secondary"; + case 5: + return "bg-label-dark"; + } + }; + + return ( +
+ + + + + + + + + + + + + + + {projects.map((project) => ( + + + + + + + + + + + + + ))} + +
+ Project Name + Project MangerSTART DATEDEADLINETaskProgress + + Action
+ {project.name} + {project.contactPerson} + + {" "} + {project.startDate + ? moment(project.startDate).format("DD-MMM-YYYY") + : "NA"} + + + {project.endDate + ? moment(project.endDate).format("DD-MMM-YYYY") + : "NA"} + {project.plannedWork} +
+
+
+
+

+ + {getProjectStatusName(project.projectStatusId)} + +

{" "} +
+ {" "} + +
+
+ ); +}; + +export default ProjectListView; From b4d2fd86f7d893e191c3468b8858079b249af254 Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Tue, 22 Apr 2025 10:45:03 +0530 Subject: [PATCH 02/10] imported projectLisComponent --- src/pages/project/ProjectList.jsx | 232 +++++++++++++++++------------- 1 file changed, 130 insertions(+), 102 deletions(-) diff --git a/src/pages/project/ProjectList.jsx b/src/pages/project/ProjectList.jsx index a0e9ea3e..aa4f5e3a 100644 --- a/src/pages/project/ProjectList.jsx +++ b/src/pages/project/ProjectList.jsx @@ -6,37 +6,35 @@ import ProjectRepository from "../../repositories/ProjectRepository"; import { useProjects } from "../../hooks/useProjects"; import { useDispatch } from "react-redux"; import showToast from "../../services/toastService"; -import { getCachedData, cacheData} from "../../slices/apiDataManager"; -import {useHasUserPermission} from "../../hooks/useHasUserPermission" +import { getCachedData, cacheData } from "../../slices/apiDataManager"; +import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import { useProfile } from "../../hooks/useProfile"; -import {MANAGE_PROJECT} from "../../utils/constants"; +import { MANAGE_PROJECT } from "../../utils/constants"; +import ProjectListView from "./ProjectListView"; -const ProjectList = () => -{ - - - const {profile: loginUser} = useProfile(); +const ProjectList = () => { + const { profile: loginUser } = useProfile(); + const [listView, setListView] = useState(true); const [showModal, setShowModal] = useState(false); - const {projects, loading, error, refetch} = useProjects(); + 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 [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 handleShow = () => setShowModal(true); - const handleClose = () => setShowModal( false ); - - + 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]) { @@ -44,7 +42,7 @@ const ProjectList = () => } grouped[statusId].push(project); }); - + // Step 2: Sort each group by name const sortedGrouped = Object.keys(grouped) .sort() // sort group keys (status IDs) @@ -53,35 +51,34 @@ const ProjectList = () => a.name.toLowerCase().localeCompare(b.name.toLowerCase()) ) ); - + setProjectList(sortedGrouped); // final sorted flat list } - - }, [ projects, loginUser?.projects, loading ] ); + }, [projects, loginUser?.projects, loading]); useEffect(() => { if (loginUser) { - setHasManageProject(HasManageProjectPermission); + setHasManageProject(HasManageProjectPermission); } else { - setHasManageProject(false); } + setHasManageProject(false); + } }, [loginUser, HasManageProjectPermission]); - - const handleSubmitForm = (newProject) => { ProjectRepository.manageProject(newProject) - .then( ( response ) => - { - - const cachedProjects_list = getCachedData( "projectslist" ) || []; - - const updated_Projects_list = [ ...cachedProjects_list, response.data ]; - + .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]); + setProjectList((prevProjectList) => [ + ...prevProjectList, + response.data, + ]); showToast("Project Created successfully.", "success"); - setShowModal(false) + setShowModal(false); }) .catch((error) => { closeModal(); @@ -98,33 +95,31 @@ const ProjectList = () => const indexOfLastItem = currentPage * itemsPerPage; const indexOfFirstItem = indexOfLastItem - itemsPerPage; - const currentItems = Array.isArray(projectList) - ? projectList.slice(indexOfFirstItem, indexOfLastItem) + const currentItems = Array.isArray(projectList) + ? projectList.slice(indexOfFirstItem, indexOfLastItem) : []; - + const paginate = (pageNumber) => setCurrentPage(pageNumber); const totalPages = Array.isArray(projectList) ? Math.ceil(projectList.length / itemsPerPage) : 0; - - return ( <>
- -
- + + +
]} > -
-
+ {/*
- {" "} + + +
*/} + +
+
+ + + +
+
+
- - {[...Array(totalPages)]?.map((_, index) => ( -
  • - -
  • - ))} -
  • - -
  • - - - )} + {/* Pagination */} + {!loading && ( + + )}
    ); From 3c9e68f91b342e363c9c1f5e6470877c08c468ef Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Wed, 23 Apr 2025 10:48:47 +0530 Subject: [PATCH 03/10] created new progressBar component --- src/components/common/ProgressBar.jsx | 43 ++++++++++++++++----------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/components/common/ProgressBar.jsx b/src/components/common/ProgressBar.jsx index 1a29a343..947c6a00 100644 --- a/src/components/common/ProgressBar.jsx +++ b/src/components/common/ProgressBar.jsx @@ -1,30 +1,37 @@ import React from "react"; -const ProgressBar = ( {completeValue, totalValue} ) => -{ - - - const getProgress = (complete, total) => { - return (total * 100) / complete + "%"; +const ProgressBar = ({ + plannedWork = 100, + completedWork = 0, + height = "8px", + className = "mb-4", + rounded = true, +}) => { + const getProgress = (planned, completed) => { + if (!planned || planned === 0) return "0%"; + return `${Math.min((completed / planned) * 100, 100).toFixed(2)}%`; }; - return ( -
    -
    + + const progressStyle = { + width: getProgress(plannedWork, completedWork), + }; + + return ( +
    -
    - ); }; export default ProgressBar; + From c76045d39e543c3ba0e6641e778d0661937684be Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Wed, 23 Apr 2025 10:49:31 +0530 Subject: [PATCH 04/10] chanaged getProjectStatusName --- src/components/Project/AboutProject.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Project/AboutProject.jsx b/src/components/Project/AboutProject.jsx index afd54971..438de6be 100644 --- a/src/components/Project/AboutProject.jsx +++ b/src/components/Project/AboutProject.jsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; import moment from "moment"; -import { ProjectStatus } from "../../utils/projectStatus"; +import { getProjectStatusName } from "../../utils/projectStatus"; const AboutProject = ({ data }) => { const [CurrentProject, setCurrentProject] = useState(data); @@ -34,7 +34,7 @@ const AboutProject = ({ data }) => {
  • Status:{" "} - {ProjectStatus(data.projectStatusId)} + {getProjectStatusName(data.projectStatusId)}
  • From 099098d39a96dd1a3653d65bed44f12245ee4339 Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Wed, 23 Apr 2025 10:52:55 +0530 Subject: [PATCH 05/10] changed getProjectStatusName getProjectStatusColor location. added these fun in Utils folder --- src/components/Project/ProjectCard.jsx | 506 ++++++++++++------------- 1 file changed, 249 insertions(+), 257 deletions(-) diff --git a/src/components/Project/ProjectCard.jsx b/src/components/Project/ProjectCard.jsx index bd0a0fca..a6a44d32 100644 --- a/src/components/Project/ProjectCard.jsx +++ b/src/components/Project/ProjectCard.jsx @@ -8,278 +8,270 @@ import ProjectRepository from "../../repositories/ProjectRepository"; import { cacheData, getCachedData } from "../../slices/apiDataManager"; import showToast from "../../services/toastService"; import { useHasUserPermission } from "../../hooks/useHasUserPermission"; -import { MANAGE_PROJECT } from "../../utils/constants"; - - +import {MANAGE_PROJECT} from "../../utils/constants"; +import { getProjectStatusColor,getProjectStatusName } from "../../utils/projectStatus"; const ProjectCard = ({ projectData }) => { - const [projectInfo, setProjectInfo] = useState(projectData); - const [projectDetails, setProjectDetails] = useState(null); - const [showModal, setShowModal] = useState(false); - const navigate = useNavigate(); - const ManageProject = useHasUserPermission(MANAGE_PROJECT); + const [projectInfo, setProjectInfo] = useState(projectData); + const [projectDetails, setProjectDetails] = useState(null); + const [showModal, setShowModal] = useState(false); + const navigate = useNavigate(); + const ManageProject = useHasUserPermission(MANAGE_PROJECT); - const handleShow = async () => { - try { - const response = await ProjectRepository.getProjectByprojectId(projectInfo.id); - setProjectDetails(response.data); - setShowModal(true); - } catch (error) { - showToast("Failed to load project details", "error"); - } - }; + const handleShow = async () => { + try { + const response = await ProjectRepository.getProjectByprojectId( + projectInfo.id + ); + setProjectDetails(response.data); + setShowModal(true); + } catch (error) { + showToast("Failed to load project details", "error"); + } + }; - const getProgress = (planned, completed) => { - return (completed * 100) / planned + "%"; - }; - const getProgressInNumber = (planned, completed) => { - return (completed * 100) / planned; - }; + const getProgress = (planned, completed) => { + return (completed * 100) / planned + "%"; + }; + const getProgressInNumber = (planned, completed) => { + return (completed * 100) / planned; + }; - const handleClose = () => setShowModal(false); - - const getProjectStatusName = (statusId) => { - switch (statusId) { - case 1: - return "Active"; - case 2: - return "On Hold"; - // case 3: - // return "Suspended"; - case 3: - return "Inactive"; - case 4: - return "Completed"; - } - }; - - const getProjectStatusColor = (statusId) => { - switch (statusId) { - case 1: - return "bg-label-success"; - case 2: - return "bg-label-warning"; - case 3: - return "bg-label-info"; - case 4: - return "bg-label-secondary"; - case 5: - return "bg-label-dark"; - } - }; - - const handleViewProject = () => { - navigate(`/projects/${projectData.id}`); - }; + const handleClose = () => setShowModal(false); - const handleFormSubmit = (updatedProject) => { - if (projectInfo?.id) { - ProjectRepository.updateProject(projectInfo.id, updatedProject) - .then((response) => { - const updatedProjectData = { - ...projectInfo, - ...response.data, - building: projectDetails?.building, - }; + const handleViewProject = () => { + navigate(`/projects/${projectData.id}`); + }; - setProjectInfo(updatedProject); + const handleFormSubmit = (updatedProject) => { + if (projectInfo?.id) { + ProjectRepository.updateProject(projectInfo.id, updatedProject) + .then((response) => { + const updatedProjectData = { + ...projectInfo, + ...response.data, + building: projectDetails?.building, + }; - if (getCachedData(`projectinfo-${projectInfo.id}`)) { - cacheData(`projectinfo-${projectInfo.id}`, updatedProjectData); - } + setProjectInfo(updatedProject); - const projects_list = getCachedData("projectslist"); - if (projects_list) { - const updatedProjectsList = projects_list.map((project) => - project.id === projectInfo.id - ? { ...project, ...response.data, tenant: project.tenant } - : project - ); - cacheData("projectslist", updatedProjectsList); - } + if (getCachedData(`projectinfo-${projectInfo.id}`)) { + cacheData(`projectinfo-${projectInfo.id}`, updatedProjectData); + } - showToast("Project updated successfully.", "success"); - setShowModal(false); - }) - .catch((error) => { - showToast(error.message, "error"); - }); - } - }; + const projects_list = getCachedData("projectslist"); + if (projects_list) { + const updatedProjectsList = projects_list.map((project) => + project.id === projectInfo.id + ? { ...project, ...response.data, tenant: project.tenant } + : project + ); + cacheData("projectslist", updatedProjectsList); + } - return ( - <> - {showModal && projectDetails && ( -
    - + showToast("Project updated successfully.", "success"); + setShowModal(false); + }) + .catch((error) => { + showToast(error.message, "error"); + }); + } + }; + + return ( + <> + {showModal && projectDetails && ( +
    + +
    + )} + +
    +
    +
    +
    +
    +
    +
    - )} - -
    -
    -
    -
    -
    -
    - -
    -
    -
    - - {projectInfo.name} - -
    -
    - Client: - {projectInfo.contactPerson} -
    -
    -
    -
    -
    - - -
    -
    -
    -
    -
    -
    -
    -

    - Start Date: - {projectInfo.startDate - ? moment(projectInfo.startDate).format("DD-MMM-YYYY") - : "NA"} -

    -

    - Deadline: - - {projectInfo.endDate - ? moment(projectInfo.endDate).format("DD-MMM-YYYY") - : "NA"} -

    -

    {projectInfo.projectAddress}

    - -
    - -
    -
    -
    -
    -

    - - {getProjectStatusName(projectInfo.projectStatusId)} - -

    {" "} - {getDateDifferenceInDays(projectInfo.endDate, Date()) >= 0 && - ( - {projectInfo.endDate && - getDateDifferenceInDays(projectInfo.endDate, Date())}{" "} - Days left - ) } - {getDateDifferenceInDays(projectInfo.endDate, Date()) < 0 && - ( - {projectInfo.endDate && - getDateDifferenceInDays(projectInfo.endDate, Date())}{" "} - Days overdue - )} - -
    -
    - Task: {projectInfo.completedWork} / {projectInfo.plannedWork} - {Math.floor(getProgressInNumber(projectInfo.plannedWork, projectInfo.completedWork)) || 0} % Completed -
    -
    -
    -
    - -
    +
    +
    + + {projectInfo.name} + +
    +
    + Client: + {projectInfo.contactPerson} +
    +
    +
    +
    + + +
    +
    - - ); +
    +
    +
    +
    +

    + Start Date: + {projectInfo.startDate + ? moment(projectInfo.startDate).format("DD-MMM-YYYY") + : "NA"} +

    +

    + Deadline: + + {projectInfo.endDate + ? moment(projectInfo.endDate).format("DD-MMM-YYYY") + : "NA"} +

    +

    {projectInfo.projectAddress}

    +
    +
    +
    +
    +
    +

    + + {getProjectStatusName(projectInfo.projectStatusId)} + +

    {" "} + {getDateDifferenceInDays(projectInfo.endDate, Date()) >= 0 && ( + + {projectInfo.endDate && + getDateDifferenceInDays(projectInfo.endDate, Date())}{" "} + Days left + + )} + {getDateDifferenceInDays(projectInfo.endDate, Date()) < 0 && ( + + {projectInfo.endDate && + getDateDifferenceInDays(projectInfo.endDate, Date())}{" "} + Days overdue + + )} +
    +
    + + Task: {projectInfo.completedWork} / {projectInfo.plannedWork} + + + {Math.floor( + getProgressInNumber( + projectInfo.plannedWork, + projectInfo.completedWork + ) + ) || 0}{" "} + % Completed + +
    +
    +
    +
    + +
    +
    +
    + + ); }; export default ProjectCard; From d9f4bc47f66b07099ac47960cea2a5fd440f6152 Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Wed, 23 Apr 2025 11:00:10 +0530 Subject: [PATCH 06/10] added new functions ,getProjectStatusName and getProjectStatusColor --- src/utils/projectStatus.js | 49 ++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/utils/projectStatus.js b/src/utils/projectStatus.js index 771c6294..81ab08af 100644 --- a/src/utils/projectStatus.js +++ b/src/utils/projectStatus.js @@ -1,25 +1,32 @@ -export const ProjectStatus =(statusId)=>{ - switch (statusId) { - case 1: - return "Active" - break; - case 2: - return "On Hold" - break; - // case 3: - // return "Suspended" - // break; - case 3: - return "Inactive" - break; - case 4: - return "Completed" - break; - default: - break; - } -} +export const getProjectStatusName = (statusId) => { + switch (statusId) { + case 1: + return "Active"; + case 2: + return "On Hold"; + // case 3: + // return "Suspended"; + case 3: + return "Inactive"; + case 4: + return "Completed"; + } +}; +export const getProjectStatusColor = (statusId) => { + switch (statusId) { + case 1: + return "bg-label-success"; + case 2: + return "bg-label-warning"; + case 3: + return "bg-label-info"; + case 4: + return "bg-label-secondary"; + case 5: + return "bg-label-dark"; + } +}; // for different color for each user export function hashString(str) { From c38a92b8b71ef8ab0c7b7e68a786f2b9d9277649 Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Wed, 23 Apr 2025 11:01:14 +0530 Subject: [PATCH 07/10] added list view component --- src/pages/project/ProjectList.jsx | 222 ++++++++++++++---------------- 1 file changed, 105 insertions(+), 117 deletions(-) diff --git a/src/pages/project/ProjectList.jsx b/src/pages/project/ProjectList.jsx index 3323652a..a21a09a0 100644 --- a/src/pages/project/ProjectList.jsx +++ b/src/pages/project/ProjectList.jsx @@ -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 paginate = (pageNumber) => setCurrentPage(pageNumber); - const totalPages = Array.isArray(projectList) - ? Math.ceil(projectList.length / itemsPerPage) - : 0; + const currentItems = filteredProjects.slice( + indexOfFirstItem, + indexOfLastItem + ); + const totalPages = Math.ceil( filteredProjects.length / itemsPerPage ); + + 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} - > + />
    @@ -126,55 +139,54 @@ const ProjectList = () => { { label: "Home", link: "/dashboard" }, { label: "Projects", link: null }, ]} - > + /> -
    - {/*
    - - -
    */} +
    +
    +
    + { + setSearchTerm(e.target.value); + setCurrentPage(1); + }} + /> +
    -
    -
    - +
    +
    +
    - {((error && !loading) || !projects) && ( -

    - There was an error loading the projects. Please try again. -

    + {loading &&

    Loading...

    } + {!loading && filteredProjects.length === 0 && !listView && ( +

    No projects found.

    )} - {(!projects || projects.length === 0 || projectList.length == 0) && - !loading && - error && ( -
    - -
    - )} -
    - {loading &&

    Loading...

    } - - {listView ? : - currentItems && - currentItems.map((item) => ( - - ))} -======= - - - {Array.isArray(currentItems) && loginUser?.projects && ( - currentItems - .filter((item) => loginUser.projects.includes(String(item.id))) - .map((item) => ( - - )) -)} ->>>>>>> 148058d1d22430d0c2a314cdade3509b38c5d090 + {listView ? ( + + ) : ( + currentItems.map((project) => ( + + )) + )}
    - {/* Pagination */} - {!loading && ( -
    @@ -223,22 +231,39 @@ const EmployeeList = () => {
    From 3ee5a71cc91e8689875036c8f0b516f967c641b5 Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Wed, 23 Apr 2025 12:16:40 +0530 Subject: [PATCH 10/10] added status and search filter filter --- src/pages/project/ProjectList.jsx | 103 +++++++-- src/pages/project/ProjectListView.jsx | 318 ++++++++++---------------- 2 files changed, 214 insertions(+), 207 deletions(-) diff --git a/src/pages/project/ProjectList.jsx b/src/pages/project/ProjectList.jsx index a21a09a0..def125ce 100644 --- a/src/pages/project/ProjectList.jsx +++ b/src/pages/project/ProjectList.jsx @@ -110,12 +110,14 @@ const ProjectList = () => { indexOfFirstItem, indexOfLastItem ); - const totalPages = Math.ceil( filteredProjects.length / itemsPerPage ); - - useEffect(() => { - const tooltipTriggerList = Array.from(document.querySelectorAll('[data-bs-toggle="tooltip"]')); - tooltipTriggerList.forEach((el) => new bootstrap.Tooltip(el)); - }, []); + const totalPages = Math.ceil(filteredProjects.length / itemsPerPage); + + useEffect(() => { + const tooltipTriggerList = Array.from( + document.querySelectorAll('[data-bs-toggle="tooltip"]') + ); + tooltipTriggerList.forEach((el) => new bootstrap.Tooltip(el)); + }, []); return ( <> @@ -162,8 +164,12 @@ const ProjectList = () => { 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" + onClick={() => setListView(true)} + data-bs-toggle="tooltip" + data-bs-offset="0,8" + data-bs-placement="top" + data-bs-custom-class="tooltip" + title="List View" > @@ -173,8 +179,12 @@ const ProjectList = () => { 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" + onClick={() => setListView(false)} + data-bs-toggle="tooltip" + data-bs-offset="0,8" + data-bs-placement="top" + data-bs-custom-class="tooltip" + title="Card View" > @@ -202,10 +212,75 @@ const ProjectList = () => {
    {listView ? ( - +
    + + + + + + + + + + + + + + + {currentItems.length === 0 ? ( + + + + ) : ( + currentItems.map((project) => ( + + )) + )} + +
    + Project Name + Project MangerSTART DATEDEADLINETaskProgress +
    + +
      + {[ + { id: 1, label: "Active" }, + { id: 2, label: "On Hold" }, + { id: 3, label: "Inactive" }, + { id: 4, label: "Completed" }, + ].map(({ id, label }) => ( +
    • +
      + handleStatusChange(id)} + /> + +
      +
    • + ))} +
    +
    +
    + Action +
    + No projects found +
    +
    ) : ( currentItems.map((project) => ( diff --git a/src/pages/project/ProjectListView.jsx b/src/pages/project/ProjectListView.jsx index 6de16f01..428291f6 100644 --- a/src/pages/project/ProjectListView.jsx +++ b/src/pages/project/ProjectListView.jsx @@ -1,55 +1,31 @@ import React, { useState, useEffect } from "react"; import moment from "moment"; -import {useProjects} from "../../hooks/useProjects"; -import { getProjectStatusName,getProjectStatusColor } from "../../utils/projectStatus"; +import { useProjects } from "../../hooks/useProjects"; +import { + getProjectStatusName, + getProjectStatusColor, +} from "../../utils/projectStatus"; import ProgressBar from "../../components/common/ProgressBar"; -import {useNavigate} from "react-router-dom"; +import { useNavigate } from "react-router-dom"; import ManageProject from "../../components/Project/ManageProject"; import ProjectRepository from "../../repositories/ProjectRepository"; -import {MANAGE_PROJECT} from "../../utils/constants"; +import { MANAGE_PROJECT } from "../../utils/constants"; import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import ManageProjectInfo from "../../components/Project/ManageProjectInfo"; import showToast from "../../services/toastService"; -import { getCachedData,cacheData } from "../../slices/apiDataManager"; +import { getCachedData, cacheData } from "../../slices/apiDataManager"; -const ProjectListView = ( {projectsData, onStatusFilterChange} ) =>{ - const [ projectDetails, setProjectDetails ] = useState( null ); - const[projectInfo,setProjectInfo] = useState(null) +const ProjectListView = ({ projectData }) => { + const [projectInfo, setProjectInfo] = useState(projectData); + const [projectDetails, setProjectDetails] = useState(null); const [showModal, setShowModal] = useState(false); - const projects = Array.isArray(projectsData) ? projectsData : []; + const navigate = useNavigate(); + const ManageProject = useHasUserPermission(MANAGE_PROJECT); - const [ selectedStatuses, setSelectedStatuses ] = useState( [ 1, 2, 3, 4 ] ); - const navigate = useNavigate() - - const handleStatusChange = (statusId) => { - const updated = selectedStatuses.includes(statusId) - ? selectedStatuses.filter((id) => id !== statusId) - : [...selectedStatuses, statusId]; - - setSelectedStatuses(updated); - onStatusFilterChange(updated); - }; - - useEffect(() => { - onStatusFilterChange(selectedStatuses); - }, []); - - const getProgress = (planned, completed) => { - return (completed * 100) / planned + "%"; - }; - const getProgressInNumber = (planned, completed) => { - return (completed * 100) / planned; - }; - const filteredProjects = projects.filter((project) => - selectedStatuses.includes(project.projectStatusId) - ); - - const handleShow = async ( project) => - { - setProjectInfo(project) + const handleShow = async () => { try { const response = await ProjectRepository.getProjectByprojectId( - project.id + projectInfo.id ); setProjectDetails(response.data); setShowModal(true); @@ -57,8 +33,22 @@ const ProjectListView = ( {projectsData, onStatusFilterChange} ) =>{ showToast("Failed to load project details", "error"); } }; + + const getProgress = (planned, completed) => { + return (completed * 100) / planned + "%"; + }; + const getProgressInNumber = (planned, completed) => { + return (completed * 100) / planned; + }; + const handleClose = () => setShowModal(false); - const handleFormSubmit = (updatedProject,projectInfo) => { + + + const handleViewProject = () => { + navigate(`/projects/${projectData.id}`); + }; + + const handleFormSubmit = (updatedProject) => { if (projectInfo?.id) { ProjectRepository.updateProject(projectInfo.id, updatedProject) .then((response) => { @@ -68,7 +58,7 @@ const ProjectListView = ( {projectsData, onStatusFilterChange} ) =>{ building: projectDetails?.building, }; - setProjectInfo(updatedProject); + setProjectInfo( updatedProjectData ); if (getCachedData(`projectinfo-${projectInfo.id}`)) { cacheData(`projectinfo-${projectInfo.id}`, updatedProjectData); @@ -84,7 +74,6 @@ const ProjectListView = ( {projectsData, onStatusFilterChange} ) =>{ cacheData("projectslist", updatedProjectsList); } showToast("Project updated successfully.", "success"); - setShowModal(false); }) .catch((error) => { @@ -92,10 +81,9 @@ const ProjectListView = ( {projectsData, onStatusFilterChange} ) =>{ }); } }; - - return (<> - - {showModal && projectDetails && ( + return ( + <> + {showModal && projectDetails && (
    { />
    )} -
    - - - - - - - - - - + + + + + + + + + + - - - - {filteredProjects.length === 0 ? ( - - - - ) : ( - filteredProjects.map((project) => ( - - - - - - - - - - - - - )) - )} - -
    - Project Name - Project MangerSTART DATEDEADLINETaskProgress -
    + +
    + navigate(`/projects/${projectInfo.id}`)} + > + {projectInfo.name} + + {projectInfo.contactPerson} + + {projectInfo.startDate + ? moment(projectInfo.startDate).format("DD-MMM-YYYY") + : "NA"} + + + {projectInfo.endDate + ? moment(projectInfo.endDate).format("DD-MMM-YYYY") + : "NA"} + {projectInfo.plannedWork} + + +

    + + {getProjectStatusName(projectInfo.projectStatusId)} + +

    +
    +
    + +
    - -
    Action
    - No projects found -
    - navigate(`/projects/${project.id}`)}>{project.name} - {project.contactPerson} - - {project.startDate - ? moment(project.startDate).format("DD-MMM-YYYY") - : "NA"} - - - {project.endDate - ? moment(project.endDate).format("DD-MMM-YYYY") - : "NA"} - {project.plannedWork} - - -

    - - {getProjectStatusName(project.projectStatusId)} - -

    -
    -
    - - -
    -
    -
    - +
  • +
  • + + + Modify + +
  • +
  • + navigate(`/activities/records?project=${projectInfo.id}`) + } + > + + + Activities + +
  • + +
    + + + ); };