import React, { useState, useEffect, useRef, useCallback } 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 { zodResolver } from "@hookform/resolvers/zod"; import { clearCacheKey, getCachedData } from "../../slices/apiDataManager"; import { useEmployeesAllOrByProjectId } from "../../hooks/useEmployees"; import { TasksRepository } from "../../repositories/ProjectRepository"; import showToast from "../../services/toastService"; import { useProjectDetails } from "../../hooks/useProjects"; import eventBus from "../../services/eventBus"; import { useCreateTask } from "../../hooks/useTasks"; const AssignTask = ({ assignData, onClose, setAssigned }) => { const maxPlanned = assignData?.workItem?.plannedWork - assignData?.workItem?.completedWork; 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 { mutate: assignTask, isPending: isSubmitting } = useCreateTask({ onSuccessCallback: () => { closedModel(); }, }); const infoRef = useRef(null); const infoRef1 = useRef(null); // State for search term const [searchTerm, setSearchTerm] = useState(""); 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, recallEmployeeData, } = useEmployeesAllOrByProjectId(false, selectedProject, false); const dispatch = useDispatch(); const { loading } = useMaster(); const { data: jobRoleData } = useMaster(); // Changed to an array to hold multiple selected roles 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(schema), }); const handleCheckboxChange = (event, user) => { const isChecked = event.target.checked; let updatedSelectedEmployees = watch("selectedEmployees") || []; if (isChecked) { if (!updatedSelectedEmployees.includes(user.id)) { updatedSelectedEmployees = [...updatedSelectedEmployees, user.id]; } } else { updatedSelectedEmployees = updatedSelectedEmployees?.filter( (id) => id !== user.id ); } setValue("selectedEmployees", updatedSelectedEmployees); trigger("selectedEmployees"); }; useEffect(() => { dispatch(changeMaster("Job Role")); // Initial state should reflect "All Roles" selected setSelectedRoles(["all"]); }, [dispatch]); // Modified handleRoleChange to handle multiple selections const handleRoleChange = (event, roleId) => { // If 'all' is selected, clear other selections if (roleId === "all") { setSelectedRoles(["all"]); } else { setSelectedRoles((prevSelectedRoles) => { // If "all" was previously selected, remove it const newRoles = prevSelectedRoles.filter((role) => role !== "all"); if (newRoles.includes(roleId)) { // If role is already selected, unselect it return newRoles.filter((id) => id !== roleId); } else { // If role is not selected, add it return [...newRoles, roleId]; } }); } }; useEffect(() => { // Update displayedSelection based on selectedRoles if (selectedRoles.includes("all")) { setDisplayedSelection("All Roles"); } else if (selectedRoles.length > 0) { const selectedRoleNames = selectedRoles.map(roleId => { const role = jobRoleData?.find(r => String(r.id) === roleId); return role ? role.name : ''; }).filter(Boolean); // Filter out empty strings for roles not found setDisplayedSelection(selectedRoleNames.join(', ')); } else { setDisplayedSelection("Select Roles"); } }, [selectedRoles, jobRoleData]); const handleSearchChange = (event) => { setSearchTerm(event.target.value); }; // Filter employees first by role, then by search term AND job role name const filteredEmployees = employees?.filter((emp) => { const matchesRole = selectedRoles.includes("all") || selectedRoles.includes(String(emp.jobRoleId)); // Convert both first and last names and job role name to lowercase for case-insensitive matching const fullName = `${emp.firstName} ${emp.lastName}`.toLowerCase(); const jobRoleName = jobRoleData?.find((role) => role.id === emp.jobRoleId)?.name?.toLowerCase() || ""; const searchLower = searchTerm.toLowerCase(); // Check if the full name OR job role name includes the search term const matchesSearch = fullName.includes(searchLower) || jobRoleName.includes(searchLower); return matchesRole && matchesSearch; }); // Determine unique job role IDs from the filtered employees (for dropdown options) const uniqueJobRoleIdsInFilteredEmployees = new Set( employees?.map(emp => emp.jobRoleId).filter(Boolean) ); // Filter jobRoleData to only include roles present in the uniqueJobRoleIdsInFilteredEmployees const jobRolesForDropdown = jobRoleData?.filter(role => uniqueJobRoleIdsInFilteredEmployees.has(role.id) ); // Calculate the count of selected roles for display const selectedRolesCount = selectedRoles.includes("all") ? 0 // "All Roles" doesn't contribute to a specific count : selectedRoles.length; const onSubmit = (data) => { const selectedEmployeeIds = data.selectedEmployees; const taskTeamWithDetails = selectedEmployeeIds ?.map((empId) => empId) ?.filter(Boolean); const formattedData = { taskTeam: taskTeamWithDetails, plannedTask: data.plannedTask, description: data.description, assignmentDate: new Date().toISOString(), workItemId: assignData?.workItem.id, }; assignTask({ payload: formattedData, workAreaId: assignData?.workArea?.id, }); }; const closedModel = () => { reset(); onClose(); }; return (

Assign Task

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

Select Team {/* Dropdown */}
{/* Badge */} {selectedRolesCount > 0 && ( {selectedRolesCount} )} {/* Dropdown Menu with Scroll */}
    {/* All Roles */}
  • handleRoleChange(e, e.target.value) } />
  • {/* Dynamic Roles */} {jobRolesForDropdown?.map((role) => (
  • handleRoleChange(e, e.target.value) } />
  • ))}
{/* Search Box */}
{/* Employees list */}
{selectedRoles?.length > 0 && (
{employeeLoading ? (

Loading employees...

) : 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"); }} >

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

{errors.selectedEmployees.message}

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