integrated reactquery for project infra
This commit is contained in:
parent
2f110b7ead
commit
52c5e3d2d2
@ -47,7 +47,7 @@ const BuildingModel = ({ project, onClose, editingBuilding = null }) => {
|
||||
"success"
|
||||
);
|
||||
reset({ Id: "0", name: "", description: "" });
|
||||
onClose?.();
|
||||
// onClose?.();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -14,7 +14,6 @@ const floorSchema = z.object({
|
||||
id: z.string().optional(),
|
||||
floorName: z.string().min(1, "Floor Name is required"),
|
||||
});
|
||||
|
||||
const defaultValues = {
|
||||
id: "0",
|
||||
floorName: "",
|
||||
@ -49,7 +48,7 @@ const FloorModel = ({ project, onClose, onSubmit }) => {
|
||||
"success"
|
||||
);
|
||||
reset({ Id: "0", name: "", description: "" });
|
||||
onClose?.();
|
||||
// onClose?.();
|
||||
},
|
||||
});
|
||||
|
||||
@ -121,7 +120,7 @@ const FloorModel = ({ project, onClose, onSubmit }) => {
|
||||
))}
|
||||
</select>
|
||||
{errors.buildingId && (
|
||||
<p className="text-danger">{errors.buildingId.message}</p>
|
||||
<p className="danger-text">{errors.buildingId.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -157,7 +156,7 @@ const FloorModel = ({ project, onClose, onSubmit }) => {
|
||||
placeholder="Floor Name"
|
||||
/>
|
||||
{errors.floorName && (
|
||||
<p className="text-danger">{errors.floorName.message}</p>
|
||||
<p className="danger-text">{errors.floorName.message}</p>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import {
|
||||
useActivitiesMaster,
|
||||
useWorkCategoriesMaster,
|
||||
} from "../../../hooks/masterHook/useMaster";
|
||||
import { useManageTask } from "../../../hooks/useProjects";
|
||||
|
||||
const taskSchema = z.object({
|
||||
buildingID: z.string().min(1, "Building is required"),
|
||||
@ -14,432 +15,263 @@ const taskSchema = z.object({
|
||||
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 greater than 0" ),
|
||||
comment:z.string(),
|
||||
completedWork: z.number().min(0, "Completed Work must be 0 or more"),
|
||||
comment: z.string(),
|
||||
});
|
||||
|
||||
const defaultModel = {
|
||||
id: null,
|
||||
buildingID: "", // Changed from "0"
|
||||
floorId: "", // Changed from "0"
|
||||
workAreaId: "", // Changed from "0"
|
||||
activityID: "", // Changed from null
|
||||
workCategoryId: "", // Kept as empty
|
||||
buildingID: "",
|
||||
floorId: "",
|
||||
workAreaId: "",
|
||||
activityID: "",
|
||||
workCategoryId: "",
|
||||
plannedWork: 0,
|
||||
completedWork: 0,
|
||||
comment: ""
|
||||
comment: "",
|
||||
};
|
||||
|
||||
const TaskModel = ({ project, onSubmit, onClose }) => {
|
||||
const { activities, loading: activityLoading } = useActivitiesMaster();
|
||||
const { categories, categoryLoading } = useWorkCategoriesMaster();
|
||||
|
||||
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 [selectedCategory, setSelectedCategory] = useState(null);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [activityData, setActivityData] = useState([]);
|
||||
const [categoryData, setCategoryData] = useState([]);
|
||||
const { activities, loading, error } = useActivitiesMaster();
|
||||
const { categories, categoryLoading, categoryError } =
|
||||
useWorkCategoriesMaster();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
reset,
|
||||
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: () => onClose?.(),
|
||||
});
|
||||
useEffect(() => {
|
||||
resetForm();
|
||||
reset(defaultModel);
|
||||
}, []);
|
||||
|
||||
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: "",
|
||||
activityID: "",
|
||||
workCategoryId: categoryData?.[0]?.id?.toString() ?? "",
|
||||
}));
|
||||
};
|
||||
|
||||
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 handleCategoryChange = (e) => {
|
||||
const { value } = e.target;
|
||||
const category = categoryData.find((b) => b.id === String(value));
|
||||
setSelectedCategory(category);
|
||||
reset((prev) => ({
|
||||
...prev,
|
||||
workCategoryId: String(value),
|
||||
}));
|
||||
};
|
||||
|
||||
const onSubmitForm = async (data) => {
|
||||
|
||||
setIsSubmitting(true);
|
||||
await onSubmit(data);
|
||||
setValue("plannedWork", 0);
|
||||
setValue("completedWork", 0);
|
||||
setValue("activityID", 0);
|
||||
setValue("workCategoryId", categoryData?.[0]?.id?.toString() ?? "");
|
||||
setIsSubmitting(false);
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
setFormData(defaultModel);
|
||||
setSelectedBuilding(null);
|
||||
setSelectedFloor(null);
|
||||
setSelectedWorkArea(null);
|
||||
setSelectedActivity(null);
|
||||
setSelectedCategory(categoryData?.[0]?.id?.toString() ?? "");
|
||||
reset(defaultModel);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && Array.isArray(activities) && activities.length > 0) {
|
||||
if (Array.isArray(activities) && activities.length > 0) {
|
||||
setActivityData(activities);
|
||||
}
|
||||
}, [activities, loading]);
|
||||
}, [activities]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!categoryLoading &&
|
||||
Array.isArray(categories) &&
|
||||
categories.length > 0
|
||||
) {
|
||||
const newCategories = categories?.slice()?.sort((a, b) => {
|
||||
const nameA = a?.name || "";
|
||||
const nameB = b?.name || "";
|
||||
return nameA?.localeCompare(nameB);
|
||||
});
|
||||
setCategoryData(newCategories);
|
||||
setSelectedCategory(newCategories[0])
|
||||
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, categoryLoading]);
|
||||
}, [categories]);
|
||||
|
||||
const onSubmitForm = async (data) => {
|
||||
const payload = [data];
|
||||
CreateTask(payload);
|
||||
};
|
||||
|
||||
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="">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="">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="">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">Select Activity</label>
|
||||
<select
|
||||
id="activityID"
|
||||
className="form-select form-select-sm"
|
||||
{...register("activityID")}
|
||||
onChange={handleActivityChange}
|
||||
>
|
||||
<option value="">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>
|
||||
)}
|
||||
|
||||
{selectedWorkArea && (
|
||||
<div className="col-12 col-md-12">
|
||||
<label className="form-label">Select Work Category</label>
|
||||
<select
|
||||
id="workCategoryId"
|
||||
className="form-select form-select-sm"
|
||||
{...register("workCategoryId")}
|
||||
onChange={handleCategoryChange}
|
||||
>
|
||||
{categoryData &&
|
||||
categoryData.length > 0 &&
|
||||
categoryData
|
||||
?.map((category) => (
|
||||
<option key={category.id} value={category.id}>
|
||||
{category.name || `Unnamed (id: ${category.id})`}
|
||||
</option>
|
||||
))}
|
||||
{!categoryLoading && categories.length === 0 && (
|
||||
<option disabled>No activities available</option>
|
||||
)}
|
||||
{categoryLoading && <option disabled>Loading...</option>}
|
||||
</select>
|
||||
|
||||
{errors.workCategoryId && (
|
||||
<p className="danger-text">
|
||||
{errors.workCategoryId.message}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selectedActivity && selectedCategory && (
|
||||
<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 && selectedCategory && (
|
||||
<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>
|
||||
)}
|
||||
|
||||
{selectedActivity && selectedCategory && (
|
||||
<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>
|
||||
)}
|
||||
{selectedActivity && selectedCategory && (
|
||||
<div className="col-12">
|
||||
<label
|
||||
className="form-text fs-7 m-1 text-lg text-dark"
|
||||
htmlFor="descriptionTextarea"
|
||||
>
|
||||
Comment
|
||||
</label>
|
||||
<textarea
|
||||
{...register("comment")}
|
||||
className="form-control"
|
||||
id="descriptionTextarea"
|
||||
rows="2"
|
||||
/>
|
||||
{errors.comment && (
|
||||
<div className="danger-text">
|
||||
{errors.comment.message}
|
||||
</div>
|
||||
)}
|
||||
</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>
|
||||
<form className="row g-2" onSubmit={handleSubmit(onSubmitForm)}>
|
||||
<div className="text-center mb-1">
|
||||
<h5 className="mb-1">Manage Task</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-6">
|
||||
<label className="form-label">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">
|
||||
<label className="form-label">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>
|
||||
)}
|
||||
|
||||
{selectedFloor && (
|
||||
<div className="col-12">
|
||||
<label className="form-label">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>
|
||||
)}
|
||||
|
||||
{selectedWorkArea && (
|
||||
<div className="col-12">
|
||||
<label className="form-label">Select Activity</label>
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
{...register("activityID")}
|
||||
>
|
||||
<option value="">Select Activity</option>
|
||||
{activityData.map((a) => (
|
||||
<option key={a.id} value={a.id}>
|
||||
{a.activityName}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.activityID && (
|
||||
<p className="danger-text">{errors.activityID.message}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selectedWorkArea && (
|
||||
<div className="col-12">
|
||||
<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">
|
||||
<label className="form-label">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">
|
||||
<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">
|
||||
<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">
|
||||
<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-center">
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-sm btn-primary me-3"
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
{isSubmitting ? "Please Wait..." : "Add Task"}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-sm btn-label-secondary"
|
||||
onClick={onClose}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default TaskModel;
|
||||
export default TaskModel;
|
||||
|
@ -1,39 +1,29 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { set, useForm } from "react-hook-form";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
import showToast from "../../../services/toastService";
|
||||
import { useManageProjectInfra } from "../../../hooks/useProjects";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
// Zod schema for form validation
|
||||
const workAreaSchema = z.object({
|
||||
id: z.string().nonempty("Floor is required"),
|
||||
|
||||
buildingId: z.string().nonempty("Building is required"),
|
||||
floorId: z.string().nonempty("Floor is required"),
|
||||
areaName: z
|
||||
.string()
|
||||
.nonempty("Work Area Name is required")
|
||||
.min(3, "Name must be at least 3 characters long"),
|
||||
id: z.string().optional(),
|
||||
buildingId: z.string().min(1, "Building is required"),
|
||||
floorId: z.string().min(1, "Floor is required"),
|
||||
areaName: z.string().min(3, "Work Area Name must be at least 3 characters"),
|
||||
});
|
||||
|
||||
// Default form data
|
||||
const defaultModel = {
|
||||
id: "0",
|
||||
areaName: "",
|
||||
buildingId: "0",
|
||||
floorId: "0",
|
||||
areaName: "",
|
||||
};
|
||||
|
||||
const WorkAreaModel = ({
|
||||
project,
|
||||
onSubmit,
|
||||
clearTrigger,
|
||||
onClearComplete,
|
||||
onClose,
|
||||
}) => {
|
||||
const WorkAreaModel = ({ project, onSubmit, onClose }) => {
|
||||
const [selectedBuilding, setSelectedBuilding] = useState(null);
|
||||
const [selectedFloor, setSelectedFloor] = useState(null);
|
||||
const [selectdWorkArea, setWorkArea] = useState();
|
||||
|
||||
const selectedProject = useSelector((store)=>store.localVariables.projectId)
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
@ -42,259 +32,169 @@ const WorkAreaModel = ({
|
||||
reset,
|
||||
watch,
|
||||
} = useForm({
|
||||
resolver: zodResolver(workAreaSchema), // Use Zod resolver for validation
|
||||
resolver: zodResolver(workAreaSchema),
|
||||
defaultValues: defaultModel,
|
||||
});
|
||||
|
||||
const floorId = watch("floorId"); // Watch the floorId for conditional rendering
|
||||
const watchBuildingId = watch("buildingId");
|
||||
const watchFloorId = watch("floorId");
|
||||
const watchWorkAreaId = watch("id");
|
||||
const { mutate: ManageWorkArea, isPending } = useManageProjectInfra({
|
||||
onSuccessCallback: (data, variables) => {
|
||||
showToast(
|
||||
watchWorkAreaId != "0"
|
||||
? "Wrok Area updated Successfully"
|
||||
: "Work Area created Successfully",
|
||||
"success"
|
||||
);
|
||||
reset({ id: "0", buildingId: "0", areaName: "", floorId: "0" });
|
||||
// onClose?.();
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (clearTrigger) {
|
||||
reset(defaultModel); // Reset form to initial state
|
||||
setSelectedBuilding(null);
|
||||
setSelectedFloor(null);
|
||||
onClearComplete();
|
||||
}
|
||||
}, [clearTrigger, onClearComplete, reset]);
|
||||
const building = project?.find((b) => b.id === watchBuildingId);
|
||||
setSelectedBuilding(building || null);
|
||||
|
||||
const handleWorkAreaChange = (e) => {
|
||||
const { value } = e.target;
|
||||
|
||||
if (value === "0") {
|
||||
setValue("id", "0"); // Create New Work Area
|
||||
if (building) {
|
||||
const floor = building.floors?.find((f) => f.id === watchFloorId);
|
||||
setSelectedFloor(floor || null);
|
||||
setValue("areaName", "");
|
||||
|
||||
setWorkArea(String(0));
|
||||
} else {
|
||||
const workArea = selectedFloor?.workAreas.find(
|
||||
(b) => b.id === String(value)
|
||||
);
|
||||
if (workArea) {
|
||||
setValue("id", String(workArea.id)); // Set id as a string
|
||||
setValue("areaName", workArea.areaName);
|
||||
setWorkArea(String(workArea.id));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleFloorChange = (e) => {
|
||||
const { value } = e.target;
|
||||
const floor = selectedBuilding?.floors.find((b) => b.id === String(value));
|
||||
|
||||
if (floor) {
|
||||
setSelectedFloor(floor);
|
||||
setValue("floorId", floor.id); // Update floorId
|
||||
setValue("id", "0"); // Reset Work Area ID for new area creation
|
||||
setValue("areaName", ""); // Reset Work Area Name when changing floor
|
||||
} else {
|
||||
setSelectedFloor(null);
|
||||
setValue("floorId", "0");
|
||||
setValue("id", "0"); // Reset Work Area ID
|
||||
setValue("areaName", ""); // Reset Work Area Name
|
||||
setValue("areaName", "");
|
||||
}
|
||||
}, [watchBuildingId, watchFloorId]);
|
||||
|
||||
const handleWrokAreaChange = (e) => {
|
||||
const workAreaId = e.target.value;
|
||||
setValue("id", workAreaId);
|
||||
const area = selectedFloor?.workAreas.find((w) => w.id === workAreaId);
|
||||
if (area) {
|
||||
setValue("areaName", area.areaName);
|
||||
} else {
|
||||
setValue("areaName", "");
|
||||
}
|
||||
};
|
||||
|
||||
const handleBuildingChange = (e) => {
|
||||
const { value } = e.target;
|
||||
const building = project?.buildings.find((b) => b.id === String(value));
|
||||
setSelectedBuilding(building);
|
||||
setSelectedFloor(null); // Reset selected floor on building change
|
||||
reset(defaultModel); // Reset the form when a new building is selected
|
||||
};
|
||||
useEffect(() => {
|
||||
reset(defaultModel);
|
||||
}, []);
|
||||
|
||||
const onSubmitForm = (data) => {
|
||||
let WorkArea = {
|
||||
id: data.id == "0" ? null : data.id,
|
||||
const onSubmitForm = ( data ) =>
|
||||
{
|
||||
const payload = {
|
||||
id: data.id === "0" ? null : data.id,
|
||||
areaName: data.areaName,
|
||||
floorId: data.floorId,
|
||||
buildingId: data.buildingId,
|
||||
};
|
||||
onSubmit(WorkArea);
|
||||
let infraObject = [
|
||||
{
|
||||
building: null,
|
||||
floor: null,
|
||||
workArea: payload,
|
||||
},
|
||||
];
|
||||
|
||||
reset({
|
||||
id: "0",
|
||||
areaName: "",
|
||||
});
|
||||
if (WorkArea.id !== null) {
|
||||
showToast("WorkArea updated successfully.", "success");
|
||||
} else {
|
||||
showToast("WorkArea created successfully.", "success");
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
reset(defaultModel);
|
||||
setSelectedFloor(null);
|
||||
setSelectedBuilding(null);
|
||||
onClose();
|
||||
ManageWorkArea({ infraObject, projectId: selectedProject });
|
||||
};
|
||||
|
||||
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 Work Area</h5>
|
||||
</div>
|
||||
<form className="row g-2" onSubmit={handleSubmit(onSubmitForm)}>
|
||||
{/* Building Selection */}
|
||||
<div className="col-6 col-md-6">
|
||||
<label className="form-label" htmlFor="buildingId">
|
||||
Select Building
|
||||
</label>
|
||||
<select
|
||||
id="buildingId"
|
||||
name="buildingId"
|
||||
className="select2 form-select form-select-sm"
|
||||
{...register("buildingId")}
|
||||
onChange={handleBuildingChange}
|
||||
>
|
||||
<option value="0">Select Building</option>
|
||||
{project?.buildings
|
||||
?.filter((building) => building?.name)
|
||||
?.sort((a, b) => {
|
||||
const nameA = a.name || "";
|
||||
const nameB = b.name || "";
|
||||
return nameA?.localeCompare(nameB);
|
||||
})
|
||||
?.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 && <span>{errors.buildingId.message}</span>}
|
||||
</div>
|
||||
|
||||
{/* Floor Selection */}
|
||||
{selectedBuilding && selectedBuilding.buildingId !== "0" && (
|
||||
<div className="col-6 col-md-6">
|
||||
<label className="form-label" htmlFor="floorId">
|
||||
Select Floor
|
||||
</label>
|
||||
<select
|
||||
id="floorId"
|
||||
name="floorId"
|
||||
className="select2 form-select form-select-sm"
|
||||
{...register("floorId")}
|
||||
onChange={handleFloorChange}
|
||||
>
|
||||
<option value="0">Select Floor</option>
|
||||
{selectedBuilding.floors
|
||||
?.filter((floor) => floor?.floorName)
|
||||
?.sort((a, b) => {
|
||||
const nameA = a.floorName || "";
|
||||
const nameB = b.floorName || "";
|
||||
return nameA?.localeCompare(nameB);
|
||||
})
|
||||
?.map((floor) => (
|
||||
<option key={floor.id} value={floor.id}>
|
||||
{floor.floorName}
|
||||
</option>
|
||||
))}
|
||||
|
||||
{selectedBuilding.floors?.filter(
|
||||
(floor) => floor?.floorName
|
||||
).length === 0 && <option disabled>No floors found</option>}
|
||||
</select>
|
||||
{errors.floorId && <span>{errors.floorId.message}</span>}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Work Area Selection or Creation */}
|
||||
{floorId !== "0" && (
|
||||
<>
|
||||
<div className="col-12 col-md-12">
|
||||
<label className="form-label">Select Work Area</label>
|
||||
<select
|
||||
id="workAreaId"
|
||||
name="workAreaId"
|
||||
className="select2 form-select form-select-sm"
|
||||
{...register("id")}
|
||||
onChange={handleWorkAreaChange}
|
||||
>
|
||||
<option value="0">Create New Work Area</option>
|
||||
{selectedFloor?.workAreas
|
||||
?.filter((workArea) => workArea?.areaName)
|
||||
?.sort((a, b) => {
|
||||
const nameA = a.areaName || "";
|
||||
const nameB = b.areaName || "";
|
||||
return nameA?.localeCompare(nameB);
|
||||
})
|
||||
?.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.id && <span>{errors.id.message}</span>}
|
||||
</div>
|
||||
|
||||
{/* Work Area Name Input */}
|
||||
<div className="col-12 col-md-12">
|
||||
<label className="form-label" htmlFor="areaName">
|
||||
{watch("id") === "0"
|
||||
? "Enter Work Area Name"
|
||||
: "Modify Work Area Name"}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="areaName"
|
||||
name="areaName"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Work Area"
|
||||
{...register("areaName")}
|
||||
/>
|
||||
{errors.areaName && (
|
||||
<span className="danger-text">
|
||||
{errors.areaName.message}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Submit and Cancel Buttons */}
|
||||
<div className="col-12 text-center">
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-sm btn-primary me-3"
|
||||
>
|
||||
{watch("id") === "0" ? "Add Work Area" : "Edit Work Area"}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-sm btn-label-secondary"
|
||||
onClick={handleCancel}
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<form className="row g-2 p-2 p-md-1" onSubmit={handleSubmit(onSubmitForm)}>
|
||||
<div className="text-center mb-1">
|
||||
<h5 className="mb-1">Manage Work Area</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-sm-6">
|
||||
<label className="form-label">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">
|
||||
<label className="form-label">Select Floor</label>
|
||||
<select
|
||||
{...register("floorId")}
|
||||
className="form-select form-select-sm"
|
||||
>
|
||||
<option value="0">
|
||||
{selectedBuilding?.floor?.length > 0
|
||||
? "NO Floor Found"
|
||||
: "Select Floor"}
|
||||
</option>
|
||||
|
||||
{selectedBuilding?.floors?.map((f) => (
|
||||
<option key={f.id} value={f.id}>
|
||||
{f.floorName}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.floorId && (
|
||||
<p className="danger-text">{errors.floorId.message}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{watchFloorId !== "0" && (
|
||||
<>
|
||||
<div className="col-12">
|
||||
<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">
|
||||
<label className="form-label">
|
||||
{watchWorkAreaId === "0"
|
||||
? "Enter Work Area Name"
|
||||
: "Edit Work Area Name"}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Work Area"
|
||||
{...register("areaName")}
|
||||
/>
|
||||
{errors.areaName && (
|
||||
<p className="danger-text">{errors.areaName.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-12 text-center">
|
||||
<button type="submit" className="btn btn-sm btn-primary me-3" disabled={isPending}>
|
||||
{isPending ? "Please Wait.." : watchWorkAreaId === "0" ? "Add Work Area" : "Update Work Area"}
|
||||
</button>
|
||||
<button type="button" className="btn btn-sm btn-label-secondary" disabled={isPending} onClick={onClose}>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,6 @@ import TaskModel from "./Infrastructure/TaskModel";
|
||||
import ProjectRepository, {
|
||||
TasksRepository,
|
||||
} from "../../repositories/ProjectRepository";
|
||||
import ProjectModal from "./ProjectModal";
|
||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||
import { MANAGE_PROJECT_INFRA } from "../../utils/constants";
|
||||
import InfraTable from "./Infrastructure/InfraTable";
|
||||
@ -32,17 +31,10 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
|
||||
const {projectInfra,isLoading,error} = useProjectInfra(projectId)
|
||||
const { projects_Details, refetch, loading } = useProjectDetails(data?.id);
|
||||
const [ project, setProject ] = useState( projects_Details );
|
||||
const [modalConfig, setModalConfig] = useState({ type: null, data: null });
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const ManageInfra = useHasUserPermission(MANAGE_PROJECT_INFRA);
|
||||
const [isBuildingModalOpen, setIsBuildingModalOpen] = useState(false);
|
||||
const [showModalFloor, setshowModalFloor] = useState(false);
|
||||
const [isWorkAreaModelOpen, setIsWorkAreaModalOpen] = useState(false);
|
||||
const [isTaskModelOpen, setIsTaskModalOpen] = useState(false);
|
||||
const [isAssignRoleModal, setIsAssingRoleModal] = useState(false);
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
const [clearFormTrigger, setClearFormTrigger] = useState(false);
|
||||
const [CurrentBuilding, setCurrentBuilding] = useState("");
|
||||
const [showModalWorkArea, setshowModalWorkArea] = useState(false);
|
||||
const [showModalTask, setshowModalTask] = useState(false);
|
||||
const [showModalBuilding, setshowModalBuilding] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
@ -50,266 +42,6 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
|
||||
setProject(projectInfra);
|
||||
}, [data, projects_Details]);
|
||||
|
||||
const openAssignModel = (assignData) => {
|
||||
setCurrentBuilding(assignData);
|
||||
setIsAssingRoleModal(true);
|
||||
};
|
||||
const openBuildingModel = (projectData) => {
|
||||
setIsBuildingModalOpen(true);
|
||||
};
|
||||
|
||||
const closeBuildingModel = () => {
|
||||
setIsBuildingModalOpen(false);
|
||||
};
|
||||
|
||||
const openWorkAreaModel = (projectData) => {
|
||||
setIsWorkAreaModalOpen(true);
|
||||
};
|
||||
|
||||
const closeWorkAreaModel = () => {
|
||||
setIsWorkAreaModalOpen(false);
|
||||
};
|
||||
const handleWorkAreaModelFormSubmit = (updatedModel) => {
|
||||
if (updatedModel.id == "") delete updatedModel.id;
|
||||
submitData([
|
||||
{
|
||||
building: null,
|
||||
floor: null,
|
||||
workArea: updatedModel,
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
const openTaskModel = (projectData) => {
|
||||
setIsTaskModalOpen(true);
|
||||
};
|
||||
|
||||
const closeTaskModel = () => {
|
||||
setIsTaskModalOpen(false);
|
||||
};
|
||||
|
||||
const handleTaskModelFormSubmit = (updatedModel) => {
|
||||
if (updatedModel.id == "") updatedModel.id = null;
|
||||
const updatedProject = { ...project };
|
||||
|
||||
ProjectRepository.manageProjectTasks([updatedModel])
|
||||
.then((response) => {
|
||||
onDataChange("task-change");
|
||||
showToast("Details updated successfully.", "success");
|
||||
// setClearFormTrigger( true );
|
||||
if (response?.data[0]) {
|
||||
const { workItemId, workItem } = response.data[0];
|
||||
|
||||
const updatedBuildings = updatedProject.buildings.map((building) =>
|
||||
building.id == updatedModel.buildingID
|
||||
? {
|
||||
...building,
|
||||
floors: building.floors.map((floor) =>
|
||||
floor.id == updatedModel.floorId
|
||||
? {
|
||||
...floor,
|
||||
workAreas: floor.workAreas.map((workArea) =>
|
||||
workArea.id === workItem?.workAreaId
|
||||
? {
|
||||
...workArea,
|
||||
workItems: workArea.workItems.some(
|
||||
(existingItem) =>
|
||||
existingItem.workItemId ===
|
||||
workItem.workItemId
|
||||
)
|
||||
? [...workArea.workItems] // Create a new array to trigger re-render
|
||||
: [...workArea.workItems, workItem],
|
||||
}
|
||||
: workArea
|
||||
),
|
||||
}
|
||||
: floor
|
||||
),
|
||||
}
|
||||
: building
|
||||
);
|
||||
updatedProject.buildings = updatedBuildings;
|
||||
// workItem update, but having local state issue there for needed to calling api
|
||||
clearCacheKey("projectInfo");
|
||||
refetch();
|
||||
|
||||
cacheData("projectInfo", {
|
||||
projectId: updatedProject.id,
|
||||
data: updatedProject,
|
||||
});
|
||||
|
||||
setProject(updatedProject);
|
||||
// closeTaskModel()
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
showToast(error.message, "error");
|
||||
});
|
||||
};
|
||||
|
||||
const submitData = async (infraObject) => {
|
||||
try {
|
||||
let response = await ProjectRepository.manageProjectInfra(infraObject);
|
||||
const entity = response.data;
|
||||
|
||||
const updatedProject = { ...project };
|
||||
// Handle the building data
|
||||
if (entity.building) {
|
||||
const { id, name, description } = entity.building;
|
||||
const updatedBuildings = updatedProject?.buildings?.map((building) =>
|
||||
building.id === id ? { ...building, name, description } : building
|
||||
);
|
||||
|
||||
// Add building if it doesn't exist
|
||||
if (!updatedProject.buildings.some((building) => building.id === id)) {
|
||||
updatedBuildings.push({
|
||||
id: id,
|
||||
name,
|
||||
description,
|
||||
floors: [],
|
||||
});
|
||||
}
|
||||
|
||||
updatedProject.buildings = updatedBuildings;
|
||||
|
||||
// Update the cache for buildings
|
||||
cacheData("projectInfo", {
|
||||
projectId: updatedProject.id,
|
||||
data: updatedProject,
|
||||
});
|
||||
setProject((prevProject) => ({
|
||||
...prevProject,
|
||||
buildings: updatedBuildings,
|
||||
}));
|
||||
// closeBuildingModel()
|
||||
}
|
||||
// Handle the floor data
|
||||
else if (entity.floor) {
|
||||
const { buildingId, id, floorName } = entity.floor;
|
||||
const updatedBuildings = updatedProject?.buildings?.map((building) =>
|
||||
building.id == buildingId
|
||||
? {
|
||||
...building,
|
||||
floors: building.floors
|
||||
.map((floor) =>
|
||||
floor.id === id
|
||||
? {
|
||||
...floor,
|
||||
floorName, // Update the floor name only
|
||||
// Keep other properties as they are (including workArea)
|
||||
}
|
||||
: floor
|
||||
)
|
||||
// Add the new floor if it doesn't already exist
|
||||
.concat(
|
||||
!building.floors.some((floor) => floor.id === id)
|
||||
? [{ id: id, floorName, workAreas: [] }] // New floor added with workArea set to null
|
||||
: []
|
||||
),
|
||||
}
|
||||
: building
|
||||
);
|
||||
|
||||
updatedProject.buildings = updatedBuildings;
|
||||
|
||||
// Cache the updated project
|
||||
cacheData("projectInfo", {
|
||||
projectId: updatedProject.id,
|
||||
data: updatedProject,
|
||||
});
|
||||
setProject(updatedProject);
|
||||
// closeFloorModel()
|
||||
}
|
||||
// Handle the work area data
|
||||
else if (entity.workArea) {
|
||||
let buildingId = infraObject[0].workArea.buildingId;
|
||||
|
||||
const { floorId, areaName, id } = entity.workArea;
|
||||
// Check if the workArea exists, otherwise create a new one
|
||||
const updatedBuildings = updatedProject.buildings.map((building) =>
|
||||
building.id == buildingId
|
||||
? {
|
||||
...building,
|
||||
floors: building.floors.map((floor) =>
|
||||
floor.id == floorId
|
||||
? {
|
||||
...floor,
|
||||
workAreas: floor.workAreas.some(
|
||||
(workArea) => workArea.id === id
|
||||
)
|
||||
? floor.workAreas.map((workArea) =>
|
||||
workArea.id === id
|
||||
? { ...workArea, areaName }
|
||||
: workArea
|
||||
)
|
||||
: [
|
||||
...floor.workAreas,
|
||||
{ id, areaName, workItems: [] },
|
||||
],
|
||||
}
|
||||
: floor
|
||||
),
|
||||
}
|
||||
: building
|
||||
);
|
||||
|
||||
updatedProject.buildings = updatedBuildings;
|
||||
|
||||
// Update the cache for work areas
|
||||
cacheData("projectInfo", {
|
||||
projectId: updatedProject.id,
|
||||
data: updatedProject,
|
||||
});
|
||||
setProject(updatedProject);
|
||||
// closeWorkAreaModel()
|
||||
}
|
||||
// Handle the task (workItem) data
|
||||
else {
|
||||
console.error("Unsupported data type for submitData", entity);
|
||||
}
|
||||
} catch (Err) {
|
||||
showToast("Somthing wrong", "error");
|
||||
}
|
||||
};
|
||||
|
||||
const toggleBuilding = (id) => {
|
||||
setExpandedBuildings((prev) =>
|
||||
prev.includes(id) ? prev.filter((bid) => bid !== id) : [...prev, id]
|
||||
);
|
||||
};
|
||||
|
||||
const handleModalData = (type, modaldata) => {
|
||||
setModalConfig({ type: type, data: modaldata });
|
||||
};
|
||||
const openModal = () => {
|
||||
const modalElement = document.getElementById("building-model");
|
||||
const modal = new Modal(modalElement, {
|
||||
backdrop: false,
|
||||
keyboard: true,
|
||||
focus: true,
|
||||
});
|
||||
modal.show();
|
||||
};
|
||||
const closeModal = () => {
|
||||
setIsModalOpen(false);
|
||||
setModalConfig(null);
|
||||
|
||||
const modalElement = document.getElementById("building-model");
|
||||
if (modalElement) {
|
||||
modalElement.classList.remove("show");
|
||||
modalElement.style.display = "none";
|
||||
}
|
||||
|
||||
document.body.classList.remove("modal-open");
|
||||
|
||||
const backdropElement = document.querySelector(".modal-backdrop");
|
||||
if (backdropElement) {
|
||||
backdropElement.classList.remove("modal-backdrop");
|
||||
backdropElement.style.display = "none";
|
||||
}
|
||||
document.body.style.overflow = "auto";
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (reloadedData) {
|
||||
refetch();
|
||||
@ -323,63 +55,30 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
{showModalBuilding && <GlobalModel isOpen={showModalBuilding} size="md" closeModal={() => setshowModalBuilding( false )}>
|
||||
<BuildingModel
|
||||
project={projectInfra}
|
||||
onClose={() => setshowModalBuilding( false )}
|
||||
/>
|
||||
</GlobalModel>}
|
||||
</GlobalModel>}
|
||||
{showModalFloor && <GlobalModel isOpen={showModalFloor} size="md" closeModal={()=>setshowModalFloor(false)}>
|
||||
<FloorModel
|
||||
project={projectInfra}
|
||||
onClose={()=>setshowModalFloor(false)}
|
||||
/>
|
||||
</GlobalModel>}
|
||||
|
||||
|
||||
|
||||
{isWorkAreaModelOpen && (
|
||||
<div
|
||||
className="modal fade show"
|
||||
id="work-area-model"
|
||||
tabIndex="-1"
|
||||
role="dialog"
|
||||
style={{ display: "block" }}
|
||||
aria-hidden="false"
|
||||
>
|
||||
{showModalWorkArea && <GlobalModel isOpen={showModalWorkArea} size="lg" closeModal={()=>setshowModalWorkArea(false)} >
|
||||
<WorkAreaModel
|
||||
project={project}
|
||||
onClose={closeWorkAreaModel}
|
||||
|
||||
onClearComplete={() => setClearFormTrigger(false)}
|
||||
project={projectInfra}
|
||||
onClose={()=>setshowModalWorkArea(false)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isTaskModelOpen && (
|
||||
<div
|
||||
className="modal fade show"
|
||||
id="task-model"
|
||||
tabIndex="-1"
|
||||
role="dialog"
|
||||
style={{ display: "block" }}
|
||||
aria-hidden="false"
|
||||
>
|
||||
<TaskModel
|
||||
project={project}
|
||||
onClose={closeTaskModel}
|
||||
onSubmit={handleTaskModelFormSubmit}
|
||||
|
||||
onClearComplete={() => setClearFormTrigger(false)}
|
||||
</GlobalModel>}
|
||||
{showModalTask && ( <GlobalModel isOpen={showModalTask} size="lg" closeModal={()=>setshowModalTask(false)}>
|
||||
<TaskModel
|
||||
project={projectInfra}
|
||||
onClose={()=>setshowModalTask(false)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isModalOpen && (
|
||||
<ProjectModal modalConfig={modalConfig} closeModal={closeModal} />
|
||||
)}
|
||||
|
||||
</GlobalModel>)}
|
||||
<div className="col-md-12 col-lg-12 col-xl-12 order-0 mb-4">
|
||||
<div className="card">
|
||||
<div className="card-body" style={{ padding: "0.5rem" }}>
|
||||
@ -409,7 +108,7 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
|
||||
<button
|
||||
type="button"
|
||||
className="link-button m-1"
|
||||
onClick={() => openWorkAreaModel()}
|
||||
onClick={() => setshowModalWorkArea(true)}
|
||||
>
|
||||
<i className="bx bx-plus-circle me-2"></i>
|
||||
Manage Work Areas
|
||||
@ -417,7 +116,7 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
|
||||
<button
|
||||
type="button"
|
||||
className="link-button m-1"
|
||||
onClick={() => openTaskModel()}
|
||||
onClick={()=>setshowModalTask(true)}
|
||||
>
|
||||
<i className="bx bx-plus-circle me-2"></i>
|
||||
Create Tasks
|
||||
@ -430,7 +129,7 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
|
||||
<InfraTable
|
||||
buildings={projectInfra}
|
||||
projectId={projectId}
|
||||
handleFloor={submitData}
|
||||
// handleFloor={submitData}
|
||||
signalRHandler ={signalRHandler}
|
||||
/>
|
||||
)}
|
||||
|
@ -346,7 +346,7 @@ export const useProjectTasks = (workAreaId,IsExpandedArea=false) =>
|
||||
}
|
||||
|
||||
|
||||
// -- Mutation-------------------------------
|
||||
// -- -------------Mutation-------------------------------
|
||||
|
||||
|
||||
|
||||
@ -396,11 +396,9 @@ export const useUpdateProject = ({ onSuccessCallback }) => {
|
||||
onSuccess: (data, variables) => {
|
||||
const { projectId } = variables;
|
||||
|
||||
// Invalidate queries
|
||||
queryClient.invalidateQueries(["ProjectsList"]);
|
||||
queryClient.invalidateQueries(["projectinfo", projectId]);
|
||||
|
||||
// Emit update event
|
||||
eventBus.emit("project", {
|
||||
keyword: "Update_Project",
|
||||
response: data,
|
||||
@ -499,16 +497,22 @@ export const useManageTask = ({onSuccessCallback}) =>
|
||||
mutationFn: async ( payload ) => await ProjectRepository.manageProjectTasks( payload ),
|
||||
onSuccess: ( data, variables ) =>
|
||||
{
|
||||
debugger
|
||||
if ( variables[ 0 ]?.id )
|
||||
{
|
||||
showToast( 'Activity Updated Successfully', 'success' );
|
||||
} else
|
||||
{
|
||||
showToast( 'Activity Created Successfully', 'success' );
|
||||
}
|
||||
queryClient.invalidateQueries(["WorkItems"])
|
||||
showToast( 'Activity Updated Successfully', 'success' );
|
||||
if (onSuccessCallback) onSuccessCallback(data);
|
||||
},
|
||||
onError: (error) =>
|
||||
{
|
||||
const message =
|
||||
error?.response?.data?.message || error.message || 'Error occurred during API call';
|
||||
showToast(message, 'error');
|
||||
|
||||
showToast(message, 'error');
|
||||
}
|
||||
|
||||
})
|
||||
|
@ -127,7 +127,7 @@ const EmployeeList = () => {
|
||||
modalElement.classList.remove("show");
|
||||
modalElement.style.display = "none";
|
||||
document.body.classList.remove("modal-open");
|
||||
document.querySelector(".modal-backdrop")?.remove(); // Use optional chaining for safety
|
||||
document.querySelector(".modal-backdrop")?.remove();
|
||||
}
|
||||
setShowModal(false);
|
||||
clearCacheKey("employeeProfile");
|
||||
@ -152,32 +152,9 @@ const EmployeeList = () => {
|
||||
setEmployeeList(sorted);
|
||||
setFilteredData(sorted);
|
||||
}
|
||||
}, [loading, employees, selectedProject, showAllEmployees]);
|
||||
}, [loading, employees, selectedProjectId, showAllEmployees]);
|
||||
|
||||
|
||||
// const suspendEmployee = (id) => {
|
||||
// setemployeeLodaing(true);
|
||||
// EmployeeRepository.deleteEmployee(id)
|
||||
// .then((response) => {
|
||||
// showToast("Employee deleted successfully.", "success");
|
||||
// clearCacheKey("employeeListByProject");
|
||||
// clearCacheKey("allEmployeeList");
|
||||
// clearCacheKey("allInactiveEmployeeList");
|
||||
// clearCacheKey("employeeProfile");
|
||||
// setEmployeeList([]);
|
||||
// recallEmployeeData(showInactive);
|
||||
// setemployeeLodaing(false);
|
||||
// setIsDeleteModalOpen(false);
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// const message =
|
||||
// error.response?.data?.message ||
|
||||
// error.message ||
|
||||
// "An unexpected error occurred";
|
||||
// showToast(message, "error");
|
||||
// setemployeeLodaing(false);
|
||||
// setIsDeleteModalOpen(false);
|
||||
// });
|
||||
// };
|
||||
|
||||
const handleConfigData = (config) => {
|
||||
setModelConfig(config);
|
||||
|
Loading…
x
Reference in New Issue
Block a user