diff --git a/src/components/Project/AssignTask.jsx b/src/components/Project/AssignTask.jsx
new file mode 100644
index 00000000..797560cc
--- /dev/null
+++ b/src/components/Project/AssignTask.jsx
@@ -0,0 +1,574 @@
+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 { 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";
+
+const AssignTask = ({ assignData, onClose, setAssigned }) => {
+ 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);
+
+ // Refs for Bootstrap Popovers
+ const infoRef = useRef(null);
+ const infoRef1 = useRef(null);
+
+ // Initialize Bootstrap Popovers on component mount
+ useEffect(() => {
+ // 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
+ // Redux state and hooks
+ const selectedProject = useSelector(
+ (store) => store.localVariables.projectId
+ );
+ const { employees, loading: employeeLoading } = useEmployeesAllOrByProjectId(
+ selectedProject,
+ false
+ );
+ const dispatch = useDispatch();
+ const { loading } = useMaster(); // Assuming this is for jobRoleData loading
+ const jobRoleData = getCachedData("Job Role");
+
+ // Local component states
+ const [selectedRole, setSelectedRole] = useState("all");
+ 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,
+ setValue,
+ watch,
+ formState: { errors },
+ reset,
+ trigger, // <--- IMPORTANT: Destructure 'trigger' here
+ } = useForm({
+ defaultValues: {
+ selectedEmployees: [],
+ description: "",
+ plannedTask: "",
+ },
+ 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") || []; // 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
+ );
+
+ // 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) => {
+ return empId; // Return just the ID as per previous discussions
+ })
+ .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(), // Current date/time
+ workItemId: assignData?.workItem?.workItem.id,
+ };
+
+ try {
+ // Call API to assign task
+ // Close the modal
+ } catch (error) {
+ console.error("Error assigning task:", error);
+ showToast("Something went wrong. Please try again.", "error");
+ }
+ };
+
+ // Handler to close the modal and reset form
+ const closedModel = () => {
+ reset();
+ onClose();
+ };
+ return (
+
+
+
Assign 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 && (
+
+ )}
+
+ ))}
+
+
+
+
+
+
+
+
+ );
+};
+
+export default AssignTask;