Adding dropdown across all places.

This commit is contained in:
Kartik Sharma 2025-12-06 14:49:23 +05:30
parent 48ff718da4
commit 72b533226a
4 changed files with 483 additions and 374 deletions

View File

@ -144,31 +144,42 @@ const FloorModel = ({ project, onClose, onSubmit }) => {
name="id" name="id"
control={control} control={control}
rules={{ required: "Floor is required" }} rules={{ required: "Floor is required" }}
render={({ field }) => ( render={({ field }) => {
<SelectField // Prepare options
label="" // Label is already above const floorOptions = [
placeholder="Select Floor" { id: "0", name: "Add New Floor" },
options={[ ...(selectedBuilding?.floors
{ id: "0", name: "Add New Floor" }, ?.filter((f) => f.floorName)
...(selectedBuilding?.floors .sort((a, b) => a.floorName.localeCompare(b.floorName))
?.filter((f) => f.floorName) .map((f) => ({ id: f.id, name: f.floorName })) ?? []),
.sort((a, b) => a.floorName.localeCompare(b.floorName)) ];
.map((f) => ({ id: f.id, name: f.floorName })) ?? []),
]} return (
value={field.value || ""} <SelectField
onChange={(value) => { label=""
field.onChange(value); placeholder="Select Floor"
handleFloorChange?.(value); options={floorOptions}
}} value={field.value || "0"} // default to "0"
required onChange={(val) => {
noOptionsMessage={() => field.onChange(val); // update react-hook-form
!selectedBuilding?.floors || selectedBuilding.floors.length === 0
? "No floors found" if (val === "0") {
: null setValue("floorName", ""); // clear for new floor
} } else {
className="m-0 form-select-sm w-100" const floor = selectedBuilding?.floors?.find(f => f.id === val);
/> setValue("floorName", floor?.floorName || "");
)} }
}}
required
noOptionsMessage={() =>
!selectedBuilding?.floors || selectedBuilding.floors.length === 0
? "No floors found"
: null
}
className="m-0 form-select-sm w-100"
/>
);
}}
/> />
{errors.id && ( {errors.id && (

View File

@ -8,10 +8,12 @@ import {
useGroups, useGroups,
useWorkCategoriesMaster, useWorkCategoriesMaster,
} from "../../../hooks/masterHook/useMaster"; } from "../../../hooks/masterHook/useMaster";
import { useManageTask, useProjectAssignedOrganizationsName, useProjectAssignedServices } from "../../../hooks/useProjects"; import { useManageTask, useProjectAssignedOrganizationsName, useProjectAssignedServices } from "../../../hooks/useProjects";
import showToast from "../../../services/toastService"; import showToast from "../../../services/toastService";
import Label from "../../common/Label"; import Label from "../../common/Label";
import { useSelectedProject } from "../../../slices/apiDataManager"; import { useSelectedProject } from "../../../slices/apiDataManager";
import { AppFormController, AppFormProvider } from "../../../hooks/appHooks/useAppForm";
import SelectField from "../../common/Forms/SelectField";
const taskSchema = z.object({ const taskSchema = z.object({
buildingID: z.string().min(1, "Building is required"), buildingID: z.string().min(1, "Building is required"),
@ -76,19 +78,13 @@ const TaskModel = ({ project, onSubmit, onClose }) => {
setValue("activityID", ""); setValue("activityID", "");
}; };
const methods = useForm({
const {
register,
handleSubmit,
watch,
setValue,
reset,
formState: { errors },
} = useForm({
resolver: zodResolver(taskSchema),
defaultValues: defaultModel, defaultValues: defaultModel,
resolver: zodResolver(taskSchema),
}); });
const { register, control, watch, handleSubmit, reset, setValue, formState: { errors } } = methods;
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
const [activityData, setActivityData] = useState([]); const [activityData, setActivityData] = useState([]);
const [categoryData, setCategoryData] = useState([]); const [categoryData, setCategoryData] = useState([]);
@ -112,10 +108,10 @@ const TaskModel = ({ project, onSubmit, onClose }) => {
const { mutate: CreateTask, isPending } = useManageTask({ const { mutate: CreateTask, isPending } = useManageTask({
onSuccessCallback: (response) => { onSuccessCallback: (response) => {
showToast(response?.message, "success"); showToast(response?.message, "success");
setValue("activityID",""), setValue("activityID", ""),
setValue("plannedWork",0), setValue("plannedWork", 0),
setValue("completedWork",0) setValue("completedWork", 0)
setValue("comment","") setValue("comment", "")
}, },
}); });
useEffect(() => { useEffect(() => {
@ -148,224 +144,290 @@ const TaskModel = ({ project, onSubmit, onClose }) => {
}; };
return ( return (
<form className="row g-2" onSubmit={handleSubmit(onSubmitForm)}> <AppFormProvider {...methods}>
<div className="text-center mb-1"> <form className="row g-2" onSubmit={handleSubmit(onSubmitForm)}>
<h5 className="mb-1">Manage Task</h5> <div className="text-center mb-1">
</div> <h5 className="mb-1">Manage Task</h5>
<div className="col-6 text-start"> </div>
<Label className="form-label" required>Select Building</Label> {/* Select Building */}
<select
className="form-select form-select-sm"
{...register("buildingID")}
>
<option value="">Select Building</option>
{project
?.filter((b) => b?.buildingName)
?.sort((a, b) => a?.buildingName.localeCompare(b.buildingName))
?.map((b) => (
<option key={b.id} value={b.id}>
{b.buildingName}
</option>
))}
</select>
{errors.buildingID && (
<p className="danger-text">{errors.buildingID.message}</p>
)}
</div>
{selectedBuilding && (
<div className="col-6 text-start"> <div className="col-6 text-start">
<Label className="form-label" required>Select Floor</Label> <AppFormController
<select name="buildingID"
className="form-select form-select-sm" control={control}
{...register("floorId")} render={({ field }) => (
> <SelectField
<option value="">Select Floor</option> label="Select Building"
{selectedBuilding.floors options={project ?? []}
?.sort((a, b) => a.floorName.localeCompare(b.floorName)) placeholder="Select Building"
?.map((f) => ( required
<option key={f.id} value={f.id}> labelKey="buildingName"
{f.floorName} valueKey="id"
</option> value={field.value}
))} onChange={(value) => {
</select> field.onChange(value);
{errors.floorId && ( setValue("floorId", "");
<p className="danger-text">{errors.floorId.message}</p> setValue("workAreaId", "");
)} setSelectedService("");
</div> setSelectedGroup("");
)} }}
className="m-0"
{/* Work Area Selection */} />
{selectedFloor && (
<div className="col-12 text-start">
<Label className="form-label" required>Select Work Area</Label>
<select
className="form-select form-select-sm"
{...register("workAreaId")}
>
<option value="">Select Work Area</option>
{selectedFloor.workAreas
?.sort((a, b) => a.areaName.localeCompare(b.areaName))
?.map((w) => (
<option key={w.id} value={w.id}>
{w.areaName}
</option>
))}
</select>
{errors.workAreaId && (
<p className="danger-text">{errors.workAreaId.message}</p>
)}
</div>
)}
{/* Services Selection */}
{selectedWorkArea && (
<div className="col-12 text-start">
<Label className="form-label" required>Select Service</Label>
<select
className="form-select form-select-sm"
{...register("serviceId")}
value={selectedService}
// onChange={handleServiceChange}
onChange={(e) => {
handleServiceChange(e);
setValue("serviceId", e.target.value);
}}
>
<option value="">Select Service</option>
{servicesLoading && <option>Loading...</option>}
{assignedServices?.map((service) => (
<option key={service.id} value={service.id}>
{service.name}
</option>
))}
</select>
</div>
)}
{/* Activity Group (Organization) Selection */}
{selectedService && (
<div className="col-12 text-start">
<Label className="form-label" required>Select Activity Group</Label>
<select
className="form-select form-select-sm"
{...register("activityGroupId")}
value={selectedGroup}
onChange={handleGroupChange}
>
<option value="">Select Group</option>
{groupsLoading && <option>Loading...</option>}
{groups?.map((g) => (
<option key={g.id} value={g.id}>{g.name}</option>
))}
</select>
{errors.activityGroupId && <p className="danger-text">{errors.activityGroupId.message}</p>}
</div>
)}
{/* Activity Selection */}
{selectedGroup && (
<div className="col-12 text-start">
<Label className="form-label" required>Select Activity</Label>
<select className="form-select form-select-sm" {...register("activityID")}>
<option value="">Select Activity</option>
{activitiesLoading && <option>Loading...</option>}
{activities?.map((a) => (
<option key={a.id} value={a.id}>{a.activityName}</option>
))}
</select>
{errors.activityID && <p className="danger-text">{errors.activityID.message}</p>}
</div>
)}
{watchActivityId && (
<div className="col-12 text-start">
<label className="form-label">Select Work Category</label>
<select
className="form-select form-select-sm"
{...register("workCategoryId")}
>
{categoryData.map((c) => (
<option key={c.id} value={c.id}>
{c.name}
</option>
))}
</select>
{errors.workCategoryId && (
<p className="danger-text">{errors.workCategoryId.message}</p>
)}
</div>
)}
{selectedActivity && selectedCategory && (
<>
<div className="col-5 text-start">
<Label className="form-label" required>Planned Work</Label>
<input
type="number"
className="form-control form-control-sm"
{...register("plannedWork", { valueAsNumber: true })}
/>
{errors.plannedWork && (
<p className="danger-text">{errors.plannedWork.message}</p>
)} )}
</div>
<div className="col-5 text-start">
<label className="form-label">Completed Work</label>
<input
type="number"
className="form-control form-control-sm"
{...register("completedWork", { valueAsNumber: true })}
/>
{errors.completedWork && (
<p className="danger-text">{errors.completedWork.message}</p>
)}
</div>
<div className="col-2 text-start">
<label className="form-label">Unit</label>
<input
type="text"
className="form-control form-control-sm"
disabled
value={selectedActivity?.unitOfMeasurement || ""}
/>
</div>
</>
)}
{selectedActivity && selectedCategory && (
<div className="col-12 text-start">
<label className="form-label">Comment</label>
<textarea
className="form-control"
rows="2"
{...register("comment")}
/> />
{errors.comment && ( {errors.buildingID && (
<p className="danger-text">{errors.comment.message}</p> <small className="danger-text">{errors.buildingID.message}</small>
)} )}
</div> </div>
)}
<div className="col-12 text-end mt-6 my-2"> {/* Select Floor */}
<button {selectedBuilding && (
type="button" <div className="col-6 text-start">
className="btn btn-sm btn-label-secondary me-3" <AppFormController
onClick={onClose} name="floorId"
> control={control}
Cancel render={({ field }) => (
</button> <SelectField
<button label="Select Floor"
type="submit" options={selectedBuilding?.floors ?? []}
className="btn btn-sm btn-primary" placeholder={
// disabled={isSubmitting} selectedBuilding?.floors?.length > 0
disabled={isPending} ? "Select Floor"
> : "No Floor Found"
{isPending ? "Please Wait..." : "Add Task"} }
</button> required
</div> labelKey="floorName"
</form> valueKey="id"
value={field.value}
onChange={(value) => {
field.onChange(value);
setValue("workAreaId", "");
}}
className="m-0"
/>
)}
/>
{errors.floorId && (
<small className="danger-text">{errors.floorId.message}</small>
)}
</div>
)}
{/* Select Work Area */}
{selectedFloor && (
<div className="col-12 text-start">
<AppFormController
name="workAreaId"
control={control}
render={({ field }) => (
<SelectField
label="Select Work Area"
options={selectedFloor?.workAreas ?? []}
placeholder="Select Work Area"
required
labelKey="areaName"
valueKey="id"
value={field.value}
onChange={(value) => {
field.onChange(value);
setSelectedService("");
setSelectedGroup("");
}}
className="m-0"
/>
)}
/>
{errors.workAreaId && (
<small className="danger-text">{errors.workAreaId.message}</small>
)}
</div>
)}
{/* Select Service */}
{selectedWorkArea && (
<div className="col-12 text-start">
<AppFormController
name="serviceId"
control={control}
render={({ field }) => (
<SelectField
label="Select Service"
options={assignedServices ?? []}
placeholder="Select Service"
required
labelKey="name"
valueKey="id"
value={field.value}
onChange={(value) => {
field.onChange(value);
setSelectedService(value);
setSelectedGroup("");
setValue("activityGroupId", "");
setValue("activityID", "");
}}
isLoading={servicesLoading}
className="m-0"
/>
)}
/>
{errors.serviceId && (
<small className="danger-text">{errors.serviceId.message}</small>
)}
</div>
)}
{/* Select Activity Group */}
{selectedService && (
<div className="col-12 text-start">
<AppFormController
name="activityGroupId"
control={control}
render={({ field }) => (
<SelectField
label="Select Activity Group"
options={groups ?? []}
placeholder="Select Activity Group"
required
labelKey="name"
valueKey="id"
value={field.value}
onChange={(value) => {
field.onChange(value);
setSelectedGroup(value);
setValue("activityID", "");
}}
isLoading={groupsLoading}
className="m-0"
/>
)}
/>
{errors.activityGroupId && (
<small className="danger-text">{errors.activityGroupId.message}</small>
)}
</div>
)}
{/* Select Activity */}
{selectedGroup && (
<div className="col-12 text-start">
<AppFormController
name="activityID"
control={control}
render={({ field }) => (
<SelectField
label="Select Activity"
options={activities ?? []}
placeholder="Select Activity"
required
labelKey="activityName"
valueKey="id"
value={field.value}
onChange={field.onChange}
isLoading={activitiesLoading}
className="m-0"
/>
)}
/>
{errors.activityID && (
<small className="danger-text">{errors.activityID.message}</small>
)}
</div>
)}
{watchActivityId && (
<div className="col-12 text-start">
<AppFormController
name="workCategoryId"
control={control}
render={({ field }) => (
<SelectField
label="Select Work Category"
options={categoryData ?? []}
placeholder="Select Work Category"
required
labelKey="name"
valueKey="id"
value={field.value}
onChange={field.onChange}
className="m-0"
/>
)}
/>
{errors.workCategoryId && (
<small className="danger-text">{errors.workCategoryId.message}</small>
)}
</div>
)}
{selectedActivity && selectedCategory && (
<>
<div className="col-5 text-start">
<Label className="form-label" required>Planned Work</Label>
<input
type="number"
className="form-control "
{...register("plannedWork", { valueAsNumber: true })}
/>
{errors.plannedWork && (
<p className="danger-text">{errors.plannedWork.message}</p>
)}
</div>
<div className="col-5 text-start">
<label className="form-label">Completed Work</label>
<input
type="number"
className="form-control "
{...register("completedWork", { valueAsNumber: true })}
/>
{errors.completedWork && (
<p className="danger-text">{errors.completedWork.message}</p>
)}
</div>
<div className="col-2 text-start">
<label className="form-label">Unit</label>
<input
type="text"
className="form-control "
disabled
value={selectedActivity?.unitOfMeasurement || ""}
/>
</div>
</>
)}
{selectedActivity && selectedCategory && (
<div className="col-12 text-start">
<label className="form-label">Comment</label>
<textarea
className="form-control"
rows="2"
{...register("comment")}
/>
{errors.comment && (
<p className="danger-text">{errors.comment.message}</p>
)}
</div>
)}
<div className="col-12 text-end mt-6 my-2">
<button
type="button"
className="btn btn-sm btn-label-secondary me-3"
onClick={onClose}
>
Cancel
</button>
<button
type="submit"
className="btn btn-sm btn-primary"
// disabled={isSubmitting}
disabled={isPending}
>
{isPending ? "Please Wait..." : "Add Task"}
</button>
</div>
</form>
</AppFormProvider>
); );
}; };

View File

@ -6,6 +6,8 @@ import showToast from "../../../services/toastService";
import { useManageProjectInfra } from "../../../hooks/useProjects"; import { useManageProjectInfra } from "../../../hooks/useProjects";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import Label from "../../common/Label"; import Label from "../../common/Label";
import { AppFormController, AppFormProvider } from "../../../hooks/appHooks/useAppForm";
import SelectField from "../../common/Forms/SelectField";
const workAreaSchema = z.object({ const workAreaSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -26,19 +28,14 @@ const defaultModel = {
const WorkAreaModel = ({ project, onSubmit, onClose }) => { const WorkAreaModel = ({ project, onSubmit, onClose }) => {
const [selectedBuilding, setSelectedBuilding] = useState(null); const [selectedBuilding, setSelectedBuilding] = useState(null);
const [selectedFloor, setSelectedFloor] = useState(null); const [selectedFloor, setSelectedFloor] = useState(null);
const selectedProject = useSelector((store) => store.localVariables.projectId) const selectedProject = useSelector((store) => store.localVariables.projectId);
const { const methods = useForm({
register,
handleSubmit,
formState: { errors },
setValue,
reset,
watch,
} = useForm({
resolver: zodResolver(workAreaSchema),
defaultValues: defaultModel, defaultValues: defaultModel,
resolver: zodResolver(workAreaSchema),
}); });
const { register, control, watch, handleSubmit, reset, setValue, formState: { errors } } = methods;
const watchBuildingId = watch("buildingId"); const watchBuildingId = watch("buildingId");
const watchFloorId = watch("floorId"); const watchFloorId = watch("floorId");
const watchWorkAreaId = watch("id"); const watchWorkAreaId = watch("id");
@ -104,99 +101,122 @@ const WorkAreaModel = ({ project, onSubmit, onClose }) => {
}; };
return ( return (
<form className="row g-2 p-2 p-md-1" onSubmit={handleSubmit(onSubmitForm)}> <AppFormProvider {...methods}>
<div className="text-center mb-1"> <form className="row g-2 p-2 p-md-1" onSubmit={handleSubmit(onSubmitForm)}>
<h5 className="mb-1">Manage Work Area</h5> <div className="text-center mb-1">
</div> <h5 className="mb-1">Manage Work Area</h5>
<div className="col-12 col-sm-6 text-start"> </div>
<Label className="form-label" required>Select Building</Label>
<select
{...register("buildingId")}
className="form-select form-select-sm"
>
<option value="0">Select Building</option>
{project?.map((b) => (
<option key={b.id} value={b.id}>
{b.buildingName}
</option>
))}
</select>
{errors.buildingId && (
<p className="danger-text">{errors.buildingId.message}</p>
)}
</div>
{watchBuildingId !== "0" && (
<div className="col-12 col-sm-6 text-start"> <div className="col-12 col-sm-6 text-start">
<Label className="form-label" required>Select Floor</Label> <AppFormController
<select name="buildingId"
{...register("floorId")} control={control}
className="form-select form-select-sm" render={({ field }) => (
> <SelectField
<option value="0"> label="Select Building"
{selectedBuilding?.floor?.length > 0 options={project ?? []}
? "NO Floor Found" placeholder="Select Building"
: "Select Floor"} required
</option> labelKey="buildingName"
valueKey="id"
value={field.value}
onChange={field.onChange}
className="m-0"
/>
)}
/>
{selectedBuilding?.floors?.map((f) => ( {errors.buildingId && (
<option key={f.id} value={f.id}> <small className="danger-text">{errors.buildingId.message}</small>
{f.floorName}
</option>
))}
</select>
{errors.floorId && (
<p className="danger-text">{errors.floorId.message}</p>
)} )}
</div> </div>
)}
{watchFloorId !== "0" && (
<>
<div className="col-12 text-start">
<label className="form-label">Select Work Area</label>
<select
{...register("id")}
className="form-select form-select-sm"
onChange={handleWrokAreaChange}
>
<option value="0">Create New Work Area</option>
{selectedFloor?.workAreas?.length > 0 &&
selectedFloor?.workAreas?.map((w) => (
<option key={w.id} value={w.id}>
{w.areaName}
</option>
))}
</select>
</div>
<div className="col-12 text-start">
<Label className="form-label" required> {watchBuildingId !== "0" && (
{watchWorkAreaId === "0" <div className="col-12 col-sm-6 text-start">
? "Enter Work Area Name" <AppFormController
: "Edit Work Area Name"} name="floorId"
</Label> control={control}
<input render={({ field }) => (
type="text" <SelectField
className="form-control form-control-sm" label="Select Floor"
placeholder="Work Area" options={selectedBuilding?.floors ?? []}
{...register("areaName")} placeholder={
selectedBuilding?.floors?.length > 0
? "Select Floor"
: "No Floor Found"
}
required
labelKey="floorName"
valueKey="id"
value={field.value}
onChange={(value) => {
field.onChange(value);
setValue("areaName", ""); // reset Work Area name when floor changes
}}
className="m-0"
/>
)}
/> />
{errors.areaName && ( {errors.floorId && (
<p className="danger-text">{errors.areaName.message}</p> <small className="danger-text">{errors.floorId.message}</small>
)} )}
</div> </div>
</> )}
)}
<div className="col-12 text-end mt-6 my-2">
<button type="button" className="btn btn-sm btn-label-secondary me-3" disabled={isPending} onClick={onClose}>
Cancel
</button>
<button type="submit" className="btn btn-sm btn-primary" disabled={isPending}>
{isPending ? "Please Wait.." : watchWorkAreaId === "0" ? "Add Work Area" : "Update Work Area"}
</button>
</div> {watchFloorId !== "0" && (
</form> <>
<div className="col-12 text-start">
<AppFormController
name="id"
control={control}
render={({ field }) => (
<SelectField
label="Select Work Area"
options={selectedFloor?.workAreas ?? []}
placeholder="Create New Work Area"
required={false}
labelKey="areaName"
valueKey="id"
value={field.value}
onChange={(value) => {
field.onChange(value);
handleWrokAreaChange({ target: { value } }); // preserve your existing handler
}}
className="m-0"
/>
)}
/>
</div>
<div className="col-12 text-start">
<Label className="form-label" required>
{watchWorkAreaId === "0"
? "Enter Work Area Name"
: "Edit Work Area Name"}
</Label>
<input
type="text"
className="form-control"
placeholder="Work Area"
{...register("areaName")}
/>
{errors.areaName && (
<p className="danger-text">{errors.areaName.message}</p>
)}
</div>
</>
)}
<div className="col-12 text-end mt-6 my-2">
<button type="button" className="btn btn-sm btn-label-secondary me-3" disabled={isPending} onClick={onClose}>
Cancel
</button>
<button type="submit" className="btn btn-sm btn-primary" disabled={isPending}>
{isPending ? "Please Wait.." : watchWorkAreaId === "0" ? "Add Work Area" : "Update Work Area"}
</button>
</div>
</form>
</AppFormProvider>
); );
}; };

View File

@ -30,6 +30,9 @@ import { useParams } from "react-router-dom";
import GlobalModel from "../common/GlobalModel"; import GlobalModel from "../common/GlobalModel";
import { setService } from "../../slices/globalVariablesSlice"; import { setService } from "../../slices/globalVariablesSlice";
import { SpinnerLoader } from "../common/Loader"; import { SpinnerLoader } from "../common/Loader";
import { useForm } from "react-hook-form";
import { AppFormController } from "../../hooks/appHooks/useAppForm";
import SelectField from "../common/Forms/SelectField";
const ProjectInfra = ({ data, onDataChange, eachSiteEngineer }) => { const ProjectInfra = ({ data, onDataChange, eachSiteEngineer }) => {
const projectId = useSelectedProject(); const projectId = useSelectedProject();
@ -52,6 +55,12 @@ const ProjectInfra = ({ data, onDataChange, eachSiteEngineer }) => {
const { data: assignedServices, isLoading: servicesLoading } = const { data: assignedServices, isLoading: servicesLoading } =
useProjectAssignedServices(projectId); useProjectAssignedServices(projectId);
const { control } = useForm({
defaultValues: {
serviceId: selectedService || "",
},
});
useEffect(() => { useEffect(() => {
setProject(projectInfra); setProject(projectInfra);
}, [data, projects_Details]); }, [data, projects_Details]);
@ -60,6 +69,11 @@ const ProjectInfra = ({ data, onDataChange, eachSiteEngineer }) => {
setProject(response); setProject(response);
}; };
const handleServiceChange = (serviceId) => {
dispatch(setService(serviceId));
};
return ( return (
<> <>
{showModalBuilding && ( {showModalBuilding && (
@ -115,37 +129,39 @@ const ProjectInfra = ({ data, onDataChange, eachSiteEngineer }) => {
<div className="card-body" style={{ padding: "0.5rem" }}> <div className="card-body" style={{ padding: "0.5rem" }}>
<div className="align-items-center"> <div className="align-items-center">
<div className="row "> <div className="row ">
<div <div className="col-md-4 col-12 dataTables_length text-start py-2 px-2">
className="dataTables_length text-start py-2 px-6 col-md-4 col-12" <div className="ms-4 mt-n1">
id="DataTables_Table_0_length" {!servicesLoading && assignedServices?.length > 0 && (
> assignedServices.length > 1 ? (
{!servicesLoading && <AppFormController
assignedServices?.length > 0 && name="serviceId"
(assignedServices.length > 1 ? ( control={control}
<label> render={({ field }) => (
<select <SelectField
name="DataTables_Table_0_length" label="Select Service"
aria-controls="DataTables_Table_0" options={[{ id: "", name: "All Projects" }, ...(assignedServices ?? [])]}
className="form-select form-select-sm" placeholder="Choose a Service"
aria-label="Select Service" required
value={selectedService} labelKey="name"
onChange={(e) => dispatch(setService(e.target.value))} valueKey="id"
> value={field.value}
<option value="">All Services</option> onChange={(val) => {
{assignedServices.map((service) => ( field.onChange(val);
<option key={service.id} value={service.id}> handleServiceChange(val);
{service.name} }}
</option> isLoading={servicesLoading}
))} />
</select> )}
</label> />
) : ( ) : (
<h5>{assignedServices[0].name}</h5> <h5>{assignedServices[0].name}</h5>
))} )
)}
</div>
</div> </div>
{/* Buttons Section (aligned to right) */} {/* Buttons Section (aligned to right) */}
<div className="col-md-8 col-12 text-end mb-1"> <div className="col-md-8 col-12 text-end mt-4">
{ManageInfra && ( {ManageInfra && (
<> <>
<button <button