diff --git a/src/components/ServiceProject/ManageJob.jsx b/src/components/ServiceProject/ManageJob.jsx index c0d9223e..97cd1a97 100644 --- a/src/components/ServiceProject/ManageJob.jsx +++ b/src/components/ServiceProject/ManageJob.jsx @@ -4,6 +4,7 @@ import Label from "../common/Label"; import { zodResolver } from "@hookform/resolvers/zod"; import { defaultJobValue, jobSchema } from "./ServiceProjectSchema"; import { + useBranches, useCreateServiceProjectJob, useJobTags, useServiceProjectJobDetails, @@ -25,6 +26,7 @@ import { useParams } from "react-router-dom"; import { useDispatch } from "react-redux"; import { useJobStatus } from "../../hooks/masterHook/useMaster"; import { useServiceProjectJobContext } from "./Jobs"; +import { SelectFieldSearch } from "../common/Forms/SelectFieldServerSide"; const ManageJob = ({ Job }) => { const { setManageJob, setSelectedJob } = useServiceProjectJobContext(); @@ -39,7 +41,7 @@ const ManageJob = ({ Job }) => { control, watch, handleSubmit, - reset, + reset,setValue, formState: { errors }, } = methods; @@ -199,7 +201,7 @@ const ManageJob = ({ Job }) => { />
- + { name="tags" label="Tag" placeholder="Enter Tag" + + /> +
+
+ setValue("branchId", val)} + valueKey="id" + labelKey="branchName" + hookParams={[projectId,true,10,1]} + useFetchHook={useBranches} + isMultiple={false} />
diff --git a/src/components/ServiceProject/ServiceProjectSchema.jsx b/src/components/ServiceProject/ServiceProjectSchema.jsx index 5a5727b7..9a14605c 100644 --- a/src/components/ServiceProject/ServiceProjectSchema.jsx +++ b/src/components/ServiceProject/ServiceProjectSchema.jsx @@ -70,6 +70,8 @@ export const jobSchema = z.object({ tags: z.array(TagSchema).optional().default([]), statusId: z.string().optional().nullable(), + + branchId: z.string().optional().nullable(), }); const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB @@ -109,6 +111,7 @@ export const defaultJobValue = { startDate: null, dueDate: null, tags: [], + branchId: null, }; //#endregion diff --git a/src/components/common/Forms/SelectFieldServerSide.jsx b/src/components/common/Forms/SelectFieldServerSide.jsx index 6ff6eb90..de0265af 100644 --- a/src/components/common/Forms/SelectFieldServerSide.jsx +++ b/src/components/common/Forms/SelectFieldServerSide.jsx @@ -361,3 +361,182 @@ export const SelectProjectField = ({
); }; + + + +export const SelectFieldSearch = ({ + label = "Select", + placeholder = "Select ", + required = false, + value = null, + onChange, + valueKey = "id", + labelKey = "name", + + isFullObject = false, + isMultiple = false, + hookParams, + useFetchHook, +}) => { + const [searchText, setSearchText] = useState(""); + const debounce = useDebounce(searchText, 300); + + const { data, isLoading } = useFetchHook(...hookParams,debounce); + const options = data?.data ?? []; + const [open, setOpen] = useState(false); + const dropdownRef = useRef(null); + + const getDisplayName = (entity) => { + if (!entity) return ""; + return `${entity[labelKey] || ""}`.trim(); + }; + + /** ----------------------------- + * SELECTED OPTION (SINGLE) + * ----------------------------- */ + let selectedSingle = null; + + if (!isMultiple) { + if (isFullObject && value) selectedSingle = value; + else if (!isFullObject && value) + selectedSingle = options.find((o) => o[valueKey] === value); + } + + /** ----------------------------- + * SELECTED OPTION (MULTIPLE) + * ----------------------------- */ + let selectedList = []; + if (isMultiple && Array.isArray(value)) { + if (isFullObject) selectedList = value; + else { + selectedList = options.filter((opt) => value.includes(opt[valueKey])); + } + } + + /** Main button label */ + const displayText = !isMultiple + ? getDisplayName(selectedSingle) || placeholder + : selectedList.length > 0 + ? selectedList.map((e) => getDisplayName(e)).join(", ") + : placeholder; + + /** ----------------------------- + * HANDLE OUTSIDE CLICK + * ----------------------------- */ + useEffect(() => { + const handleClickOutside = (e) => { + if (dropdownRef.current && !dropdownRef.current.contains(e.target)) { + setOpen(false); + } + }; + + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, []); + + /** ----------------------------- + * HANDLE SELECT + * ----------------------------- */ + const handleSelect = (option) => { + if (!isMultiple) { + // SINGLE SELECT + if (isFullObject) onChange(option); + else onChange(option[valueKey]); + } else { + // MULTIPLE SELECT + let updated = []; + + const exists = selectedList.some((e) => e[valueKey] === option[valueKey]); + + if (exists) { + // remove + updated = selectedList.filter((e) => e[valueKey] !== option[valueKey]); + } else { + // add + updated = [...selectedList, option]; + } + + if (isFullObject) onChange(updated); + else onChange(updated.map((x) => x[valueKey])); + } + }; + + return ( +
+ {label && ( + + )} + + {/* MAIN BUTTON */} + + + {/* DROPDOWN */} + {open && ( + + )} +
+ ); +}; diff --git a/src/hooks/useServiceProject.jsx b/src/hooks/useServiceProject.jsx index 3dfd4115..f5baa4b7 100644 --- a/src/hooks/useServiceProject.jsx +++ b/src/hooks/useServiceProject.jsx @@ -308,13 +308,15 @@ export const useBranches = ( pageNumber, searchString ); + console.log(resp) return resp.data; }, enabled: !!projectId, }); }; -export const useBranch = (id) => { + +export const useBranch = (id)=>{ return useQuery({ queryKey: ["branch", id], queryFn: async () => { diff --git a/src/repositories/ServiceProjectRepository.jsx b/src/repositories/ServiceProjectRepository.jsx index e838a04b..1fa29fa9 100644 --- a/src/repositories/ServiceProjectRepository.jsx +++ b/src/repositories/ServiceProjectRepository.jsx @@ -45,8 +45,8 @@ export const ServiceProjectRepository = { UpdateBranch: (id, data) => api.put("/api/ServiceProject/branch/edit/${id}", data), GetBranchList: (projectId, isActive, pageSize, pageNumber, searchString) => { - api.get( - `/api/ServiceProject/branch/list/${projectId}/?isActive=${isActive}&pageSize=${pageSize}&pageNumber=${pageNumber}&searchString=${searchString}` + return api.get( + `/api/ServiceProject/branch/list/${projectId}?isActive=${isActive}&pageSize=${pageSize}&pageNumber=${pageNumber}&searchString=${searchString}` ); },