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 && (
)}
))}
);
};
export default AssignTask;