363 lines
12 KiB
JavaScript

import React, { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import {useActivitiesMaster} from "../../../hooks/masterHook/useMaster";
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"),
activityID: z.string().min(1, "Activity is required"),
plannedWork: z.number().min(1, "Planned Work must be greater than 0"),
completedWork: z.number().min(0, "Completed Work must be greater than 0"),
});
const defaultModel = {
id: null,
buildingID:"0",
floorId: "0",
workAreaId: "0",
activityID: null,
plannedWork: 0,
completedWork: 0,
};
const TaskModel = ({
project,
onSubmit,
clearTrigger,
onClearComplete,
onClose,
}) => {
const [formData, setFormData] = useState(defaultModel);
const [selectedBuilding, setSelectedBuilding] = useState(null);
const [selectedFloor, setSelectedFloor] = useState(null);
const [selectedWorkArea, setSelectedWorkArea] = useState(null);
const [selectedActivity, setSelectedActivity] = useState(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const [activityData, setActivityData] = useState([]);
const {activities, loading, error} = useActivitiesMaster();
const {
register,
handleSubmit,
formState: { errors },
reset,
setValue,
} = useForm({
resolver: zodResolver(taskSchema),
defaultValues: defaultModel,
});
useEffect(() => {
resetForm();
}, []);
const handleBuildingChange = (e) => {
const { value } = e.target;
const building = project.buildings.find((b) => b.id === String(value));
setSelectedBuilding(building);
setSelectedFloor(null);
setSelectedWorkArea(null);
setSelectedActivity(null);
reset({
...defaultModel,
buildingID: value,
});
};
const handleFloorChange = (e) => {
const { value } = e.target;
const floor = selectedBuilding.floors.find((b) => b.id === String(value));
setSelectedFloor(floor);
setSelectedWorkArea(null);
setSelectedActivity(null);
reset((prev) => ({
...prev,
floorId: value,
workAreaId: 0,
activityID: 0,
}));
};
const handleWorkAreaChange = (e) => {
const { value } = e.target;
const workArea = selectedFloor.workAreas.find(
(b) => b.id === String(value)
);
setSelectedWorkArea(workArea);
reset((prev) => ({
...prev,
workAreaId: String(value),
}));
};
const handleActivityChange = (e) => {
const { value } = e.target;
const activity = activityData.find((b) => b.id === String(value));
setSelectedActivity(activity);
reset((prev) => ({
...prev,
activityID: String(value),
}));
};
const onSubmitForm = async ( data ) =>
{
setIsSubmitting(true);
await onSubmit(data);
setValue("plannedWork", 0);
setValue( "completedWork", 0 );
setIsSubmitting(false);
};
const resetForm = () => {
setFormData(defaultModel);
setSelectedBuilding(null); // not "0"
setSelectedFloor(null);
setSelectedWorkArea(null);
setSelectedActivity(null);
reset(defaultModel);
};
useEffect(() => {
if (!loading && Array.isArray(activities) && activities.length > 0) {
setActivityData(activities);
}
}, [activities, loading]);
return (
<div className="modal-dialog modal-lg modal-simple modal-edit-user">
<div className="modal-content">
<div className="modal-body">
<div className="row">
<button
type="button"
className="btn-close"
aria-label="Close"
onClick={onClose}
/>
<div className="text-center mb-1">
<h5 className="mb-1">Manage Task</h5>
</div>
<form className="row g-2" onSubmit={handleSubmit(onSubmitForm)}>
{/* Select Building */}
<div className="col-6 col-md-6">
<label className="form-label" htmlFor="buildingID">
Select Building
</label>
<select
id="buildingID"
className="form-select form-select-sm"
{...register("buildingID")}
onChange={handleBuildingChange}
>
<option value="0">Select Building</option>
{project.buildings
?.filter((building) => building?.name) // Ensure valid name
?.sort((a, b) => a.name?.localeCompare(b.name))
?.map((building) => (
<option key={building.id} value={building.id}>
{building.name}
</option>
))}
{project.buildings?.filter((building) => building?.name)
.length === 0 && (
<option disabled>No buildings found</option>
)}
</select>
{errors.buildingID && (
<p className="danger-text">{errors.buildingID.message}</p>
)}
</div>
{/* Select Floor */}
{selectedBuilding && (
<div className="col-6 col-md-6">
<label className="form-label" htmlFor="floorId">
Select Floor
</label>
<select
id="floorId"
className="form-select form-select-sm"
{...register("floorId")}
onChange={handleFloorChange}
>
<option value="0">Select Floor</option>
{selectedBuilding.floors
?.filter(
(floor) =>
floor?.floorName && Array.isArray(floor.workAreas)
)
?.sort((a, b) => a.floorName.localeCompare(b.floorName))
?.map((floor) => (
<option key={floor.id} value={floor.id}>
{floor.floorName} - ({floor.workAreas.length} Work
Areas)
</option>
))}
{selectedBuilding.floors?.filter(
(floor) =>
floor?.floorName && Array.isArray(floor.workAreas)
).length === 0 && <option disabled>No floors found</option>}
</select>
{errors.floorId && (
<p className="danger-text">{errors.floorId.message}</p>
)}
</div>
)}
{selectedFloor && (
<div className="col-12 col-md-12">
<label className="form-label" htmlFor="workAreaId">
Select Work Area
</label>
<select
id="workAreaId"
className="form-select form-select-sm"
{...register("workAreaId")}
onChange={handleWorkAreaChange}
>
<option value="0">Select Work Area</option>
{selectedFloor.workAreas
?.filter((workArea) => workArea?.areaName)
?.sort((a, b) => a.areaName.localeCompare(b.areaName))
?.map((workArea) => (
<option key={workArea.id} value={workArea.id}>
{workArea.areaName}
</option>
))}
{selectedFloor.workAreas?.filter(
(workArea) => workArea?.areaName
).length === 0 && (
<option disabled>No work areas found</option>
)}
</select>
{errors.workAreaId && (
<p className="danger-text">{errors.workAreaId.message}</p>
)}
</div>
)}
{selectedWorkArea && (
<div className="col-12 col-md-12">
<label className="form-label" htmlFor="activityID">
Select Activity
</label>
<select
id="activityID"
className="form-select form-select-sm"
{...register("activityID")}
onChange={handleActivityChange}
>
<option value="0">Select Activity</option>
{activityData && activityData.length > 0 && (
activityData
?.slice()
?.sort( ( a, b ) =>
{
const nameA = a?.activityName || "";
const nameB = b?.activityName || "";
return nameA.localeCompare( nameB );
} )
?.map( ( activity ) => (
<option key={activity.id} value={activity.id}>
{
activity.activityName ||
`Unnamed (id: ${ activity.id })`}
</option>
) )
) }
{(!loading && activities.length === 0 )&& (
<option disabled>No activities available</option>
)}
{loading && ( <option disabled>Loading...</option>)}
</select>
{errors.activityID && (
<p className="danger-text">{errors.activityID.message}</p>
)}
</div>
)}
{selectedActivity && (
<div className="col-5 col-md-5">
<label className="form-label" htmlFor="plannedWork">
{formData.id !== "0" ? "Modify " : "Enter "} Planned Work
</label>
<input
{...register("plannedWork", { valueAsNumber: true })}
type="number"
className="form-control form-control-sm me-2"
placeholder="Planned Work"
/>
{errors.plannedWork && (
<p className="danger-text">{errors.plannedWork.message}</p>
)}
</div>
)}
{selectedActivity && (
<div className="col-5 col-md-5">
<label className="form-label" htmlFor="completedWork">
{formData.id !== "0" ? "Modify " : "Enter "} Completed Work
</label>
<input
{...register("completedWork", { valueAsNumber: true })}
type="number"
className="form-control form-control-sm me-2"
placeholder="Completed Work"
/>
{errors.completedWork && (
<p className="danger-text">
{errors.completedWork.message}
</p>
)}
</div>
)}
{/* Unit */}
{selectedActivity && (
<div className="col-2 col-md-2">
<label className="form-label" htmlFor="unit">
Unit
</label>
<input
type="text"
disabled
className="form-control form-control-sm me-2"
value={selectedActivity?.unitOfMeasurement || ""}
/>
</div>
)}
<div className="col-12 text-center">
<button type="submit" className="btn btn-sm btn-primary me-3">
{isSubmitting
? "Please Wait.."
: "Add Task"}
</button>
<button
type="button"
className="btn btn-sm btn-label-secondary"
onClick={onClose}
>
Cancel
</button>
</div>
</form>
</div>
</div>
</div>
</div>
);
};
export default TaskModel;