diff --git a/src/components/Dashboard/ProjectCompletionChart.jsx b/src/components/Dashboard/ProjectCompletionChart.jsx index b8c656b8..f1f63936 100644 --- a/src/components/Dashboard/ProjectCompletionChart.jsx +++ b/src/components/Dashboard/ProjectCompletionChart.jsx @@ -2,15 +2,19 @@ import React, { useState } from "react"; import HorizontalBarChart from "../Charts/HorizontalBarChart"; import { useProjects } from "../../hooks/useProjects"; import { ITEMS_PER_PAGE } from "../../utils/constants"; +import { useProjectCompletionStatus } from "../../hooks/useDashboard_Data"; const ProjectCompletionChart = () => { - const [currentPage, setCurrentPage] = useState(1); - const { data: projects, isLoading: loading, isError, error } = useProjects(50,currentPage); - // Bar chart logic - const projectNames = projects?.data?.map((p) => p.name) || []; + const { + data: projects, + isLoading: loading, + isError, + error, + } = useProjectCompletionStatus(); + const projectNames = projects?.map((p) => p.name) || []; const projectProgress = - projects?.data?.map((p) => { + projects?.map((p) => { const completed = p.completedWork || 0; const planned = p.plannedWork || 1; const percent = planned ? (completed / planned) * 100 : 0; diff --git a/src/components/ServiceProject/ServiceProjectBranch/BranchDetails.jsx b/src/components/ServiceProject/ServiceProjectBranch/BranchDetails.jsx index 2aefa4ad..87d59b8c 100644 --- a/src/components/ServiceProject/ServiceProjectBranch/BranchDetails.jsx +++ b/src/components/ServiceProject/ServiceProjectBranch/BranchDetails.jsx @@ -27,59 +27,34 @@ const BranchDetails = ({ branch }) => { ); return ( -
-
- - Branch Details - -
-
-
Name:
-
{data?.branchName}
-
+<> +
+ + Branch Details + +
-
-
Type:
-
{data?.branchType}
-
-
-
Contact No:
-
{data?.contactInformation}
-
+
+
Contact No:
+
{data?.contactInformation}
+
-
-
Address:
-
{data?.address}
-
+
+
Type:
+
{data?.branchType}
+
- {googleMapUrl && ( -
-
Map:
+
+
Email:
+
{data?.email}
+
-
- - Open in Google Maps - +
+
Address:
+
{data?.address}
+
+ - - - {copied && Copied!} -
-
- )} -
); }; diff --git a/src/components/ServiceProject/ServiceProjectBranch/ServiceBranch.jsx b/src/components/ServiceProject/ServiceProjectBranch/ServiceBranch.jsx index 0655247f..cfa35f17 100644 --- a/src/components/ServiceProject/ServiceProjectBranch/ServiceBranch.jsx +++ b/src/components/ServiceProject/ServiceProjectBranch/ServiceBranch.jsx @@ -26,7 +26,6 @@ const ServiceBranch = () => { const { data, isLoading, isError, error } = useBranches( projectId, - // true, !showInactive, ITEMS_PER_PAGE - 10, currentPage, @@ -78,45 +77,47 @@ const ServiceBranch = () => {
{/* Header Section */}
-
+
- Branch + Branchs
{/* Flex container for toggle + button */} -
-
- - {/* Toggle Switch */} -
- setShowInactive(!showInactive)} - /> - -
- - {/* Add Branch Button */} - +
+
+ +
+ setShowInactive(!showInactive)} + /> + +
+
+ +
@@ -152,7 +153,6 @@ const ServiceBranch = () => { )} - {isError && ( {
- ))} @@ -247,7 +246,9 @@ const ServiceBranch = () => { setManageState({ IsOpen: false, branchId: null })} + closeModal={() => + setManageState({ IsOpen: false, branchId: null }) + } > { setManageState({ IsOpen: false, branchId: null }) } /> - )}
diff --git a/src/components/ServiceProject/ServiceProjectJob/JobComments.jsx b/src/components/ServiceProject/ServiceProjectJob/JobComments.jsx index 197aa729..4e1dfb9d 100644 --- a/src/components/ServiceProject/ServiceProjectJob/JobComments.jsx +++ b/src/components/ServiceProject/ServiceProjectJob/JobComments.jsx @@ -150,7 +150,7 @@ const JobComments = ({ data }) => { type="submit" disabled={!watch("comment")?.trim() || isPending} > - Submit + Send
diff --git a/src/components/ServiceProject/ServiceProjectJob/ManageJobTicket.jsx b/src/components/ServiceProject/ServiceProjectJob/ManageJobTicket.jsx index 12428c77..fd5c69da 100644 --- a/src/components/ServiceProject/ServiceProjectJob/ManageJobTicket.jsx +++ b/src/components/ServiceProject/ServiceProjectJob/ManageJobTicket.jsx @@ -47,7 +47,11 @@ const ManageJobTicket = ({ Job }) => {
); return ( -
+
{data?.title}
@@ -56,7 +60,7 @@ const ManageJobTicket = ({ Job }) => { {data?.jobTicketUId || "N/A"}

-
+
{data?.status?.displayName} @@ -65,6 +69,7 @@ const ManageJobTicket = ({ Job }) => { id="STATUS_CHANEG" Mode="click" className="" + align="right" content={ {

{data?.description || "N/A"}

-
-
+
+
{" "} Created Date : {formatUTCToLocalTime(data?.createdAt, true)}
+
+ {data?.tags?.map((tag, ind) => ( + + {tag?.name} + + ))} +
- + Start Date :{" "} {formatUTCToLocalTime(data?.startDate)} {" "} {" "} - + Due on :{" "} {formatUTCToLocalTime(data?.startDate)} @@ -117,7 +132,7 @@ const ManageJobTicket = ({ Job }) => { const { days, color } = daysLeft(data?.startDate, data?.dueDate); return ( - Days Left: + Days Left: {days !== null ? `${days} days` : "N/A"} @@ -125,29 +140,80 @@ const ManageJobTicket = ({ Job }) => { ); })()}
- {data?.projectBranch && ( -
- - Branch Name : + {/* {data?.projectBranch && ( +
+ + Branch Name: } > - + {data?.projectBranch?.branchName}
- )} + )} */} -
- People -
+
+

+ Peoples +

+ + {/* Created By */} +
+

Created By

+ +
+ +
+

+ {data?.createdBy?.firstName} {data?.createdBy?.lastName} +

+ + {data?.createdBy?.jobRoleName} + +
+
+
+ + {/* Assigned To */} +
+

Assigned To

+ +
+
+ {data?.assignees?.map((emp) => ( +
+ + +
+ + {emp.firstName} {emp.lastName} + + + {emp.jobRoleName} + +
+
+ ))} +
+
+
+
diff --git a/src/components/common/HoverPopup.jsx b/src/components/common/HoverPopup.jsx index 2093c25a..89716984 100644 --- a/src/components/common/HoverPopup.jsx +++ b/src/components/common/HoverPopup.jsx @@ -1,6 +1,10 @@ import React, { useEffect, useRef } from "react"; import { useDispatch, useSelector } from "react-redux"; -import { closePopup, openPopup, togglePopup } from "../../slices/localVariablesSlice"; +import { + closePopup, + openPopup, + togglePopup, +} from "../../slices/localVariablesSlice"; /** * align: "auto" | "left" | "right" @@ -63,7 +67,8 @@ const HoverPopup = ({ const popup = popupRef.current; // choose boundary: provided boundaryRef or nearest positioned parent (popup.parentElement) - const boundaryEl = (boundaryRef && boundaryRef.current) || popup.parentElement; + const boundaryEl = + (boundaryRef && boundaryRef.current) || popup.parentElement; if (!boundaryEl) return; const boundaryRect = boundaryEl.getBoundingClientRect(); @@ -75,15 +80,12 @@ const HoverPopup = ({ popup.style.transform = ""; popup.style.top = ""; - // default: place below trigger and center horizontally relative to parent - // We'll use absolute positioning with respect to the positioned parent container. - // Ensure popup is positioned using left/right in parent's coordinate system. - // Compute desired left (centered under trigger) const popupRect = popup.getBoundingClientRect(); const parentRect = boundaryRect; // alias // Convert trigger center to parent coordinates - const triggerCenterX = triggerRect.left + triggerRect.width / 2 - parentRect.left; + const triggerCenterX = + triggerRect.left + triggerRect.width / 2 - parentRect.left; // preferred left so popup center aligns to trigger center: const preferredLeft = triggerCenterX - popupRect.width / 2; @@ -111,10 +113,19 @@ const HoverPopup = ({ setRight(0); return; } + if (align === "center") { + popup.style.left = "50%"; + popup.style.right = "auto"; + popup.style.transform = "translateX(-50%)"; + return; + } // align === "auto": try preferred centered position, but flip fully if overflow // clamp preferredLeft to boundaries so it doesn't render partially outside - const leftIfCentered = Math.max(0, Math.min(preferredLeft, parentRect.width - popupRect.width)); + const leftIfCentered = Math.max( + 0, + Math.min(preferredLeft, parentRect.width - popupRect.width) + ); // if centered fits, use it if (leftIfCentered === preferredLeft) { @@ -142,8 +153,17 @@ const HoverPopup = ({ }, [visible, align, boundaryRef]); return ( -
+
{ const [dashboard_data, setDashboard_Data] = useState([]); const [isLineChartLoading, setLoading] = useState(false); @@ -18,11 +17,13 @@ export const useDashboard_Data = ({ days, FromDate, projectId }) => { try { const payload = { days, - FromDate: FromDate || '', + FromDate: FromDate || "", projectId: projectId || null, }; - const response = await GlobalRepository.getDashboardProgressionData(payload); + const response = await GlobalRepository.getDashboardProgressionData( + payload + ); setDashboard_Data(response.data); } catch (err) { setError("Failed to fetch dashboard data."); @@ -38,123 +39,6 @@ export const useDashboard_Data = ({ days, FromDate, projectId }) => { return { dashboard_data, loading: isLineChartLoading, error }; }; - -// export const useDashboard_AttendanceData = (date, projectId) => { -// const [dashboard_Attendancedata, setDashboard_AttendanceData] = useState([]); -// const [isLineChartLoading, setLoading] = useState(false); -// const [error, setError] = useState(""); - -// useEffect(() => { -// const fetchData = async () => { -// setLoading(true); -// setError(""); - -// try { -// const response = await GlobalRepository.getDashboardAttendanceData(date, projectId); // date in 2nd param -// setDashboard_AttendanceData(response.data); -// } catch (err) { -// setError("Failed to fetch dashboard data."); -// console.error(err); -// } finally { -// setLoading(false); -// } -// }; - -// if (date && projectId !== null) { -// fetchData(); -// } -// }, [date, projectId]); - -// return { dashboard_Attendancedata, isLineChartLoading: isLineChartLoading, error }; -// }; - - -// 🔹 Dashboard Projects Card Data Hook -// export const useDashboardProjectsCardData = () => { -// const [projectsCardData, setProjectsData] = useState([]); -// const [loading, setLoading] = useState(false); -// const [error, setError] = useState(""); - -// useEffect(() => { -// const fetchProjectsData = async () => { -// setLoading(true); -// setError(""); - -// try { -// const response = await GlobalRepository.getDashboardProjectsCardData(); -// setProjectsData(response.data); -// } catch (err) { -// setError("Failed to fetch projects card data."); -// console.error(err); -// } finally { -// setLoading(false); -// } -// }; - -// fetchProjectsData(); -// }, []); - -// return { projectsCardData, loading, error }; -// }; - -// 🔹 Dashboard Teams Card Data Hook -// export const useDashboardTeamsCardData = (projectId) => { -// const [teamsCardData, setTeamsData] = useState({}); -// const [loading, setLoading] = useState(false); -// const [error, setError] = useState(""); - -// useEffect(() => { -// const fetchTeamsData = async () => { -// setLoading(true); -// setError(""); - -// try { -// const response = await GlobalRepository.getDashboardTeamsCardData(projectId); -// setTeamsData(response.data || {}); -// } catch (err) { -// setError("Failed to fetch teams card data."); -// console.error("Error fetching teams card data:", err); -// setTeamsData({}); -// } finally { -// setLoading(false); -// } -// }; - -// fetchTeamsData(); -// }, [projectId]); - -// return { teamsCardData, loading, error }; -// }; - -// export const useDashboardTasksCardData = (projectId) => { -// const [tasksCardData, setTasksData] = useState({}); -// const [loading, setLoading] = useState(false); -// const [error, setError] = useState(""); - -// useEffect(() => { -// const fetchTasksData = async () => { -// setLoading(true); -// setError(""); - -// try { -// const response = await GlobalRepository.getDashboardTasksCardData(projectId); -// setTasksData(response.data); -// } catch (err) { -// setError("Failed to fetch tasks card data."); -// console.error(err); -// setTasksData({}); -// } finally { -// setLoading(false); -// } -// }; - -// fetchTasksData(); -// }, [projectId]); - -// return { tasksCardData, loading, error }; -// }; - - export const useAttendanceOverviewData = (projectId, days) => { const [attendanceOverviewData, setAttendanceOverviewData] = useState([]); const [loading, setLoading] = useState(false); @@ -167,7 +51,10 @@ export const useAttendanceOverviewData = (projectId, days) => { setError(""); try { - const response = await GlobalRepository.getAttendanceOverview(projectId, days); + const response = await GlobalRepository.getAttendanceOverview( + projectId, + days + ); setAttendanceOverviewData(response.data); } catch (err) { setError("Failed to fetch attendance overview data."); @@ -182,7 +69,6 @@ export const useAttendanceOverviewData = (projectId, days) => { return { attendanceOverviewData, loading, error }; }; - // -------------------Query---------------------------- // export const useDashboard_Data = (days, FromDate, projectId)=>{ @@ -199,39 +85,47 @@ export const useAttendanceOverviewData = (projectId, days) => { // } // }) // } - +export const useProjectCompletionStatus = () => { + return useQuery({ + queryKey: ["projectCompletionStatus"], + queryFn: async () => { + const resp = await await GlobalRepository.getProjectCompletionStatus(); + return resp.data; + }, + }); +}; export const useDashboard_AttendanceData = (date, projectId) => { return useQuery({ queryKey: ["dashboardAttendances", date, projectId], queryFn: async () => { - - const resp = await await GlobalRepository.getDashboardAttendanceData(date, projectId) + const resp = await await GlobalRepository.getDashboardAttendanceData( + date, + projectId + ); return resp.data; - } - }) -} + }, + }); +}; export const useDashboardTeamsCardData = (projectId) => { return useQuery({ queryKey: ["dashboardTeams", projectId], queryFn: async () => { - - const resp = await GlobalRepository.getDashboardTeamsCardData(projectId) + const resp = await GlobalRepository.getDashboardTeamsCardData(projectId); return resp.data; - } - }) -} + }, + }); +}; export const useDashboardTasksCardData = (projectId) => { return useQuery({ queryKey: ["dashboardTasks", projectId], queryFn: async () => { - - const resp = await GlobalRepository.getDashboardTasksCardData(projectId) + const resp = await GlobalRepository.getDashboardTasksCardData(projectId); return resp.data; - } - }) -} + }, + }); +}; // export const useAttendanceOverviewData = (projectId, days) => { // return useQuery({ // queryKey:["dashboardAttendanceOverView",projectId], @@ -247,29 +141,30 @@ export const useDashboardProjectsCardData = () => { return useQuery({ queryKey: ["dashboardProjects"], queryFn: async () => { - const resp = await GlobalRepository.getDashboardProjectsCardData(); return resp.data; - } - }) -} + }, + }); +}; export const useExpenseAnalysis = (projectId, startDate, endDate) => { const hasBothDates = !!startDate && !!endDate; const noDatesSelected = !startDate && !endDate; - const shouldFetch = - noDatesSelected || - hasBothDates; + const shouldFetch = noDatesSelected || hasBothDates; return useQuery({ queryKey: ["expenseAnalysis", projectId, startDate, endDate], queryFn: async () => { - const resp = await GlobalRepository.getExpenseData(projectId, startDate, endDate); + const resp = await GlobalRepository.getExpenseData( + projectId, + startDate, + endDate + ); return resp.data; }, enabled: shouldFetch, - refetchOnWindowFocus: true, // refetch when you come back - refetchOnMount: "always", // always refetch on remount + refetchOnWindowFocus: true, // refetch when you come back + refetchOnMount: "always", // always refetch on remount staleTime: 0, }); }; @@ -280,17 +175,20 @@ export const useExpenseStatus = (projectId) => { queryFn: async () => { const resp = await GlobalRepository.getExpenseStatus(projectId); return resp.data; - } - }) -} + }, + }); +}; export const useExpenseDataByProject = (projectId, categoryId, months) => { return useQuery({ queryKey: ["expenseByProject", projectId, categoryId, months], queryFn: async () => { - const resp = await GlobalRepository.getExpenseDataByProject(projectId, categoryId, months); + const resp = await GlobalRepository.getExpenseDataByProject( + projectId, + categoryId, + months + ); return resp.data; }, - }); -}; \ No newline at end of file +}; diff --git a/src/repositories/GlobalRepository.jsx b/src/repositories/GlobalRepository.jsx index ec90d25d..2516020a 100644 --- a/src/repositories/GlobalRepository.jsx +++ b/src/repositories/GlobalRepository.jsx @@ -18,6 +18,8 @@ const GlobalRepository = { return api.get(`/api/Dashboard/Progression?${params.toString()}`); }, + getProjectCompletionStatus:()=>api.get(`/api/Dashboard/project-completion-status`), + getDashboardAttendanceData: (date, projectId) => { diff --git a/src/repositories/ProjectRepository.jsx b/src/repositories/ProjectRepository.jsx index 86e59955..9894feae 100644 --- a/src/repositories/ProjectRepository.jsx +++ b/src/repositories/ProjectRepository.jsx @@ -1,6 +1,7 @@ import { api } from "../utils/axiosClient"; const ProjectRepository = { + getProjectList: (pageSize, pageNumber) => api.get(`/api/project/list?pageSize=${pageSize}&pageNumber=${pageNumber}`), getProjectByprojectId: (projetid) =>