From a6c6a7389941dc5b832631f77e60c6d48bd790e1 Mon Sep 17 00:00:00 2001 From: "kartik.sharma" Date: Sat, 24 May 2025 14:45:29 +0530 Subject: [PATCH] Correction in Assign Task popup. --- src/components/Project/AssignRole.jsx | 184 ++++++++++++++------------ 1 file changed, 103 insertions(+), 81 deletions(-) diff --git a/src/components/Project/AssignRole.jsx b/src/components/Project/AssignRole.jsx index 58d162bb..a639abc8 100644 --- a/src/components/Project/AssignRole.jsx +++ b/src/components/Project/AssignRole.jsx @@ -2,71 +2,78 @@ 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 { employee } from "../../data/masters"; import { useForm, Controller } from "react-hook-form"; import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { getCachedData } from "../../slices/apiDataManager"; -import { useProjects } from "../../hooks/useProjects"; import { useEmployeesAllOrByProjectId } from "../../hooks/useEmployees"; import { TasksRepository } from "../../repositories/ProjectRepository"; import showToast from "../../services/toastService"; const AssignRoleModel = ({ assignData, onClose }) => { + // Calculate maxPlanned based on assignData 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" }), + .min(1, { message: "At least one employee must be selected" }), // Added custom message here for consistency description: z.string().min(1, { message: "Description is required" }), plannedTask: z.preprocess( - (val) => parseInt(val, 10), + (val) => parseInt(val, 10), // Preprocess value to integer z .number({ required_error: "Planned task is required", - invalid_type_error: "Planned task must be a number", + invalid_type_error: "Target for Today must be a number", }) - .int() - .positive({ message: "Planned task must be a positive number" }) + .int() // Ensure it's an integer + .positive({ message: "Planned task must be a positive number" }) // Must be positive .max(maxPlanned, { + // Max value validation message: `Planned task cannot exceed ${maxPlanned}`, }) ), }); + // State for help popovers (though not fully implemented in provided snippets) const [isHelpVisibleTarget, setIsHelpVisibleTarget] = useState(false); const helpPopupRefTarget = useRef(null); - const [isHelpVisible, setIsHelpVisible] = useState(false); + // Refs for Bootstrap Popovers const infoRef = useRef(null); const infoRef1 = useRef(null); + // Initialize Bootstrap Popovers on component mount useEffect(() => { - - if (infoRef.current) { - new bootstrap.Popover(infoRef.current, { - trigger: 'focus', - placement: 'right', - html: true, - content: `
Pending Task assign for today
`, - }); + // Check if Bootstrap is available globally + 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."); } + }, []); // Empty dependency array ensures this runs once on mount - if (infoRef1.current) { - new bootstrap.Popover(infoRef1.current, { - trigger: 'focus', - placement: 'right', - html: true, - content: `
Target task for today
`, - }); - } - }, []); - - - const [plannedTask, setPlannedTask] = useState(); + // Redux state and hooks const selectedProject = useSelector( (store) => store.localVariables.projectId ); @@ -74,15 +81,15 @@ const AssignRoleModel = ({ assignData, onClose }) => { selectedProject, false ); - const dispatch = useDispatch(); - const { data, loading } = useMaster(); + const { loading } = useMaster(); // Assuming this is for jobRoleData loading const jobRoleData = getCachedData("Job Role"); + // Local component states const [selectedRole, setSelectedRole] = useState("all"); - const [selectedEmployees, setSelectedEmployees] = useState([]); - const [displayedSelection, setDisplayedSelection] = useState(""); + const [displayedSelection, setDisplayedSelection] = useState(""); // This state is not updated in the provided code, consider if it's still needed or how it should be updated + // React Hook Form setup const { handleSubmit, control, @@ -90,84 +97,90 @@ const AssignRoleModel = ({ assignData, onClose }) => { watch, formState: { errors }, reset, + trigger, // <--- IMPORTANT: Destructure 'trigger' here } = useForm({ defaultValues: { selectedEmployees: [], description: "", plannedTask: "", }, - resolver: zodResolver(schema), + resolver: zodResolver(schema), // Integrate Zod schema with react-hook-form }); + // Handler for employee checkbox changes const handleCheckboxChange = (event, user) => { const isChecked = event.target.checked; - let updatedSelectedEmployees = watch("selectedEmployees") || []; + let updatedSelectedEmployees = watch("selectedEmployees") || []; // Get current selected employees from form state if (isChecked) { + // Add employee if checked and not already in the list if (!updatedSelectedEmployees.includes(user.id)) { updatedSelectedEmployees = [...updatedSelectedEmployees, user.id]; } } else { + // Remove employee if unchecked updatedSelectedEmployees = updatedSelectedEmployees.filter( (id) => id !== user.id ); } - + // Update the form state with the new list of selected employees setValue("selectedEmployees", updatedSelectedEmployees); + trigger("selectedEmployees"); // <--- IMPORTANT: Trigger validation here }; + // Effect to dispatch action for Job Role master data useEffect(() => { dispatch(changeMaster("Job Role")); + // Cleanup function to reset selected role when component unmounts or dispatch changes return () => setSelectedRole("all"); }, [dispatch]); + // Handler for role filter change const handleRoleChange = (event) => { setSelectedRole(event.target.value); }; + // Filter employees based on selected role const filteredEmployees = selectedRole === "all" ? employees : employees?.filter( - (emp) => String(emp.jobRoleId || "") === selectedRole - ); + (emp) => String(emp.jobRoleId || "") === selectedRole + ); + // Form submission handler const onSubmit = async (data) => { const selectedEmployeeIds = data.selectedEmployees; + // Prepare taskTeam data (only IDs are needed for the backend based on previous context) const taskTeamWithDetails = selectedEmployeeIds .map((empId) => { - const employee = employees.find((e) => e.id === empId); - const jobRole = jobRoleData?.find((r) => r.id === employee?.jobRoleId); - return employee - ? employee.id - : null; + return empId; // Return just the ID as per previous discussions }) - .filter(Boolean); + .filter(Boolean); // Ensure no nulls if employee not found (though unlikely with current logic) + // Format data for API call const formattedData = { taskTeam: taskTeamWithDetails, plannedTask: data.plannedTask, description: data.description, - assignmentDate: new Date().toISOString(), + assignmentDate: new Date().toISOString(), // Current date/time workItemId: assignData?.workItem?.workItem.id, }; try { - let response = await TasksRepository.assignTask(formattedData); - showToast("Task Successfully Assigned", "success"); - reset(); - onClose(); + // Call API to assign task + await TasksRepository.assignTask(formattedData); + showToast("Task Successfully Assigned", "success"); // Show success toast + reset(); // Reset form fields + onClose(); // Close the modal } catch (error) { - console.log(error.response); - showToast("something wrong", "error"); + console.error("Error assigning task:", error); // Log the full error for debugging + showToast("Something went wrong. Please try again.", "error"); // Show generic error toast } }; - useEffect(() => { - dispatch(changeMaster("Job Role")); - return () => setSelectedRole("all"); - }, [dispatch]); + // Handler to close the modal and reset form const closedModel = () => { reset(); onClose(); @@ -200,7 +213,7 @@ const AssignRoleModel = ({ assignData, onClose }) => { assignData?.workItem?.workItem?.activityMaster ?.activityName, ] - .filter(Boolean) + .filter(Boolean) // Filter out any undefined/null values .map((item, index, array) => ( {item} @@ -232,7 +245,7 @@ const AssignRoleModel = ({ assignData, onClose }) => {