From 29caa20250bce1dfa78177b8b7e84f72b7c2db45 Mon Sep 17 00:00:00 2001 From: Vikas Nale Date: Wed, 9 Apr 2025 14:44:57 +0530 Subject: [PATCH] Card changes to show days left for project --- package-lock.json | 6 + package.json | 2 +- src/components/Project/ProjectCard.jsx | 502 +++++++++++++------------ src/utils/dateUtils.jsx | 58 ++- vite.config.ts | 2 +- 5 files changed, 287 insertions(+), 283 deletions(-) diff --git a/package-lock.json b/package-lock.json index 77ec7fcf..adfa6823 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@hookform/resolvers": "^3.10.0", "@reduxjs/toolkit": "^2.5.0", + "@types/web": "^0.0.216", "@vitejs/plugin-react": "^4.3.4", "axios": "^1.7.9", "axios-retry": "^4.5.0", @@ -1439,6 +1440,11 @@ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==" }, + "node_modules/@types/web": { + "version": "0.0.216", + "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.216.tgz", + "integrity": "sha512-HLaPWQKq1oh6aQv1JLRsiH0vW4VsO+L/zTOeOUmoGBnLVR2wCj4w4oWfa/0O5JFMqZXWC6VpipqQU6B1v2M/qg==" + }, "node_modules/@ungap/structured-clone": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.1.tgz", diff --git a/package.json b/package.json index 9bec5700..ee6a4a1b 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,6 @@ "private": true, "version": "0.0.0", "type": "module", - "scripts": { "dev": "vite", "json-server": "json-server --watch ./src/data/demo.json --port 5000", @@ -14,6 +13,7 @@ "dependencies": { "@hookform/resolvers": "^3.10.0", "@reduxjs/toolkit": "^2.5.0", + "@types/web": "^0.0.216", "@vitejs/plugin-react": "^4.3.4", "axios": "^1.7.9", "axios-retry": "^4.5.0", diff --git a/src/components/Project/ProjectCard.jsx b/src/components/Project/ProjectCard.jsx index 296c1605..67250441 100644 --- a/src/components/Project/ProjectCard.jsx +++ b/src/components/Project/ProjectCard.jsx @@ -2,279 +2,283 @@ import React, { useState } from "react"; import moment from "moment"; import { getDateDifferenceInDays } from "../../utils/dateUtils"; import { useNavigate } from "react-router-dom"; -import {useProjectDetails} from "../../hooks/useProjects"; +import { useProjectDetails } from "../../hooks/useProjects"; import ManageProjectInfo from "./ManageProjectInfo"; import ProjectRepository from "../../repositories/ProjectRepository"; -import {cacheData, getCachedData} from "../../slices/apiDataManager"; +import { cacheData, getCachedData } from "../../slices/apiDataManager"; import showToast from "../../services/toastService"; -import {useHasUserPermission} from "../../hooks/useHasUserPermission"; -import {MANAGE_PROJECT} from "../../utils/constants"; +import { useHasUserPermission } from "../../hooks/useHasUserPermission"; +import { MANAGE_PROJECT } from "../../utils/constants"; 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 handleClose = () => setShowModal(false); - 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 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 handleViewProject = () => { - navigate(`/projects/${projectData.id}`); - }; + 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 handleFormSubmit = (updatedProject) => { - if (projectInfo?.id) { - ProjectRepository.updateProject(projectInfo.id, updatedProject) - .then((response) => { - const updatedProjectData = { - ...projectInfo, - ...response.data, - building: projectDetails?.building, - }; + const handleFormSubmit = (updatedProject) => { + if (projectInfo?.id) { + ProjectRepository.updateProject(projectInfo.id, updatedProject) + .then((response) => { + const updatedProjectData = { + ...projectInfo, + ...response.data, + building: projectDetails?.building, + }; - setProjectInfo(updatedProject); + setProjectInfo(updatedProject); - if (getCachedData(`projectinfo-${projectInfo.id}`)) { - cacheData(`projectinfo-${projectInfo.id}`, updatedProjectData); - } + if (getCachedData(`projectinfo-${projectInfo.id}`)) { + cacheData(`projectinfo-${projectInfo.id}`, updatedProjectData); + } - 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); - } + 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); + } - showToast("Project updated successfully.", "success"); - setShowModal(false); - }) - .catch((error) => { - showToast(error.message, "error"); - }); - } - }; + showToast("Project updated successfully.", "success"); + setShowModal(false); + }) + .catch((error) => { + showToast(error.message, "error"); + }); + } + }; - return ( - <> - {showModal && projectDetails && ( -
- -
- )} - -
-
-
-
-
-
- + 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}

