diff --git a/src/components/Activities/ReportTaskComments.jsx b/src/components/Activities/ReportTaskComments.jsx index 0c2d1712..f5db9434 100644 --- a/src/components/Activities/ReportTaskComments.jsx +++ b/src/components/Activities/ReportTaskComments.jsx @@ -17,6 +17,7 @@ const ReportTaskComments = ({ actionAllow = false, handleCloseAction, }) => { + const defaultCompletedTask = Number(commentsData?.completedTask) || 0; const schema = actionAllow ? z.object({ comment: z.string().min(1, "Comment cannot be empty"), @@ -35,8 +36,8 @@ const ReportTaskComments = ({ invalid_type_error: "Completed Work must be a number", }) .min(0, "Completed Work must be greater than 0") - .max(commentsData?.completedTask, { - message: `Completed task cannot exceed : ${commentsData?.completedTask}`, + .max(defaultCompletedTask, { + message: `Completed task cannot exceed: ${defaultCompletedTask}`, }) ), }) @@ -46,8 +47,8 @@ const ReportTaskComments = ({ const [loading, setloading] = useState(false); const [comments, setComment] = useState([]); - const {status, loading: auditStatusLoading} = useAuditStatus(); - const [IsNeededSubTask,setIsNeededSubTask] = useState(false) + const { status, loading: auditStatusLoading } = useAuditStatus(); + const [IsNeededSubTask, setIsNeededSubTask] = useState(false); const { watch, @@ -62,7 +63,6 @@ const ReportTaskComments = ({ const containerRef = useRef(null); const firstRender = useRef(true); - useEffect(() => { const taskList = getCachedData("taskList"); if (taskList && taskList.data && commentsData?.id) { @@ -107,6 +107,10 @@ const ReportTaskComments = ({ if (actionAllow) { handleCloseAction(IsNeededSubTask); + showToast( + "Review submitted successfully. Record has been updated.", + "success" + ); } else { if (taskList && taskList.data) { const updatedTaskList = taskList.data.map((task) => { @@ -127,11 +131,11 @@ const ReportTaskComments = ({ projectId: taskList.projectId, }); } + showToast("Successfully Sent", "success"); } reset(); setloading(false); - showToast("Successfully Sent", "success"); } catch (error) { setloading(false); showToast( @@ -142,56 +146,95 @@ const ReportTaskComments = ({ }; const selectedAuditStatus = watch("workStatus"); + + useEffect(() => { + reset({ + approvedTask: defaultCompletedTask || 0, + }); + }, [ defaultCompletedTask ] ); return (
Activity Summary
-

- - Location : - +

+
+ + Location: +
+
{`${commentsData?.workItem?.workArea?.floor?.building?.name}`}{" "} {" "} - {`${commentsData?.workItem?.workArea?.floor?.floorName} `}{" "} - - {`${commentsData?.workItem?.workArea?.areaName}`} - - {` ${commentsData?.workItem?.activityMaster?.activityName}`} - -

+ {`${commentsData?.workItem?.workArea?.floor?.floorName}`}{" "} + {" "} + {`${commentsData?.workItem?.workArea?.areaName}`}{" "} + {" "} + {`${commentsData?.workItem?.activityMaster?.activityName}`} +
+
-

- - Assigned By : - - {commentsData?.assignedBy?.firstName + - " " + - commentsData?.assignedBy?.lastName} - {" "} -

+
+
+ {commentsData?.assignedBy && ( +
+ + Assigned By: + + {commentsData.assignedBy.firstName}{" "} + {commentsData.assignedBy.lastName} + +
+ )} +
-

- - Reported By :- -

+
+ {commentsData.reportedBy && ( +
+ + Reported By: +
+ + {commentsData.reportedBy.firstName + + " " + + commentsData.reportedBy.lastName} +
+
+ )} +
+
+ +
+
+
+ + Planned Work: + + {commentsData?.plannedTask}{" "} + {commentsData?.workItem?.activityMaster?.unitOfMeasurement} + +
+
+ +
+ {commentsData?.reportedDate != null && ( +
+ + Completed Work: + + {commentsData?.completedTask}{" "} + {commentsData?.workItem?.activityMaster?.unitOfMeasurement} + +
+ )} +
+
+ -

- {" "} - - Planned Work: {commentsData?.plannedTask}{" "} - {commentsData?.workItem?.activityMaster?.unitOfMeasurement} -

- {commentsData?.reportedDate != null && ( -

- - Completed Work : {commentsData?.completedTask}{" "} - {commentsData?.workItem?.activityMaster?.unitOfMeasurement} -

- )} - {!commentsData?.reportedDate && ( -

Completed Work :  -

- )}

Team : @@ -209,16 +252,58 @@ const ReportTaskComments = ({ ))}

+
- +
Note: - -
+
+
{commentsData?.description}
+ + {commentsData?.approvedBy && ( + <> +
+
+ +
+ {commentsData.approvedBy && ( +
+ + Approved By: +
+ + {commentsData.approvedBy.firstName + + " " + + commentsData.approvedBy.lastName} +
+
+ )} +
+ +
+ {commentsData?.workStatus != null && ( +
+ + Work Status : + + {commentsData?.workStatus.name} + {/* {commentsData?.} */} + +
+ )} +
+
+
+ Total Approved : {commentsData?.completedTask } +
+ )} + {commentsData?.reportedPreSignedUrls?.length > 0 && ( <>

@@ -234,7 +319,8 @@ const ReportTaskComments = ({ )}

- {actionAllow && ( + {( actionAllow && !commentsData.approvedBy ) && ( + <>
@@ -249,40 +335,39 @@ const ReportTaskComments = ({

)}
-
-
- - -
+
+ + {errors.workStatus && ( -

{errors.workStatus.message}

+
+ {errors.workStatus.message} +
)}
-
+
+ + )} @@ -295,17 +380,21 @@ const ReportTaskComments = ({ {errors.comment && (
{errors.comment.message}
)} -
-
+
+
setIsNeededSubTask((e)=>!e)} + onChange={(e) => setIsNeededSubTask((e) => !e)} value={IsNeededSubTask} id="defaultCheck1" /> -
diff --git a/src/components/Activities/SubTask.jsx b/src/components/Activities/SubTask.jsx index 996509e5..2514f325 100644 --- a/src/components/Activities/SubTask.jsx +++ b/src/components/Activities/SubTask.jsx @@ -1,550 +1,228 @@ -import React, { useState, useEffect, useRef } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import { changeMaster } from "../../slices/localVariablesSlice"; -import useMaster from "../../hooks/masterHook/useMaster"; -import { useForm, Controller } from "react-hook-form"; -import { z } from "zod"; +import React, { useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; -import { clearCacheKey, getCachedData } from "../../slices/apiDataManager"; -import { useEmployeesAllOrByProjectId } from "../../hooks/useEmployees"; -import { TasksRepository } from "../../repositories/ProjectRepository"; +import { string, z } from "zod"; +import { + useActivitiesMaster, + useWorkCategoriesMaster, +} from "../../hooks/masterHook/useMaster"; import showToast from "../../services/toastService"; -import { useProjectDetails } from "../../hooks/useProjects"; +import ProjectRepository from "../../repositories/ProjectRepository"; +import { useTaskById } from "../../hooks/useTasks"; -const SubTask = ({ assignData, onClose }) => { - const maxPlanned = - assignData?.workItem?.workItem?.plannedWork - - assignData?.workItem?.workItem?.completedWork; - - // Zod schema for form validation - - const schema = z.object({ - selectedEmployees: z - .array(z.string()) - .min(1, { message: "At least one employee must be selected" }), - description: z.string().min(1, { message: "Description is required" }), - plannedTask: z.preprocess( - (val) => parseInt(val, 10), - z - .number({ - required_error: "Planned task is required", - invalid_type_error: "Target for Today must be a number", - }) - .int() - .positive({ message: "Planned task must be a positive number" }) - .max(maxPlanned, { - message: `Planned task cannot exceed ${maxPlanned}`, - }) - ), - }); - - const [isHelpVisibleTarget, setIsHelpVisibleTarget] = useState(false); - const helpPopupRefTarget = useRef(null); - const [isHelpVisible, setIsHelpVisible] = useState(false); - - const infoRef = useRef(null); - const infoRef1 = useRef(null); - - useEffect(() => { - if (typeof bootstrap !== "undefined") { - if (infoRef.current) { - new bootstrap.Popover(infoRef.current, { - trigger: "focus", - placement: "right", - html: true, - content: `
Total Pending tasks of the Activity
`, - }); - } - - if (infoRef1.current) { - new bootstrap.Popover(infoRef1.current, { - trigger: "focus", - placement: "right", - html: true, - content: `
Target task for today
`, - }); - } - } else { - console.warn("Bootstrap is not available. Popovers might not function."); - } - }, []); - - const selectedProject = useSelector( - (store) => store.localVariables.projectId - ); - const { employees, loading: employeeLoading } = useEmployeesAllOrByProjectId( - selectedProject, - false - ); - const dispatch = useDispatch(); - const { loading } = useMaster(); - const jobRoleData = getCachedData("Job Role"); - - const [selectedRole, setSelectedRole] = useState("all"); - const [displayedSelection, setDisplayedSelection] = useState(""); +const subTaskSchema = z.object({ + activityId: z.string().min(1, "Activity is required"), + workCategoryId: z.string().min(1, "Category is required"), + plannedWork: z.number().min(1, "Planned work is required"), + completedWork: z.number().min(0, "Completed work cannot be negative"), + comment: z.string().min(1, "Comment is required"), +}); +const SubTask = ({ activity, onClose }) => { + const [selectedCategory, setSelectedCategory] = useState(null); + const [categoryData, setCategoryData] = useState([]); + const { activities, loading } = useActivitiesMaster(); + const { categories, categoryLoading } = useWorkCategoriesMaster(); + const [isSubmitting, setIsSubmitting] = useState(false); + const { Task, loading: TaskLoading } = useTaskById(activity?.id); const { + register, handleSubmit, - control, - setValue, - watch, formState: { errors }, reset, - trigger, + setValue, + watch, } = useForm({ - defaultValues: { - selectedEmployees: [], - description: "", - plannedTask: "", - }, - resolver: zodResolver(schema), + resolver: zodResolver(subTaskSchema), }); + const selectedActivityId = watch("activityId"); + const selectedActivity = activities?.find((a) => a.id === selectedActivityId); - const handleCheckboxChange = (event, user) => { - const isChecked = event.target.checked; - let updatedSelectedEmployees = watch("selectedEmployees") || []; // Get current selected employees from form state - - if (isChecked) { - if (!updatedSelectedEmployees.includes(user.id)) { - updatedSelectedEmployees = [...updatedSelectedEmployees, user.id]; - } - } else { - updatedSelectedEmployees = updatedSelectedEmployees.filter( - (id) => id !== user.id - ); - } - setValue("selectedEmployees", updatedSelectedEmployees); - trigger("selectedEmployees"); // <--- IMPORTANT: Trigger validation here - }; - + // Set categories when fetched useEffect(() => { - dispatch(changeMaster("Job Role")); - return () => setSelectedRole("all"); - }, [dispatch]); + setCategoryData(categories); + }, [categories]); - // Handler for role filter change - const handleRoleChange = (event) => { - setSelectedRole(event.target.value); + // Set initial values from activity + useEffect(() => { + if (Task?.workItem) { + reset({ + workCategoryId: Task?.workItem?.workCategoryId || "", + activityId: Task?.workItem?.activityId || "", + plannedWork: Number(Task.notApprovedTask || Task.workItem?.plannedWork), + completedWork: 0, + comment: "", + }); + } + }, [Task, reset]); + + const handleCategoryChange = (e) => { + const value = e.target.value; + const category = categoryData.find((b) => b.id === String(value)); + setSelectedCategory(category); + setValue("workCategoryId", value); }; - const filteredEmployees = - selectedRole === "all" - ? employees - : employees?.filter( - (emp) => String(emp.jobRoleId || "") === selectedRole - ); - - const onSubmit = async (data) => { - const selectedEmployeeIds = data.selectedEmployees; - - const taskTeamWithDetails = selectedEmployeeIds - .map((empId) => { - return empId; - }) - .filter(Boolean); - - - - - let payload = { - - assignmentDate: new Date().toISOString(), - parentTaskId: assignData?.id, - plannedTask: data.plannedTask, - description: data.description, - taskTeam: taskTeamWithDetails, - workItemId: assignData.workItem.workItemId - } + const onSubmitForm = async (formData) => { + let payload = { + workAreaID: Task.workItem.workAreaId, + workCategoryId: formData.workCategoryId, + activityID: formData.activityId, + plannedWork: formData.plannedWork, + completedWork: formData.completedWork, + parentTaskId: activity?.id, + comment: formData.comment, + }; + setIsSubmitting(true); try { - console.log(payload) - showToast("Task Successfully Assigned", "success"); + await ProjectRepository.manageProjectTasks([payload]); + showToast("SubTask Created Successfully", "success"); + setIsSubmitting(false); reset(); - clearCacheKey("projectInfo"); - onClose(); } catch (error) { - console.error("Error assigning task:", error); - showToast("Something went wrong. Please try again.", "error"); + setIsSubmitting(false); + const msg = + error.response.message || + error.message || + "Error occured during API calling"; + showToast(msg, "error"); } }; - const closedModel = () => { - reset(); - onClose(); - }; - console.log(assignData); return ( -
-

Create Sub Task

-
-
-

- - Work Location : - {[ - assignData?.building?.name, - assignData?.floor?.floorName, - assignData?.workArea?.areaName, - assignData?.workItem?.workItem?.activityMaster?.activityName, - ] - .filter(Boolean) // Filter out any undefined/null values - .map((item, index, array) => ( - - {item} - {index < array.length - 1 && ( - - )} - - ))} - -

- - -
-
-
-
-
- Select Team -
{displayedSelection}
- - -
    -
  • - -
  • - {jobRoleData?.map((user) => ( -
  • - -
  • - ))} -
-
-
-
-
- -
-
- {selectedRole !== "" && ( -
- {loading ? ( -
-

Loading roles...

-
- ) : filteredEmployees?.length > 0 ? ( - filteredEmployees?.map((emp) => { - const jobRole = jobRoleData?.find( - (role) => role?.id === emp?.jobRoleId - ); - - return ( -
-
- ( - { - handleCheckboxChange(e, emp); - }} - /> - )} - /> -
-

- {emp.firstName} {emp.lastName} -

- - {loading ? ( - - - - ) : ( - jobRole?.name || "Unknown Role" - )} - -
-
-
- ); - }) - ) : ( -
-

- No employees found for the selected role. -

-
- )} -
- )} -
-
- -
- {watch("selectedEmployees")?.length > 0 && ( -
-
- {watch("selectedEmployees")?.map((empId) => { - const emp = employees.find((emp) => emp.id === empId); - return ( - emp && ( - - {emp.firstName} {emp.lastName} -

{ - const updatedSelected = watch( - "selectedEmployees" - ).filter((id) => id !== empId); - setValue( - "selectedEmployees", - updatedSelected - ); - trigger("selectedEmployees"); // <--- IMPORTANT: Trigger validation on removing badge - }} - > - -

-
- ) - ); - })} -
-
- )} -
- - {!loading && errors.selectedEmployees && ( -
-

{errors.selectedEmployees.message}

{" "} - {/* Use message from Zod schema */} -
- )} - -
-
- -
-
- - {/* Target for Today input and validation */} -
-
- -
-
- ( -
- - - { - assignData?.workItem?.workItem?.activityMaster - ?.unitOfMeasurement - } - -
-
-   - - - - -
-
-
- )} - /> -
- - {errors.plannedTask && ( -
- {errors.plannedTask.message} -
- )} - - {isHelpVisible && ( -
-

- Enter the target value for today's task. -

-
- )} -
- - - ( -