diff --git a/src/components/Dashboard/ProjectCompletionChart.jsx b/src/components/Dashboard/ProjectCompletionChart.jsx index 5bc9dde0..b8c656b8 100644 --- a/src/components/Dashboard/ProjectCompletionChart.jsx +++ b/src/components/Dashboard/ProjectCompletionChart.jsx @@ -6,11 +6,11 @@ import { ITEMS_PER_PAGE } from "../../utils/constants"; const ProjectCompletionChart = () => { const [currentPage, setCurrentPage] = useState(1); - const { data: projects, isLoading: loading, isError, error } = useProjects(ITEMS_PER_PAGE,currentPage); + const { data: projects, isLoading: loading, isError, error } = useProjects(50,currentPage); // Bar chart logic - const projectNames = projects?.data.map((p) => p.name) || []; + const projectNames = projects?.data?.map((p) => p.name) || []; const projectProgress = - projects?.map((p) => { + projects?.data?.map((p) => { const completed = p.completedWork || 0; const planned = p.plannedWork || 1; const percent = planned ? (completed / planned) * 100 : 0; diff --git a/src/components/Project/ProjectListView.jsx b/src/components/Project/ProjectListView.jsx index 3bf9b160..2741801e 100644 --- a/src/components/Project/ProjectListView.jsx +++ b/src/components/Project/ProjectListView.jsx @@ -13,15 +13,9 @@ import { useNavigate } from "react-router-dom"; import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import { useProjectContext } from "../../pages/project/ProjectPage"; import usePagination from "../../hooks/usePagination"; +import Pagination from "../common/Pagination"; -const ProjectListView = ({ - currentItems, - selectedStatuses, - handleStatusChange, - setCurrentPage, - totalPages, - isLoading, -}) => { +const ProjectListView = ({ data, currentPage, totalPages, paginate }) => { const dispatch = useDispatch(); const navigate = useNavigate(); const { setMangeProject } = useProjectContext(); @@ -132,152 +126,103 @@ const ProjectListView = ({ return (
- -
- - - - {projectColumns.map((col) => ( - - ))} - - - - - {currentItems?.map((project) => ( - +
+
- {col.label} - Action
+ + {projectColumns.map((col) => ( - + {col.label} + ))} - + - ))} - -
- {col.getValue - ? col.getValue(project) - : project[col.key] || "N/A"} - - - Action
+ + + {data?.map((project) => ( + + {projectColumns.map((col) => ( + + {col.getValue + ? col.getValue(project) + : project[col.key] || "N/A"} + + ))} + +
+ + +
+ + + ))} + +
- {isLoading && ( -
- {" "} - {isLoading &&

Loading...

} - {!isLoading && filteredProjects.length === 0 && ( -

No projects found.

- )} -
- )} - {!isLoading && currentItems.length === 0 && ( -
-

No projects found.

-
- )} - {!isLoading && totalPages > 1 && ( - - )} +
); }; diff --git a/src/components/ServiceProject/ManageJobTicket.jsx b/src/components/ServiceProject/ManageJobTicket.jsx index 9094c336..9dbf0b9f 100644 --- a/src/components/ServiceProject/ManageJobTicket.jsx +++ b/src/components/ServiceProject/ManageJobTicket.jsx @@ -11,7 +11,7 @@ import { daysLeft, getJobStatusBadge } from "../../utils/appUtils"; import HoverPopup from "../common/HoverPopup"; import ChangeStatus from "./ChangeStatus"; import { useParams } from "react-router-dom"; -import { STATUS_JOB_DONE } from "../../utils/constants"; +import { STATUS_JOB_CLOSED } from "../../utils/constants"; import Tooltip from "../common/Tooltip"; const ManageJobTicket = ({ Job }) => { @@ -58,7 +58,7 @@ const ManageJobTicket = ({ Job }) => { {data?.status?.displayName} - {STATUS_JOB_DONE !== data?.status?.id && ( + {STATUS_JOB_CLOSED !== data?.status?.id && ( {
  • {/* Added mt-4 for some top margin */} -
  • {/* Added mt-4 for some top margin */} + {/* Added mt-4 for some top margin */} -
  • + diff --git a/src/components/common/Forms/InputFieldSuggesstion.jsx b/src/components/common/Forms/InputFieldSuggesstion.jsx deleted file mode 100644 index 881eb16c..00000000 --- a/src/components/common/Forms/InputFieldSuggesstion.jsx +++ /dev/null @@ -1,56 +0,0 @@ -import React from 'react' - -const InputFieldSuggesstion = () => { - return ( -
    - setTimeout(() => setShowSuggestions(false), 150)} - onFocus={() => { - if (value) setShowSuggestions(true); - }} - disabled={disabled} - /> - {showSuggestions && filteredList.length > 0 && ( - - )} - - {error && {error}} -
    - ) -} - -export default InputFieldSuggesstion diff --git a/src/components/common/Forms/InputSuggesstionField.jsx b/src/components/common/Forms/InputSuggesstionField.jsx new file mode 100644 index 00000000..9ef02e9d --- /dev/null +++ b/src/components/common/Forms/InputSuggesstionField.jsx @@ -0,0 +1,90 @@ +import React, { useEffect, useRef, useState } from "react"; +import Label from "../Label"; + +const InputSuggessionField = ({ + organizationList = [], + value, + onChange, + error, + disabled=false +}) => { + const [open, setOpen] = useState(false); + const dropdownRef = useRef(null); + + useEffect(() => { + const handleClickOutside = (event) => { + if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { + setOpen(false); + } + }; + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, []); + + const selectedOption = options.find((opt) => opt[valueKey] === value); + + const displayText = selectedOption ? selectedOption[labelKey] : placeholder; + + const handleSelect = (option) => { + onChange(option[valueKey]); + setOpen(false); + }; + + const toggleDropdown = () => setOpen((prev) => !prev); + + return ( +
    + {label && ( + + )} + + + + {open && !isLoading && ( + + )} +
    + ); +}; + +export default InputSuggessionField; diff --git a/src/components/common/Forms/SelectFieldServerSide.jsx b/src/components/common/Forms/SelectFieldServerSide.jsx index f7aa70eb..6ff6eb90 100644 --- a/src/components/common/Forms/SelectFieldServerSide.jsx +++ b/src/components/common/Forms/SelectFieldServerSide.jsx @@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from "react"; import Label from "../Label"; import { useDebounce } from "../../../utils/appUtils"; import { useEmployeesName } from "../../../hooks/useEmployees"; +import { useProjectBothName } from "../../../hooks/useProjects"; const SelectEmployeeServerSide = ({ label = "Select", @@ -154,7 +155,9 @@ const SelectEmployeeServerSide = ({ )} {!isLoading && options.length === 0 && ( -
  • No results found
  • +
  • + No results found +
  • )} {!isLoading && @@ -183,24 +186,29 @@ const SelectEmployeeServerSide = ({ }; export default SelectEmployeeServerSide; - -export const SelectProjectField = ()=>{ - const [searchText, setSearchText] = useState(""); +export const SelectProjectField = ({ + label = "Select", + placeholder = "Select Project", + required = false, + value = null, + onChange, + valueKey = "id", + isFullObject = false, + isMultiple = false, + isAllProject = false, +}) => { + const [searchText, setSearchText] = useState(""); const debounce = useDebounce(searchText, 300); - const { data, isLoading } = useEmployeesName( - projectId, - debounce, - isAllEmployee - ); + const { data, isLoading } = useProjectBothName(debounce); - const options = data?.data ?? []; + const options = data ?? []; const [open, setOpen] = useState(false); const dropdownRef = useRef(null); - const getDisplayName = (emp) => { - if (!emp) return ""; - return `${emp.firstName || ""} ${emp.lastName || ""}`.trim(); + const getDisplayName = (project) => { + if (!project) return ""; + return `${project.name || ""}`.trim(); }; /** ----------------------------- @@ -304,7 +312,7 @@ export const SelectProjectField = ()=>{ top: "100%", left: 0, zIndex: 1050, - marginTop: "4px", + marginTop: "2px", borderRadius: "0.375rem", overflow: "hidden", }} @@ -324,7 +332,9 @@ export const SelectProjectField = ()=>{ )} {!isLoading && options.length === 0 && ( -
  • No results found
  • +
  • + No results found +
  • )} {!isLoading && @@ -350,4 +360,4 @@ export const SelectProjectField = ()=>{ )} ); -}; \ No newline at end of file +}; diff --git a/src/components/common/MultiSelectDropdown.css b/src/components/common/MultiSelectDropdown.css index 394f24db..3bbd482c 100644 --- a/src/components/common/MultiSelectDropdown.css +++ b/src/components/common/MultiSelectDropdown.css @@ -10,7 +10,7 @@ display: flex; justify-content: space-between; align-items: center; - padding: 5px; + padding: 4px; border: 1px solid #ddd; border-radius: 5px; cursor: pointer; diff --git a/src/components/common/SelectMultiple.jsx b/src/components/common/SelectMultiple.jsx index 0fae63df..8d4aae7d 100644 --- a/src/components/common/SelectMultiple.jsx +++ b/src/components/common/SelectMultiple.jsx @@ -101,7 +101,7 @@ const SelectMultiple = ({ value={searchText} onChange={(e) => setSearchText(e.target.value)} className="multi-select-dropdown-search-input" - style={{ width: "100%", padding: 4 }} + style={{ width: "100%", }} /> @@ -177,7 +177,7 @@ const SelectMultiple = ({ return ( {label} diff --git a/src/hooks/useProjects.js b/src/hooks/useProjects.js index fcb715b6..25caf14b 100644 --- a/src/hooks/useProjects.js +++ b/src/hooks/useProjects.js @@ -20,12 +20,15 @@ export const useCurrentService = () => { // ------------------------------Query------------------- -export const useProjects = (pageSize,pageNumber) => { +export const useProjects = (pageSize, pageNumber) => { const loggedUser = useSelector((store) => store.globalVariables.loginUser); return useQuery({ - queryKey: ["ProjectsList",pageSize,pageNumber], + queryKey: ["ProjectsList", pageSize, pageNumber], queryFn: async () => { - const response = await ProjectRepository.getProjectList(pageSize,pageNumber); + const response = await ProjectRepository.getProjectList( + pageSize, + pageNumber + ); return response?.data; }, enabled: !!loggedUser, @@ -153,7 +156,7 @@ export const useProjectsAllocationByEmployee = (employeeId) => { return { projectList, loading: isLoading, error, refetch }; }; -export const useProjectName = (provideAll=false) => { +export const useProjectName = (provideAll = false) => { const { data = [], isLoading, @@ -161,7 +164,7 @@ export const useProjectName = (provideAll=false) => { refetch, isError, } = useQuery({ - queryKey: ["basicProjectNameList",provideAll], + queryKey: ["basicProjectNameList", provideAll], queryFn: async () => { const res = await ProjectRepository.projectNameList(provideAll); return res.data || res; @@ -179,6 +182,19 @@ export const useProjectName = (provideAll=false) => { }; }; +export const useProjectBothName = (searchString) => { + return useQuery({ + queryKey: ["basic_bothProject", searchString], + queryFn: async () => { + const res = await ProjectRepository.projectNameListAll(searchString); + return res.data || res; + }, + onError: (error) => { + showToast(error.message || "Error while Fetching project Name", "error"); + }, + }); +}; + export const useProjectInfra = (projectId, serviceId) => { const { data: projectInfra, @@ -337,7 +353,7 @@ export const useEmployeeForTaskAssign = ( // -- -------------Mutation------------------------------- -export const useCreateProject = ( onSuccessCallback ) => { +export const useCreateProject = (onSuccessCallback) => { const queryClient = useQueryClient(); return useMutation({ @@ -368,7 +384,7 @@ export const useCreateProject = ( onSuccessCallback ) => { }); }; -export const useUpdateProject = ( onSuccessCallback ) => { +export const useUpdateProject = (onSuccessCallback) => { const queryClient = useQueryClient(); const { mutate, isPending, isSuccess, isError } = useMutation({ mutationFn: async ({ projectId, payload }) => { diff --git a/src/pages/ServiceProject/ServiceProjectDisplay.jsx b/src/pages/ServiceProject/ServiceProjectDisplay.jsx index 96a9ddb4..1d59f1f2 100644 --- a/src/pages/ServiceProject/ServiceProjectDisplay.jsx +++ b/src/pages/ServiceProject/ServiceProjectDisplay.jsx @@ -52,7 +52,7 @@ const ServiceProjectDisplay = ({ listView ,selectedStatuses }) => {

    List

    ) : ( filteredProjects?.map((project) => ( - + )) )} diff --git a/src/pages/project/ProjectPage.jsx b/src/pages/project/ProjectPage.jsx index ad2c3d80..d9557f48 100644 --- a/src/pages/project/ProjectPage.jsx +++ b/src/pages/project/ProjectPage.jsx @@ -83,7 +83,7 @@ const ProjectPage = () => {
    -
    +
    {/* LEFT SIDE — DATE TOGGLE BUTTONS */}
    @@ -179,7 +179,7 @@ const ProjectPage = () => { {HasManageProject && (
    ); - + return (
    {listView ? ( ) : ( )} - {/* Project Manage Update or Create */} {manageProject?.isOpen && ( )} -
    ); }; diff --git a/src/repositories/ProjectRepository.jsx b/src/repositories/ProjectRepository.jsx index 1220d085..86e59955 100644 --- a/src/repositories/ProjectRepository.jsx +++ b/src/repositories/ProjectRepository.jsx @@ -1,17 +1,24 @@ import { api } from "../utils/axiosClient"; const ProjectRepository = { - getProjectList: (pageSize,pageNumber) => api.get(`/api/project/list?pageSize=${pageSize}&pageNumber=${pageNumber}`), + getProjectList: (pageSize, pageNumber) => + api.get(`/api/project/list?pageSize=${pageSize}&pageNumber=${pageNumber}`), getProjectByprojectId: (projetid) => api.get(`/api/project/details/${projetid}`), - getProjectAllocation: (projectId, serviceId, organizationId, employeeStatus) => { + getProjectAllocation: ( + projectId, + serviceId, + organizationId, + employeeStatus + ) => { let url = `/api/project/allocation/${projectId}`; const params = []; if (organizationId) params.push(`organizationId=${organizationId}`); if (serviceId) params.push(`serviceId=${serviceId}`); - if (employeeStatus !== undefined) params.push(`includeInactive=${employeeStatus}`); + if (employeeStatus !== undefined) + params.push(`includeInactive=${employeeStatus}`); if (params.length > 0) { url += `?${params.join("&")}`; @@ -20,7 +27,6 @@ const ProjectRepository = { return api.get(url); }, - getEmployeesByProject: (projectId) => api.get(`/api/Project/employees/get/${projectId}`), @@ -40,10 +46,13 @@ const ProjectRepository = { api.get(`/api/project/allocation-histery/${id}`), updateProjectsByEmployee: (id, data) => api.post(`/api/project/assign-projects/${id}`, data), - projectNameList: (provideAll) => api.get(`/api/project/list/basic?provideAll=${provideAll}`), + projectNameList: (provideAll) => + api.get(`/api/project/list/basic?provideAll=${provideAll}`), + projectNameListAll: (searchString) => + api.get(`/api/project/list/basic/all?searchString=${searchString}`), getProjectDetails: (id) => api.get(`/api/project/details/${id}`), - + getProjectInfraByproject: (projectId, serviceId) => { let url = `/api/project/infra-details/${projectId}`; if (serviceId) { @@ -85,7 +94,7 @@ const ProjectRepository = { api.get(`/api/Project/get/assigned/services/${projectId}`), getProjectAssignedOrganizations: (projectId) => api.get(`/api/Project/get/assigned/organization/${projectId}`), - getProjectAssignedOrganizationsName: (projectId) => + getProjectAssignedOrganizationsName: (projectId) => api.get(`/api/Project/get/assigned/organization/dropdown/${projectId}`), getEmployeeForTaskAssign: (projectId, serviceId, organizationId) => { diff --git a/src/utils/constants.jsx b/src/utils/constants.jsx index 24121cb0..2375b010 100644 --- a/src/utils/constants.jsx +++ b/src/utils/constants.jsx @@ -208,6 +208,6 @@ export const PAYEE_RECURRING_EXPENSE = [ //#region Service Project and Jobs -export const STATUS_JOB_DONE = "ed10ab57-dbaa-4ca5-8ecd-56745dcbdbd7" +export const STATUS_JOB_CLOSED = "3ddeefb5-ae3c-4e10-a922-35e0a452bb69" //#endregion \ No newline at end of file