+
+
+
+
+
+
+ +
+
+
+ + {projectInfo.name} + +
+
+ Client: + {projectInfo.contactPerson} +
+
+
+
+
+ +
- -
-
-
-
-

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

{" "} - - {projectInfo.startDate && - projectInfo.endDate && - getDateDifferenceInDays( - projectInfo.startDate, - projectInfo.endDate - )}{" "} - Days left - -
-
- Task: {projectInfo.completedWork} / { projectInfo.plannedWork} - {Math.floor(getProgressInNumber(projectInfo.plannedWork,projectInfo.completedWork)) || 0} % Completed -
-
-
-
-
- {/* +
+
+
+
+
+
+

+ 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; diff --git a/src/utils/dateUtils.jsx b/src/utils/dateUtils.jsx index 73557700..7f4a222a 100644 --- a/src/utils/dateUtils.jsx +++ b/src/utils/dateUtils.jsx @@ -13,56 +13,50 @@ export const getDateDifferenceInDays = (startDate, endDate) => { } // Calculate the difference in milliseconds - const differenceInMs = end - start; + const differenceInMs = start - end; // Convert milliseconds to days const differenceInDays = Math.floor(differenceInMs / (1000 * 60 * 60 * 24)); - return differenceInDays; }; export const formatDate = (date) => { - if (!date) return ''; // Return an empty string if no date + if (!date) return ""; // Return an empty string if no date const dateObj = new Date(date); - return dateObj.toISOString().split('T')[0]; // Get the date in YYYY-MM-DD format + return dateObj.toISOString().split("T")[0]; // Get the date in YYYY-MM-DD format }; - -export const convertShortTime=(dateString)=> { +export const convertShortTime = (dateString) => { const date = new Date(dateString); let hours = date.getHours(); - const minutes = String(date.getMinutes()).padStart(2, '0'); - - const ampm = hours >= 12 ? 'PM' : 'AM'; + const minutes = String(date.getMinutes()).padStart(2, "0"); + + const ampm = hours >= 12 ? "PM" : "AM"; hours = hours % 12; // Convert to 12-hour format hours = hours ? hours : 12; // If hours is 0, set it to 12 - return `${String(hours).padStart(2, '0')}:${minutes} ${ampm}`; -} + return `${String(hours).padStart(2, "0")}:${minutes} ${ampm}`; +}; - export const timeElapsed = (checkInTime, timeElapsedInHours) =>{ - const checkInDate = new Date(checkInTime); +export const timeElapsed = (checkInTime, timeElapsedInHours) => { + const checkInDate = new Date(checkInTime); - const currentTime = new Date(); - - const timeDifference = currentTime - checkInDate; - - - const timeDifferenceInHours = timeDifference / (1000 * 60 * 60); - - return timeDifferenceInHours >= timeElapsedInHours; - } + const currentTime = new Date(); + const timeDifference = currentTime - checkInDate; + const timeDifferenceInHours = timeDifference / (1000 * 60 * 60); - export const checkIfCurrentDate = (dateString) => { - const currentDate = new Date(); - const inputDate = new Date(dateString); - - - currentDate.setHours(0, 0, 0, 0); - inputDate.setHours(0, 0, 0, 0); - - return currentDate.getTime() === inputDate.getTime(); - }; \ No newline at end of file + return timeDifferenceInHours >= timeElapsedInHours; +}; + +export const checkIfCurrentDate = (dateString) => { + const currentDate = new Date(); + const inputDate = new Date(dateString); + + currentDate.setHours(0, 0, 0, 0); + inputDate.setHours(0, 0, 0, 0); + + return currentDate.getTime() === inputDate.getTime(); +}; diff --git a/vite.config.ts b/vite.config.ts index b5b23fd9..32d40651 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -13,7 +13,7 @@ export default defineConfig({ define: { 'process.env': { VITE_BASE_URL: process.env.VITE_BASE_URL || 'http://localhost:5032', - }, + }, }, plugins: [react()],