import React, { useEffect, useRef, useState } from "react"; import { HexColorPicker } from "react-colorful"; import { useDispatch, useSelector } from "react-redux"; import { Link, useParams } from "react-router-dom"; import { activeLoader, addNewTagToProject, deleteTagProject, filterCreatedByMe, filteredExecutorTasks, filteredParticipateTasks, getBoarderLoader, getProjectBoard, modalToggle, movePositionProjectTask, moveProjectTask, setColumnId, setColumnName, setColumnPriority, setProjectBoardFetch, setToggleTab } from "@redux/projectsTrackerSlice"; import { urlForLocal } from "@utils/helper"; import { caseOfNum } from "@utils/helper"; import { apiRequest } from "@api/request"; import { useNotification } from "@hooks/useNotification"; import BaseButton from "@components/Common/BaseButton/BaseButton"; import { Footer } from "@components/Common/Footer/Footer"; import { Loader } from "@components/Common/Loader/Loader"; import AcceptModal from "@components/Modal/AcceptModal/AcceptModal"; import ListEmployees from "@components/Modal/Tracker/ListEmployees/ListEmployees"; import ModalTicket from "@components/Modal/Tracker/ModalTicket/ModalTicket"; import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal"; import { Navigation } from "@components/Navigation/Navigation"; import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs"; import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader"; import TrackerSelectColumn from "@components/TrackerSelectColumn/TrackerSelectColumn"; import arrow from "assets/icons/arrows/arrowCalendar.png"; import arrowDown from "assets/icons/arrows/selectArrow.png"; import close from "assets/icons/close.png"; import commentsBoard from "assets/icons/commentsBoard.svg"; import del from "assets/icons/delete.svg"; import edit from "assets/icons/edit.svg"; import filesBoard from "assets/icons/filesBoard.svg"; import trackerNoTasks from "assets/icons/trackerNoTasks.svg"; import project from "assets/icons/trackerProject.svg"; import tasks from "assets/icons/trackerTasks.svg"; import accept from "assets/images/accept.png"; import archive from "assets/images/archiveIcon.png"; import avatarMok from "assets/images/avatarMok.png"; import { getCorrectDate } from "../../components/Calendar/calendarHelper"; export const ProjectTracker = () => { const dispatch = useDispatch(); const projectId = useParams(); const [openColumnSelect, setOpenColumnSelect] = useState({}); const [selectedTab, setSelectedTab] = useState(0); const [priorityTask, setPriorityTask] = useState(0); const [wrapperHover, setWrapperHover] = useState({}); const [taskHover, setTaskHover] = useState({}); const [modalAdd, setModalAdd] = useState(false); const [modalActiveTicket, setModalActiveTicket] = useState(false); const [selectedTicket, setSelectedTicket] = useState({}); const [personListOpen, setPersonListOpen] = useState(false); const [tags, setTags] = useState({ open: false, add: false, edit: false }); const [acceptModalOpen, setAcceptModalOpen] = useState(false); const [currentColumnDelete, setCurrentColumnDelete] = useState(null); const [color, setColor] = useState("#aabbcc"); const [tagInfo, setTagInfo] = useState({ description: "", name: "" }); const [checkBoxParticipateTasks, setCheckBoxParticipateTasks] = useState(false); const [filteredNoTasks, setFilteredNoTasks] = useState(false); const [checkBoxMyTasks, setCheckBoxMyTasks] = useState(false); const [selectedExecutor, setSelectedExecutor] = useState(null); const [selectExecutorOpen, setSelectedExecutorOpen] = useState(false); const startWrapperIndexTest = useRef({}); const projectBoard = useSelector(getProjectBoard); const loader = useSelector(getBoarderLoader); const { showNotification } = useNotification(); const priority = { 2: "Высокий", 1: "Средний", 0: "Низкий" }; const priorityClass = { 2: "high", 1: "middle", 0: "low" }; useEffect(() => { dispatch(activeLoader()); dispatch(setProjectBoardFetch(projectId.id)); initListeners(); }, []); useEffect(() => { const tasksHover = {}; const columnHover = {}; let columnsTasksEmpty = true; if (Object.keys(projectBoard).length) { projectBoard.columns.forEach((column) => { if (column.tasks.length) columnsTasksEmpty = false; setOpenColumnSelect((prevState) => ({ ...prevState, [column.id]: false })); columnHover[column.id] = false; column.tasks.forEach((task) => (tasksHover[task.id] = false)); }); } if ( columnsTasksEmpty && (checkBoxMyTasks || selectedExecutor || checkBoxParticipateTasks) ) { setFilteredNoTasks(true); } else { setFilteredNoTasks(false); } setWrapperHover(columnHover); setTaskHover(tasksHover); }, [projectBoard]); function dragStartHandler(e, task, columnId) { startWrapperIndexTest.current = { task: task, index: columnId }; } function dragOverTaskHandler(e, task) { e.preventDefault(); if (startWrapperIndexTest.current.task.id === task.id) { return; } setTaskHover((prevState) => ({ [prevState]: false, [task.id]: true })); } function dragLeaveTaskHandler() { setTaskHover((prevState) => ({ [prevState]: false })); } function dragEndTaskHandler() { setTaskHover((prevState) => ({ [prevState]: false })); setWrapperHover((prevState) => ({ [prevState]: false })); } function dragDropTaskHandler(e, task, column) { e.preventDefault(); if (task.id === startWrapperIndexTest.current.task.id) { return; } const finishTask = column.tasks.indexOf(task); dispatch( movePositionProjectTask({ startTask: startWrapperIndexTest.current.task, finishTask: task, finishIndex: finishTask }) ); } function dragOverHandler(e) { e.preventDefault(); } function dragEnterHandler(columnId) { if (columnId === startWrapperIndexTest.current.index) { return; } setWrapperHover((prevState) => ({ [prevState]: false, [columnId]: true })); } function dragDropHandler(e, columnId) { e.preventDefault(); setWrapperHover((prevState) => ({ [prevState]: false })); if ( startWrapperIndexTest.current.index === columnId || e.target.className.includes("__item") ) { return; } if (columnId !== startWrapperIndexTest.current.index) { dispatch( moveProjectTask({ startWrapperIndex: startWrapperIndexTest.current, columnId }) ); } } function selectedTabTask(columnId, length) { setSelectedTab(columnId); dispatch(modalToggle("create-ticket-project")); setModalAdd(true); setPriorityTask(length); } function openTicket(e, task) { if (window.innerWidth < 985) { return; } setSelectedTicket(task); setModalActiveTicket(true); } function deleteColumn(column) { const priorityColumns = []; apiRequest("/project-column/update-column", { method: "PUT", data: { column_id: column.id, project_id: projectBoard.id, status: 0 } }).then(() => { if (column.priority < projectBoard.columns.length) { for (let i = column.priority; i < projectBoard.columns.length; i++) { const currentColumn = { column_id: projectBoard.columns[i].id, priority: i }; priorityColumns.push(currentColumn); } apiRequest("/project-column/set-priority", { method: "POST", data: { project_id: projectBoard.id, data: JSON.stringify(priorityColumns) } }).then(() => { dispatch(setProjectBoardFetch(projectBoard.id)); }); } else { dispatch(setProjectBoardFetch(projectBoard.id)); } showNotification({ show: true, text: "Колонка удалена", type: "error" }); }); } function filterParticipateTasks() { if (!checkBoxParticipateTasks) { dispatch(filteredParticipateTasks(Number(localStorage.getItem("id")))); } else { dispatch(setProjectBoardFetch(projectId.id)); setCheckBoxParticipateTasks(false); setCheckBoxMyTasks(false); setSelectedExecutor(null); } setCheckBoxParticipateTasks(!checkBoxParticipateTasks); } function filterMyTask() { if (!checkBoxMyTasks) { dispatch(filterCreatedByMe(Number(localStorage.getItem("id")))); } else { dispatch(setProjectBoardFetch(projectId.id)); setCheckBoxParticipateTasks(false); setCheckBoxMyTasks(false); setSelectedExecutor(null); } setCheckBoxMyTasks(!checkBoxMyTasks); } function executorFilter(user) { dispatch(filteredExecutorTasks(user.user_id)); setSelectedExecutor(user); } function deleteSelectedExecutorFilter() { setSelectedExecutor(null); setCheckBoxParticipateTasks(false); setCheckBoxMyTasks(false); dispatch(setProjectBoardFetch(projectId.id)); } function addNewTag() { apiRequest("/mark/create", { method: "POST", data: { title: tagInfo.description, slug: tagInfo.name, color: color, status: 1 } }).then((data) => { apiRequest("/mark/attach", { method: "POST", data: { mark_id: data.id, entity_type: 1, entity_id: projectId.id } }).then((data) => { dispatch(addNewTagToProject(data.mark)); setTags((prevState) => ({ ...prevState, add: false })); }); }); } function editTag() { apiRequest("/mark/update", { method: "PUT", data: { mark_id: tagInfo.editMarkId, title: tagInfo.description, slug: tagInfo.name, color: color } }).then(() => { dispatch(setProjectBoardFetch(projectId.id)); setTags((prevState) => ({ ...prevState, edit: false })); setTagInfo({ description: "", name: "" }); setColor("#aabbcc"); }); } function deleteTag(tagId) { apiRequest("/mark/detach", { method: "DELETE", data: { mark_id: tagId, entity_type: 1, entity_id: projectId.id } }).then(() => { dispatch(deleteTagProject(tagId)); }); } const initListeners = () => { document.addEventListener("click", closeByClickingOut); }; const closeByClickingOut = (event) => { const path = event.path || (event.composedPath && event.composedPath()); if ( event && !path.find( (div) => div.classList && (div.classList.contains("add-person") || div.classList.contains("persons__list")) ) ) { setPersonListOpen(false); } if ( event && !path.find( (div) => div.classList && (div.classList.contains("tasks__head__executor") || div.classList.contains("tasks__head__executorDropdown")) ) ) { setSelectedExecutorOpen(false); } if ( event && !path.find( (div) => div.classList && (div.classList.contains("tasks__head__tags") || div.classList.contains("tags__list")) ) ) { setTags({ open: false, add: false, edit: false }); setTagInfo({ description: "", name: "" }); setColor("#aabbcc"); } if ( event && !path.find( (div) => div.classList && (div.classList.contains("board__head__more") || div.classList.contains("column__select")) ) ) { setOpenColumnSelect((prevState) => { const newState = {}; for (const key in prevState) { newState[key] = false; } return newState; }); } }; function closeAcceptModal() { setAcceptModalOpen(false); } return (
Проекты
dispatch(setToggleTab(2))} >Все мои задачи
dispatch(setToggleTab(3))} >Архив
добавить колонку
добавить участника
{selectedExecutor.user.fio}
Выберите исполнителя
{selectExecutorOpen && ({user.user?.fio}
Список тегов
+Добавить новый тег
+{tag.title}
К списку проектов
{task.title}
{tag.slug}
Приоритет:
{priority[task.execution_priority]}Срок исполнения:
{getCorrectDate(task.dead_line)}Пока нет подходящих задач
Ставьте задачи, следите за прогрессом, ведите учёт рабочего времени