Duffer Derek

Current Path : /var/www/api-mk-planner.bitkit.dk/httpdocs/Frontend/src/hooks/
Upload File :
Current File : /var/www/api-mk-planner.bitkit.dk/httpdocs/Frontend/src/hooks/useMainTaskView.js

import * as dateFns from "date-fns";
import { format } from "date-fns";
import { useEffect, useState } from "react";
import { toast } from "react-toastify";
import { showToast } from "../components/atom/toaster/toaster";
import { updateOrAddTasks } from "../utils/commonFunctions";
import { useAuthContext } from "./useAuthContext";
import { useDataContext } from "./useDataContext";

const unAssignedPartner = {
  id: null,
  name: "Make Unassigned",
  type: null,
  email: null,
  phone: null,
  firstname: null,
  lastname: null,
};

/**
 * Format subtask data, modifying it to include shared data if applicable.
 * @param {Array} subTasks
 * @returns {Array}
 */
const formatSubTaskData = (subTasks) => {
  let formattedData = subTasks;
  let sharedData = [];
  subTasks.forEach((subTask) => {
    // Check if the subtask has shared_time (indicating it's shared) or if it's marked for deletion
    if (
      (subTask?.shared_time && subTask?.shared_time !== "0") ||
      (subTask?.shared_time == null && subTask.delete == true)
    ) {
      sharedData = {
        date: subTask?.date,
        notes: subTask?.notes,
        time: subTask?.shared_time,
        user_id: subTask?.user?.id,
        shared: 1,
      };
      // If the subtask is marked for deletion, set the delete flag in sharedData
      if (subTask.delete == true) {
        sharedData.delete = true;
      }

      formattedData.push(sharedData);
    }
  });
  return formattedData;
};

