373 lines
12 KiB
JavaScript

import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import {
useActivitiesByGroups,
useActivitiesMaster,
useGroups,
useWorkCategoriesMaster,
} from "../../../hooks/masterHook/useMaster";
import { useManageTask, useProjectAssignedOrganizations, useProjectAssignedServices } from "../../../hooks/useProjects";
import showToast from "../../../services/toastService";
import Label from "../../common/Label";
import { useSelectedProject } from "../../../slices/apiDataManager";
const taskSchema = z.object({
buildingID: z.string().min(1, "Building is required"),
floorId: z.string().min(1, "Floor is required"),
workAreaId: z.string().min(1, "Work Area is required"),
serviceId: z.string().min(1, "Service is required"),
activityGroupId: z.string().min(1, "Activity Group is required"),
activityID: z.string().min(1, "Activity is required"),
workCategoryId: z.string().min(1, "Work Category is required"),
plannedWork: z.number().min(1, "Planned Work must be greater than 0"),
completedWork: z.number().min(0, "Completed Work must be 0 or more"),
comment: z.string(),
});
const defaultModel = {
id: null,
buildingID: "",
floorId: "",
workAreaId: "",
serviceId: "",
activityGroupId: "",
activityID: "",
workCategoryId: "",
plannedWork: 0,
completedWork: 0,
comment: "",
};
const TaskModel = ({ project, onSubmit, onClose }) => {
// const { activities, loading: activityLoading } = useActivitiesMaster();
const { categories, categoryLoading } = useWorkCategoriesMaster();
const projectId = useSelectedProject();
const { data: assignedServices, isLoading: servicesLoading } = useProjectAssignedServices(projectId);
const { data: assignedOrganizations, isLoading: orgLoading } = useProjectAssignedOrganizations(projectId);
const [selectedService, setSelectedService] = useState("");
const [selectedGroup, setSelectedGroup] = useState("");
const { data: groupsResponse, isLoading: groupsLoading } = useGroups(selectedService);
const groups = groupsResponse?.data ?? [];
const { data: activitiesResponse, isLoading: activitiesLoading } = useActivitiesByGroups(selectedGroup);
const activities = activitiesResponse?.data ?? [];
// Fetch Assigned Organizations (Activity Groups)
const [selectedOrg, setSelectedOrg] = useState("");
const handleServiceChange = (e) => {
const value = e.target.value;
setSelectedService(value);
setSelectedGroup("");
setValue("activityGroupId", "");
setValue("activityID", "");
};
const handleGroupChange = (e) => {
const value = e.target.value;
setSelectedGroup(value);
setValue("activityGroupId", value);
setValue("activityID", "");
};
const {
register,
handleSubmit,
watch,
setValue,
reset,
formState: { errors },
} = useForm({
resolver: zodResolver(taskSchema),
defaultValues: defaultModel,
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [activityData, setActivityData] = useState([]);
const [categoryData, setCategoryData] = useState([]);
const watchBuildingId = watch("buildingID");
const watchFloorId = watch("floorId");
const watchWorkAreaId = watch("workAreaId");
const watchActivityId = watch("activityID");
const watchCategoryId = watch("workCategoryId");
const selectedBuilding = project?.find((b) => b.id === watchBuildingId);
const selectedFloor = selectedBuilding?.floors?.find(
(f) => f.id === watchFloorId
);
const selectedWorkArea = selectedFloor?.workAreas?.find(
(w) => w.id === watchWorkAreaId
);
const selectedActivity = activityData?.find((a) => a.id === watchActivityId);
const selectedCategory = categoryData?.find((c) => c.id === watchCategoryId);
const { mutate: CreateTask, isPending } = useManageTask({
onSuccessCallback: (response) => {
showToast(response?.message, "success");
setValue("activityID",""),
setValue("plannedWork",0),
setValue("completedWork",0)
setValue("comment","")
},
});
useEffect(() => {
reset(defaultModel);
}, []);
useEffect(() => {
if (Array.isArray(activities) && activities.length > 0) {
setActivityData(activities);
}
}, [activities]);
useEffect(() => {
if (Array.isArray(categories) && categories.length > 0) {
const sorted = [...categories].sort((a, b) =>
(a?.name || "").localeCompare(b?.name || "")
);
setCategoryData(sorted);
setValue("workCategoryId", sorted?.[0]?.id?.toString() ?? "");
}
}, [categories]);
const onSubmitForm = async (data) => {
const payload = [data];
CreateTask({
payload: payload, buildingId: data.buildingID,
floorId: data.floorId,
workAreaId: data.workAreaId, PreviousPlannedWork: 0, previousCompletedWork: 0
});
};
return (
<form className="row g-2" onSubmit={handleSubmit(onSubmitForm)}>
<div className="text-center mb-1">
<h5 className="mb-1">Manage Task</h5>
</div>
<div className="col-6 text-start">
<Label className="form-label" required>Select Building</Label>
<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">
<Label className="form-label" required>Select Floor</Label>
<select
className="form-select form-select-sm"
{...register("floorId")}
>
<option value="">Select Floor</option>
{selectedBuilding.floors
?.sort((a, b) => a.floorName.localeCompare(b.floorName))
?.map((f) => (
<option key={f.id} value={f.id}>
{f.floorName}
</option>
))}
</select>
{errors.floorId && (
<p className="danger-text">{errors.floorId.message}</p>
)}
</div>
)}
{/* 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 && (
<p className="danger-text">{errors.comment.message}</p>
)}
</div>
)}
<div className="col-12 text-end mt-5">
<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>
);
};
export default TaskModel;