Merge branch 'Ashutosh_Enhancement#205_Added_WorkCategory_Dropdown' into Issue_May_2W
This commit is contained in:
commit
a7aa815691
@ -3,7 +3,7 @@ import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { useActivitiesMaster } from "../../../hooks/masterHook/useMaster";
|
||||
import { useActivitiesMaster, useWorkCategoriesMaster } from "../../../hooks/masterHook/useMaster";
|
||||
import { useProjectDetails } from "../../../hooks/useProjects";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import ProjectRepository from "../../../repositories/ProjectRepository";
|
||||
@ -18,6 +18,7 @@ import showToast from "../../../services/toastService";
|
||||
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"),
|
||||
})
|
||||
@ -43,17 +44,21 @@ const EditActivityModal = ({
|
||||
);
|
||||
const defaultModel = {
|
||||
activityID: 0,
|
||||
workCategoryId: 0,
|
||||
plannedWork: 0,
|
||||
completedWork: 0,
|
||||
};
|
||||
|
||||
const {projects_Details, refetch} = useProjectDetails( selectedProject );
|
||||
const [ActivityUnit,setActivityUnit]= useState("")
|
||||
const { projects_Details, refetch } = useProjectDetails(selectedProject);
|
||||
const [ActivityUnit, setActivityUnit] = useState("");
|
||||
const { activities, loading, error } = useActivitiesMaster();
|
||||
const { categories, categoryLoading, categoryError } =
|
||||
useWorkCategoriesMaster();
|
||||
const [formData, setFormData] = useState(defaultModel);
|
||||
const [selectedActivity, setSelectedActivity] = useState(null);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [activityData, setActivityData] = useState([]);
|
||||
const [categoryData, setCategoryData] = useState([]);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const {
|
||||
@ -70,12 +75,19 @@ const EditActivityModal = ({
|
||||
});
|
||||
|
||||
const handleActivityChange = (e) => {
|
||||
const selectedId = Number(e.target.value);
|
||||
const selected = activityData.find( ( a ) => a.id === selectedId );
|
||||
const selectedId = String(e.target.value);
|
||||
const selected = activityData.find((a) => a.id === selectedId);
|
||||
setSelectedActivity(selected || null);
|
||||
setValue("activityID", selectedId);
|
||||
};
|
||||
|
||||
const handleCategoryChange = (e) => {
|
||||
const selectedId = String(e.target.value);
|
||||
const category = categoryData.find((b) => b.id === selectedId);
|
||||
setSelectedCategory(category || null);
|
||||
setValue("workCategoryId", selectedId);
|
||||
};
|
||||
|
||||
const onSubmitForm = async ( data ) =>
|
||||
{
|
||||
setIsSubmitting(true)
|
||||
@ -167,6 +179,8 @@ const EditActivityModal = ({
|
||||
useEffect(() => {
|
||||
reset({
|
||||
activityID: workItem?.workItem?.activityId || workItem?.activityId || 0,
|
||||
workCategoryId:
|
||||
workItem?.workItem?.workCategoryId || workItem?.workCategoryId || 0,
|
||||
plannedWork:
|
||||
workItem?.workItem?.plannedWork || workItem?.plannedWork || 0,
|
||||
completedWork:
|
||||
@ -177,13 +191,12 @@ const EditActivityModal = ({
|
||||
|
||||
const ISselectedActivity = watch("activityID");
|
||||
useEffect(() => {
|
||||
if( ISselectedActivity ){
|
||||
if (ISselectedActivity) {
|
||||
const selected = activities.find((a) => a.id === ISselectedActivity);
|
||||
setSelectedActivity( selected || null );
|
||||
setActivityUnit(selected?.unitOfMeasurement)
|
||||
setSelectedActivity(selected || null);
|
||||
setActivityUnit(selected?.unitOfMeasurement);
|
||||
}
|
||||
}, [ ISselectedActivity,activities] );
|
||||
|
||||
}, [ISselectedActivity, activities]);
|
||||
|
||||
return (
|
||||
<div className="modal-dialog modal-lg modal-simple modal-edit-user">
|
||||
@ -279,6 +292,45 @@ const EditActivityModal = ({
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Select Category */}
|
||||
<div className="col-12 col-md-12">
|
||||
<label className="form-label" htmlFor="activityID">
|
||||
Select Work Category
|
||||
</label>
|
||||
<select
|
||||
id="workCategoryId"
|
||||
className="form-select form-select-sm"
|
||||
{...register("workCategoryId")}
|
||||
>
|
||||
{loading ? (
|
||||
<option value="">Loading...</option>
|
||||
) : (
|
||||
<option disabled>Select Category</option>
|
||||
)}
|
||||
{categories &&
|
||||
categories.length > 0 &&
|
||||
categories
|
||||
.slice()
|
||||
.sort((a, b) =>
|
||||
(a.name || "").localeCompare(
|
||||
b.name || ""
|
||||
)
|
||||
)
|
||||
.map((category) => (
|
||||
<option key={category.id} value={category.id}>
|
||||
{category.name}
|
||||
</option>
|
||||
))}
|
||||
{!loading && categories.length === 0 && (
|
||||
<option disabled>No categories available</option>
|
||||
)}
|
||||
</select>
|
||||
|
||||
{errors.workCategoryId && (
|
||||
<p className="danger-text">{errors.workCategoryId.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Planned Work */}
|
||||
{/* {ISselectedActivity && ( */}
|
||||
<div className="col-5 col-md-5">
|
||||
|
@ -2,23 +2,28 @@ 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";
|
||||
import {
|
||||
useActivitiesMaster,
|
||||
useWorkCategoriesMaster,
|
||||
} 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"),
|
||||
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"),
|
||||
});
|
||||
|
||||
const defaultModel = {
|
||||
id: null,
|
||||
buildingID:"0",
|
||||
buildingID: "0",
|
||||
floorId: "0",
|
||||
workAreaId: "0",
|
||||
activityID: null,
|
||||
workCategoryId: "",
|
||||
plannedWork: 0,
|
||||
completedWork: 0,
|
||||
};
|
||||
@ -30,15 +35,18 @@ const TaskModel = ({
|
||||
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 {activities, loading, error} = useActivitiesMaster();
|
||||
const [categoryData, setCategoryData] = useState([]);
|
||||
const { activities, loading, error } = useActivitiesMaster();
|
||||
const { categories, categoryLoading, categoryError } =
|
||||
useWorkCategoriesMaster();
|
||||
|
||||
const {
|
||||
register,
|
||||
@ -79,6 +87,7 @@ const TaskModel = ({
|
||||
floorId: value,
|
||||
workAreaId: 0,
|
||||
activityID: 0,
|
||||
workCategoryId: categoryData?.[0]?.id?.toString() ?? "",
|
||||
}));
|
||||
};
|
||||
|
||||
@ -104,13 +113,24 @@ const TaskModel = ({
|
||||
}));
|
||||
};
|
||||
|
||||
const onSubmitForm = async ( data ) =>
|
||||
{
|
||||
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) => {
|
||||
console.log(data);
|
||||
setIsSubmitting(true);
|
||||
await onSubmit(data);
|
||||
setValue("plannedWork", 0);
|
||||
setValue( "completedWork", 0 );
|
||||
setValue("activityID",0)
|
||||
setValue("completedWork", 0);
|
||||
setValue("activityID", 0);
|
||||
setValue("workCategoryId", categoryData?.[0]?.id?.toString() ?? "");
|
||||
setIsSubmitting(false);
|
||||
};
|
||||
|
||||
@ -120,15 +140,32 @@ const TaskModel = ({
|
||||
setSelectedFloor(null);
|
||||
setSelectedWorkArea(null);
|
||||
setSelectedActivity(null);
|
||||
setSelectedCategory(categoryData?.[0]?.id?.toString() ?? "");
|
||||
reset(defaultModel);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && Array.isArray(activities) && activities.length > 0) {
|
||||
|
||||
setActivityData(activities);
|
||||
}
|
||||
}, [activities, loading]);
|
||||
|
||||
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])
|
||||
}
|
||||
}, [categories, categoryLoading]);
|
||||
|
||||
return (
|
||||
<div className="modal-dialog modal-lg modal-simple modal-edit-user">
|
||||
<div className="modal-content">
|
||||
@ -247,9 +284,7 @@ const TaskModel = ({
|
||||
|
||||
{selectedWorkArea && (
|
||||
<div className="col-12 col-md-12">
|
||||
<label className="form-label" >
|
||||
Select Activity
|
||||
</label>
|
||||
<label className="form-label">Select Activity</label>
|
||||
<select
|
||||
id="activityID"
|
||||
className="form-select form-select-sm"
|
||||
@ -257,28 +292,25 @@ const TaskModel = ({
|
||||
onChange={handleActivityChange}
|
||||
>
|
||||
<option value="0">Select Activity</option>
|
||||
{activityData && activityData.length > 0 && (
|
||||
{activityData &&
|
||||
activityData.length > 0 &&
|
||||
activityData
|
||||
?.slice()
|
||||
?.sort( ( a, b ) =>
|
||||
{
|
||||
?.sort((a, b) => {
|
||||
const nameA = a?.activityName || "";
|
||||
const nameB = b?.activityName || "";
|
||||
return nameA.localeCompare( nameB );
|
||||
} )
|
||||
?.map( ( activity ) => (
|
||||
return nameA.localeCompare(nameB);
|
||||
})
|
||||
?.map((activity) => (
|
||||
<option key={activity.id} value={activity.id}>
|
||||
{
|
||||
activity.activityName ||
|
||||
|
||||
`Unnamed (id: ${ activity.id })`}
|
||||
{activity.activityName ||
|
||||
`Unnamed (id: ${activity.id})`}
|
||||
</option>
|
||||
) )
|
||||
) }
|
||||
{(!loading && activities.length === 0 )&& (
|
||||
))}
|
||||
{!loading && activities.length === 0 && (
|
||||
<option disabled>No activities available</option>
|
||||
)}
|
||||
{loading && ( <option disabled>Loading...</option>)}
|
||||
{loading && <option disabled>Loading...</option>}
|
||||
</select>
|
||||
|
||||
{errors.activityID && (
|
||||
@ -287,7 +319,38 @@ const TaskModel = ({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selectedActivity && (
|
||||
{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
|
||||
@ -304,7 +367,7 @@ const TaskModel = ({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selectedActivity && (
|
||||
{selectedActivity && selectedCategory && (
|
||||
<div className="col-5 col-md-5">
|
||||
<label className="form-label" htmlFor="completedWork">
|
||||
{formData.id !== "0" ? "Modify " : "Enter "} Completed Work
|
||||
@ -324,7 +387,7 @@ const TaskModel = ({
|
||||
)}
|
||||
|
||||
{/* Unit */}
|
||||
{selectedActivity && (
|
||||
{selectedActivity && selectedCategory && (
|
||||
<div className="col-2 col-md-2">
|
||||
<label className="form-label" htmlFor="unit">
|
||||
Unit
|
||||
@ -340,9 +403,7 @@ const TaskModel = ({
|
||||
|
||||
<div className="col-12 text-center">
|
||||
<button type="submit" className="btn btn-sm btn-primary me-3">
|
||||
{isSubmitting
|
||||
? "Please Wait.."
|
||||
: "Add Task"}
|
||||
{isSubmitting ? "Please Wait.." : "Add Task"}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
|
@ -121,6 +121,9 @@ const WorkArea = ({ workArea, floor, forBuilding }) => {
|
||||
<th className="infra-activity-table-header d-sm-none d-sm-table-cell">
|
||||
Status
|
||||
</th>
|
||||
<th className="infra-activity-table-header-first">
|
||||
Category
|
||||
</th>
|
||||
{/* for greather than mobile view ************* */}
|
||||
<th className="infra-activity-table-header d-none d-md-table-cell">
|
||||
Planned
|
||||
|
@ -160,6 +160,15 @@ const WorkItem = ( {
|
||||
? NewWorkItem?.workItem?.plannedWork || workItem?.plannedWork
|
||||
: "NA"}
|
||||
</td>
|
||||
|
||||
<td className="text-start table-cell-small">
|
||||
<span className="fw-light">
|
||||
{hasWorkItem
|
||||
? NewWorkItem?.workItem?.workCategoryMaster?.name ||
|
||||
workItem.workCategoryMaster?.name || "NA"
|
||||
: "NA"}
|
||||
</span>
|
||||
</td>
|
||||
{/* for greather than mobile view ************* */}
|
||||
<td className="text-center d-none d-md-table-cell">
|
||||
{hasWorkItem
|
||||
|
@ -117,3 +117,36 @@ export const useActivitiesMaster = () =>
|
||||
|
||||
return {activities,loading,error}
|
||||
}
|
||||
|
||||
export const useWorkCategoriesMaster = () =>
|
||||
{
|
||||
const [ categories, setCategories ] = useState( [] )
|
||||
const [ categoryLoading, setloading ] = useState( false );
|
||||
const [ categoryError, setError ] = useState( "" )
|
||||
|
||||
const fetchCategories =async () => {
|
||||
const cacheddata = getCachedData("Work Category");
|
||||
|
||||
if (!cacheddata) {
|
||||
setloading(true);
|
||||
try {
|
||||
const response = await MasterRespository.getWorkCategory();
|
||||
setCategories(response.data);
|
||||
cacheData("Work Category", response.data);
|
||||
} catch (err) {
|
||||
setError(err);
|
||||
console.log(err);
|
||||
} finally {
|
||||
setloading(false);
|
||||
}
|
||||
} else {
|
||||
setCategories(cacheddata);
|
||||
}
|
||||
}
|
||||
useEffect( () =>
|
||||
{
|
||||
fetchCategories()
|
||||
}, [] )
|
||||
|
||||
return {categories,categoryLoading,categoryError}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user