const useMainTaskView = () => {
  const [subTasks, setSubTasks] = useState([]);
  const { taskDetails, filterOptions, filters, dispatch } = useDataContext();
  const [taskPartner, setTaskPartner] = useState();
  const [startDate, setStartDate] = useState();
  const [endDate, setEndDate] = useState();
  const { access_token } = useAuthContext();
  const [errorDate, setErrorDate] = useState({
    date: "",
    message: "",
    key: "",
  });

  const taskPartnerOptions = [
    ...(filterOptions?.partners || []),
    unAssignedPartner,
  ];

  /**
   * Handle changes to a subtask field.
   * Updates the specified subtask with the new value for the specified key.
   * @param {any} value
   * @param {string} key
   * @param {string} date
   */
  const handleSubTaskFieldChange = (value, key, date) => {
    // Find the index of the subtask with the specified date
    const index = subTasks.findIndex((sub) => sub.date === date);
    // Find the subtask object with the specified date
    const subTask = subTasks.find((sub) => sub.date === date);
    // Create a new subtask object with the updated field value
    const updatedSubTask = { ...subTask, [key]: value };
    // If the subtask is marked for deletion, reset shared_time and user fields
    if (updatedSubTask.delete == true) {
      updatedSubTask.shared_time = null;
      updatedSubTask.user = null;
    }
    // If notes field is undefined, set it to an empty string for adding subtask without notes
    if (updatedSubTask.notes === undefined) {
      updatedSubTask.notes = "";
    }
    let updatedSubTasks = [...subTasks];
    updatedSubTasks[index] = updatedSubTask;
    setSubTasks(updatedSubTasks);
  };

  /**
   * Set data for a single task, including user details if provided.
   * @param {Object} Task
   * @param {Object} user
   */
  const setSingleTaskData = (task, user = {}) => {
    const userDetails = {
      id: user.userId,
      name: user.username,
      phone: user.phone,
      email: user.email,
      type: user.type,
      firstname: user.firstname,
      lastname: user.lastname,
    };
    const updatedTask = {
      ...task,
      user: userDetails,
    };
    // setting updatedTask into datacontext
    dispatch({
      type: "SINGLE_TASK",
      payload: updatedTask,
    });
  };

  useEffect(() => {
    if (taskDetails?.user) {
      setTaskPartner(taskDetails?.user);
      setStartDate(new Date(taskDetails?.startDate));
      setEndDate(new Date(taskDetails?.endDate));
    }
    if (taskDetails) {
      generateSubTasks(taskDetails);
    }
  }, [taskDetails]);

  /**
   * Generate subtasks for all dates between start and end date of a task.
   * If subtasks are already provided and the task is shared, use the provided subtasks.
   * If subtasks are not provided or the task is not shared, generate subtasks for each date.
   * @param {*} taskDetails
   */
  const generateSubTasks = (taskDetails) => {
    // Extracting necessary details from the taskDetails
    const startDate = taskDetails.startDate;
    const endDate = taskDetails.endDate;
    const subTasks = taskDetails.subtasks || [];
    let list = [];
    // Checking if the task is shared and if subtasks are already provided
    if (taskDetails?.shared && subTasks.length > 0) {
      // If shared and subtasks are provided, directly add them to the list

      list.push(...subTasks);
    } else {
      let start = new Date(startDate);
      do {
        const dayOfWeek = start.getDay();

        const date = start.toDateString();
        const user_id = taskDetails?.user?.id ? taskDetails?.user?.id : null;
        // Filtering subtasks that match the current date
        const matchingSubTasks = subTasks.filter(
          (subTask) => subTask.date === date
        );
        // If matching subtasks are found, add them to the list
        if (matchingSubTasks.length > 0) {
          list.push(...matchingSubTasks);
        } else {
          list.push({
            date,
            user_id,
          });
        }

        start = dateFns.addDays(start, 1);
      } while (
        // Continue loop until start date is before the end date  or start date is the same as the end date
        dateFns.isBefore(start, new Date(endDate)) ||
        dateFns.isSameDay(start, new Date(endDate))
      );
    }

    setSubTasks(list);
  };

  /**
   * Handle change in task partner dropdown selection.
   * Updates the taskDetails based on the selected value.
   * @param {Object} value
   */
  const handleTaskPartnerDropdownChange = (value) => {
    const updatedTask = {
      ...taskDetails,
    };
    //if user select unassigned then color should be "#d3d3d3"
    if (value.id == null) {
      updatedTask.unassigned = true;
      updatedTask.user = unAssignedPartner;
      updatedTask.country_side_color = "#d3d3d3";
    } else {
      // Find the color corresponding to the selected countryside
      const color = filterOptions.lansdel.find(
        (category) => category.name === updatedTask.countryside
      )?.color;

      updatedTask.unassigned = false;
      updatedTask.user = value;
      updatedTask.country_side_color = color;
    }
    // set updatedTask into datacontext
    dispatch({
      type: "SINGLE_TASK",
      payload: updatedTask,
    });
  };

  /**
   * Save the data of the task and its subtasks.
   * Shows confirmation messages if necessary.
   * @param {function} setShowContent
   * @param {function} closePopupBodyClick
   */
  const saveData = async (setShowContent, closePopupBodyClick) => {
    if (taskDetails.unassigned == true) {
      // Show a confirmation message if the task is unassigned
      const message =
        "Now the task is unassigned, so if any subtask is created for this task, all will be deleted. Click 'OK' to confirm";
      toastMessage(message, setShowContent, closePopupBodyClick);
    } else {
      // Check for validation errors before saving
      const hasError = checkValidation();
      if (hasError) return;
      const showToastMessage = subTasks?.some((subTask) => {
        if (!subTask.id || !subTask.date) return false;
       
        const subTaskDate = new Date(subTask.date);
        return subTaskDate < startDate || subTaskDate > endDate;
      }) || false;
      // show toast message before save data
      if (showToastMessage) {
        const message =
          "The changed date is not matching with its subtask do you want to delete that subtask and update the task";
        toastMessage(message, setShowContent, closePopupBodyClick);
      } else {
        // If no toast message needs to be shown, update task and subtasks
        upadteTaskAndSubTask(setShowContent, closePopupBodyClick);
      }
    }
    dispatch({
      type: "POP_UP_STATUS",
      payload: false,
    });
  };

  /**
   * Check validation for subtasks.
   * @returns {boolean}
   */
  const checkValidation = () => {
    let hasError = false;
    subTasks.forEach((subTask) => {
      const isNotesEmpty = subTask.notes === undefined;
      const isTimeEmpty =
        subTask.time === undefined ||
        subTask.time == "" ||
        subTask.time == "00:00";
      const isPartnerEmpty =
        subTask.user == undefined ||
        subTask.user.name == null ||
        subTask.user == null;
      const isSharedTimeEmpty =
        subTask.shared_time == undefined ||
        subTask.shared_time == null ||
        subTask.shared_time == "00:00";
      // If notes and time are not both empty or both filled, set error and flag hasError
      if ((!isNotesEmpty && isTimeEmpty) || (!isTimeEmpty && isNotesEmpty)) {
        setErrorDate({
          date: subTask.date,
          message: "Time not be empty",
          key: "notes",
        });
        hasError = true;
        return hasError;
      } else {
        // If both partner and shared time should have values but one of them is missing, set error
        if (
          (!isPartnerEmpty && isSharedTimeEmpty) ||
          (isPartnerEmpty && !isSharedTimeEmpty)
        ) {
          setErrorDate({
            date: subTask.date,
            message: "Both shared partner and shared time should have values",
            key: "shared",
          });
          hasError = true;
          return hasError;
        }
        // If both notes and time are empty but partner and shared time are filled, set error and flag hasError
        if (
          isNotesEmpty &&
          isTimeEmpty &&
          !isPartnerEmpty &&
          !isSharedTimeEmpty
        ) {
          setErrorDate({
            date: subTask.date,
            message: "please fill Subtask time before sharing subtask ",
            key: "notes",
          });
          hasError = true;
          return hasError;
        }
      }
    });
    return hasError;
  };
  const toastMessage = (message, setShowContent, closePopupBodyClick) => {
    const toastId = showToast(
      "ok",
      message,
      {
        autoClose: 3000,
        position: "top-center",
      },
      0,
      () => {
        upadteTaskAndSubTask(setShowContent, closePopupBodyClick);
        toast.dismiss(toastId);
      },
      () => toast.dismiss(toastId)
    );
  };

  /**
   * Update task and its subtasks.
   * @param {function} setShowContent
   * @param {function} closePopupBodyClick
   */
  const upadteTaskAndSubTask = async (setShowContent, closePopupBodyClick) => {
    // Hide content
    setShowContent(false);

    let finalSubTaskData = {
      tasks: {
        data: [],
        item_id: taskDetails?.item_id,
      },
    };

    let taskData = {
      item_id: taskDetails?.item_id,
      start_date: format(startDate, "yyyy-MM-dd"),
      end_date: format(endDate, "yyyy-MM-dd"),
      user_id: taskPartner?.id,
      country_side_color: taskDetails?.country_side_color,
    };
    if (taskDetails.unassigned !== true) {
      // Filter out subtasks without time, convert date to appropriate format and add user_id and shared fields
      let formattedSubTasks = subTasks
        .filter((subTask) => subTask?.time)
        .map((subTask) => ({
          ...subTask,
          date: new Date(format(subTask?.date, "yyyy-MM-dd")),
          user_id: taskPartner?.id,
          shared: 0,
        }));
      const includeSharedSubTask = formatSubTaskData(formattedSubTasks);

      finalSubTaskData.tasks.data = [
        ...finalSubTaskData.tasks.data,
        ...includeSharedSubTask,
      ];
    } else {
      taskData.unassigned = true;
    }
    const finalData = {
      sub_tasks: finalSubTaskData,
      task_data: taskData,
      filter: filters,
    };
    // Update or add tasks using finalData and access token
    const response = await updateOrAddTasks(finalData, access_token);
    // Set response data
    setData(response);
    // Close popup
    closePopupBodyClick();
    // Show content
    setShowContent(true);
  };

  /**
   * Set response data to data context
   * @param {*} response
   */
  const setData = (response) => {
    dispatch({
      type: "DATA",
      payload: response?.data?.tasks?.assigned,
    });

    dispatch({
      type: "UNASSIGNED_TASK",
      payload: response?.data?.tasks?.unassigned,
    });
  };

  const openMainTask = () => {
    document.body.style.overflow = "hidden";
    dispatch({
      type: "POP_UP_STATUS",
      payload: true,
    });
  };

  const closeMainTask = () => {
    setErrorDate({
      date: "",
      message: "",
      key: "",
    });
    document.body.style.overflow = "visible";
    dispatch({
      type: "POP_UP_STATUS",
      payload: false,
    });
  };

  return {
    setSingleTaskData,
    taskDetails,
    filterOptions,
    startDate,
    endDate,
    taskPartner,
    saveData,
    subTasks,
    setSubTasks,
    setTaskPartner,
    taskPartner,
    startDate,
    setStartDate,
    endDate,
    setEndDate,
    handleSubTaskFieldChange,
    errorDate,
    taskPartnerOptions,
    handleTaskPartnerDropdownChange,
    openMainTask,
    closeMainTask,
  };
};

export default useMainTaskView;

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists