import React, { useState, useEffect, useRef, useCallback } from "react"; import { useDispatch, useSelector } from "react-redux"; import { changeMaster } from "../../slices/localVariablesSlice"; import useMaster, { useServices } from "../../hooks/masterHook/useMaster"; import { useForm, Controller } from "react-hook-form"; import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { useSelectedProject } from "../../slices/apiDataManager"; import { useEmployeesAllOrByProjectId } from "../../hooks/useEmployees"; import { TasksRepository } from "../../repositories/ProjectRepository"; import showToast from "../../services/toastService"; import { useEmployeeForTaskAssign, useProjectAssignedOrganizations, useProjectDetails, } from "../../hooks/useProjects"; import eventBus from "../../services/eventBus"; import { useCreateTask } from "../../hooks/useTasks"; import Label from "../common/Label"; const TaskSchema = (maxPlanned) => { return 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 AssignTask = ({ assignData, onClose, setAssigned }) => { const planned = assignData?.workItem?.plannedWork || 0; const completed = assignData?.workItem?.completedWork || 0; const maxPlanned = planned - completed; const [isHelpVisibleTarget, setIsHelpVisibleTarget] = useState(false); const helpPopupRefTarget = useRef(null); const [isHelpVisible, setIsHelpVisible] = useState(false); const [selectedService, setSelectedService] = useState(null); const [selectedOrganization, setSelectedOrganization] = useState(null); const { mutate: assignTask, isPending: isSubmitting } = useCreateTask({ onSuccessCallback: closedModel, }); const dropdownRef = useRef(null); const [open, setOpen] = useState(false); useEffect(() => { const handleClickOutside = (event) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { setOpen(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, []); const infoRef = useRef(null); const infoRef1 = useRef(null); const [searchTerm, setSearchTerm] = useState(""); useEffect(() => { if (typeof bootstrap !== "undefined") { infoRef.current && new bootstrap.Popover(infoRef.current, { trigger: "focus", placement: "right", html: true, content: `
Total Pending tasks of the Activity
`, }); 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 = useSelectedProject(); const { data: serviceList, isLoading: isServiceLoading } = useServices(); const { data: organizationList, isLoading: isOrgLoading } = useProjectAssignedOrganizations(selectedProject); const { data: employees, isLoading: isEmployeeLoading } = useEmployeeForTaskAssign( selectedProject, selectedService, selectedOrganization ); const dispatch = useDispatch(); const { loading, data: jobRoleData } = useMaster(); const [selectedRoles, setSelectedRoles] = useState(["all"]); const [displayedSelection, setDisplayedSelection] = useState(""); const { handleSubmit, control, setValue, watch, formState: { errors }, reset, trigger, } = useForm({ defaultValues: { selectedEmployees: [], description: "", plannedTask: "" }, resolver: zodResolver(TaskSchema(maxPlanned)), }); const handleCheckboxChange = (event, user) => { const updatedSelectedEmployees = event.target.checked ? [...(watch("selectedEmployees") || []), user.id].filter( (v, i, a) => a.indexOf(v) === i ) : (watch("selectedEmployees") || []).filter((id) => id !== user.id); setValue("selectedEmployees", updatedSelectedEmployees); trigger("selectedEmployees"); }; useEffect(() => { dispatch(changeMaster("Job Role")); setSelectedRoles(["all"]); }, [dispatch]); const handleRoleChange = (event, roleId) => { setSelectedRoles((prev) => { if (roleId === "all") return ["all"]; const newRoles = prev.filter((r) => r !== "all"); return newRoles.includes(roleId) ? newRoles.filter((r) => r !== roleId) : [...newRoles, roleId]; }); }; useEffect(() => { if (selectedRoles.includes("all")) { setDisplayedSelection("All Roles"); } else if (selectedRoles.length > 0) { setDisplayedSelection( selectedRoles .map((id) => jobRoleData?.find((r) => String(r.id) === id)?.name) .filter(Boolean) .join(", ") ); } else setDisplayedSelection("Select Roles"); }, [selectedRoles, jobRoleData]); const handleSearchChange = (e) => setSearchTerm(e.target.value); const filteredEmployees = employees?.data?.filter((emp) => { const matchesRole = selectedRoles.includes("all") || selectedRoles.includes(String(emp.jobRoleId)); const searchLower = searchTerm.toLowerCase(); const fullName = `${emp.firstName} ${emp.lastName}`.toLowerCase(); const jobRoleName = jobRoleData ?.find((role) => role.id === emp.jobRoleId) ?.name?.toLowerCase() || ""; return ( matchesRole && (fullName.includes(searchLower) || jobRoleName.includes(searchLower)) ); }); const jobRolesForDropdown = jobRoleData?.filter((role) => new Set(employees?.data?.map((emp) => emp.jobRoleId).filter(Boolean)).has( role.id ) ); const selectedRolesCount = selectedRoles.includes("all") ? 0 : selectedRoles.length; const onSubmit = (data) => { assignTask({ payload: { taskTeam: data.selectedEmployees.filter(Boolean), plannedTask: data.plannedTask, description: data.description, assignmentDate: new Date().toISOString(), workItemId: assignData?.workItem.id, }, workAreaId: assignData?.workArea?.id, }); }; function closedModel() { reset(); onClose(); } return (

Assign Task

Work Location : {[ assignData?.building?.buildingName, assignData?.floor?.floorName, assignData?.workArea?.areaName, assignData?.workItem?.activityMaster?.activityName, ] .filter(Boolean) .map((item, index, array) => ( {item} {index < array.length - 1 && ( )} ))}

{/* Dropdown */}
setOpen(!open)} > {/* Badge */} {selectedRolesCount > 0 && ( {selectedRolesCount} )} {/* Dropdown Menu */} {open && (
    {/* All Roles */}
  • handleRoleChange(e, e.target.value) } />
  • {/* Dynamic Roles */} {jobRolesForDropdown?.map((role) => (
  • handleRoleChange(e, e.target.value) } />
  • ))}
)}
{/* Search Box */}
{/* Employees list */}
{selectedRoles?.length > 0 && (
{isEmployeeLoading ? (

Loading employees...

) : filteredEmployees?.length > 0 ? ( filteredEmployees.map((emp,index) => { 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 filter.

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

{ const updatedSelected = watch( "selectedEmployees" ).filter((id) => id !== empId); setValue( "selectedEmployees", updatedSelected ); trigger("selectedEmployees"); }} >

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

{errors.selectedEmployees.message}

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