Merge branch 'main' into tracker-connect-back
# Conflicts: # src/components/Modal/TrackerModal/trackerModal.scss # src/components/UI/ModalTicket/ModalTicket.jsx
This commit is contained in:
		@@ -2,4 +2,4 @@
 | 
			
		||||
. "$(dirname -- "$0")/_/husky.sh"
 | 
			
		||||
 | 
			
		||||
npm run format
 | 
			
		||||
npm run lint
 | 
			
		||||
#npm run lint
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										629
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										629
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										10
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								package.json
									
									
									
									
									
								
							@@ -7,8 +7,6 @@
 | 
			
		||||
    "@testing-library/jest-dom": "^5.12.0",
 | 
			
		||||
    "@testing-library/react": "^11.2.7",
 | 
			
		||||
    "@testing-library/user-event": "^12.8.3",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^4.5.0",
 | 
			
		||||
    "@typescript-eslint/parser": "^4.5.0",
 | 
			
		||||
    "axios": "^0.24.0",
 | 
			
		||||
    "babel": "^6.23.0",
 | 
			
		||||
    "bfj": "^7.0.2",
 | 
			
		||||
@@ -50,14 +48,17 @@
 | 
			
		||||
    "@babel/preset-env": "^7.20.2",
 | 
			
		||||
    "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
 | 
			
		||||
    "@trivago/prettier-plugin-sort-imports": "^4.1.1",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^5.60.0",
 | 
			
		||||
    "@typescript-eslint/parser": "^5.60.0",
 | 
			
		||||
    "babel-loader": "^9.1.2",
 | 
			
		||||
    "copy-webpack-plugin": "^10.2.0",
 | 
			
		||||
    "cross-env": "^7.0.3",
 | 
			
		||||
    "css-loader": "6.7.3",
 | 
			
		||||
    "dotenv-webpack": "^7.0.3",
 | 
			
		||||
    "eslint": "^8.41.0",
 | 
			
		||||
    "eslint": "^8.43.0",
 | 
			
		||||
    "eslint-plugin-react": "^7.32.2",
 | 
			
		||||
    "html-webpack-plugin": "5.5.0",
 | 
			
		||||
    "husky": "^8.0.0",
 | 
			
		||||
    "mini-css-extract-plugin": "^2.7.2",
 | 
			
		||||
    "node-sass": "8.0.0",
 | 
			
		||||
    "postcss": "^8.4.21",
 | 
			
		||||
@@ -74,8 +75,7 @@
 | 
			
		||||
    "webpack-bundle-analyzer": "4.7.0",
 | 
			
		||||
    "webpack-cli": "^5.0.1",
 | 
			
		||||
    "webpack-dev-server": "4.11.1",
 | 
			
		||||
    "webpack-merge": "5.8.0",
 | 
			
		||||
    "husky": "^8.0.0"
 | 
			
		||||
    "webpack-merge": "5.8.0"
 | 
			
		||||
  },
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "cross-env SERVE=true webpack -c config/webpack/prod.js",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,10 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
import "./basebutton.scss"
 | 
			
		||||
import "./basebutton.scss";
 | 
			
		||||
 | 
			
		||||
export const BaseButton = ({ children, styles, ...props }) => {
 | 
			
		||||
  return (
 | 
			
		||||
    <button
 | 
			
		||||
      className={styles ? `${styles} button` : "button"}
 | 
			
		||||
      {...props}
 | 
			
		||||
    >
 | 
			
		||||
    <button className={styles ? `${styles} button` : "button"} {...props}>
 | 
			
		||||
      {children}
 | 
			
		||||
    </button>
 | 
			
		||||
  );
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,10 @@
 | 
			
		||||
        img {
 | 
			
		||||
          margin-right: 12px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        p:hover {
 | 
			
		||||
          text-decoration: underline;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,14 +4,13 @@ import { Link } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
import { modalToggle, setProjectBoardFetch } from "@redux/projectsTrackerSlice";
 | 
			
		||||
 | 
			
		||||
import { urlForLocal } from "@utils/helper";
 | 
			
		||||
import { getCorrectRequestDate, urlForLocal } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import { getCorrectDate } from "@components/Calendar/calendarHelper";
 | 
			
		||||
import BaseButton from "@components/Common/BaseButton/BaseButton";
 | 
			
		||||
import ModalLayout from "@components/Common/ModalLayout/ModalLayout";
 | 
			
		||||
import TrackerModal from "@components/Modal/TrackerModal/TrackerModal";
 | 
			
		||||
import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal";
 | 
			
		||||
import TrackerTaskComment from "@components/TrackerTaskComment/TrackerTaskComment";
 | 
			
		||||
 | 
			
		||||
import archive from "assets/icons/archive.svg";
 | 
			
		||||
import arrow from "assets/icons/arrows/arrowStart.png";
 | 
			
		||||
@@ -26,7 +25,7 @@ import plus from "assets/icons/plus.svg";
 | 
			
		||||
import send from "assets/icons/send.svg";
 | 
			
		||||
import watch from "assets/icons/watch.svg";
 | 
			
		||||
 | 
			
		||||
import "./ModalTicket.scss";
 | 
			
		||||
import "./modalTicket.scss";
 | 
			
		||||
 | 
			
		||||
export const ModalTiсket = ({
 | 
			
		||||
  active,
 | 
			
		||||
@@ -45,13 +44,19 @@ export const ModalTiсket = ({
 | 
			
		||||
    comment: "",
 | 
			
		||||
  });
 | 
			
		||||
  const [comments, setComments] = useState([]);
 | 
			
		||||
  const [commentsEditOpen, setCommentsEditOpen] = useState({});
 | 
			
		||||
  const [commentsEditText, setCommentsEditText] = useState({});
 | 
			
		||||
  const [dropListOpen, setDropListOpen] = useState(false);
 | 
			
		||||
  const [dropListMembersOpen, setDropListMembersOpen] = useState(false);
 | 
			
		||||
  const [executor, setExecutor] = useState(task.executor);
 | 
			
		||||
  const [members, setMembers] = useState(task.taskUsers);
 | 
			
		||||
  const [users, setUsers] = useState([]);
 | 
			
		||||
  const [timerStart, setTimerStart] = useState(false);
 | 
			
		||||
  const [timerInfo, setTimerInfo] = useState({});
 | 
			
		||||
  const [currentTimerCount, setCurrentTimerCount] = useState({
 | 
			
		||||
    hours: 0,
 | 
			
		||||
    minute: 0,
 | 
			
		||||
    seconds: 0,
 | 
			
		||||
  });
 | 
			
		||||
  const [timerId, setTimerId] = useState(null);
 | 
			
		||||
 | 
			
		||||
  function deleteTask() {
 | 
			
		||||
    apiRequest("/task/update-task", {
 | 
			
		||||
@@ -90,37 +95,78 @@ export const ModalTiсket = ({
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      let newComment = res;
 | 
			
		||||
      newComment.created_at = new Date();
 | 
			
		||||
      newComment.subComments = [];
 | 
			
		||||
      setInputsValue((prevValue) => ({ ...prevValue, comment: "" }));
 | 
			
		||||
      setComments((prevValue) => [...prevValue, newComment]);
 | 
			
		||||
      setCommentsEditOpen((prevValue) => ({ ...prevValue, [res.id]: false }));
 | 
			
		||||
      setCommentsEditText((prevValue) => ({
 | 
			
		||||
        ...prevValue,
 | 
			
		||||
        [res.id]: res.text,
 | 
			
		||||
      }));
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  function deleteComment(commentId) {
 | 
			
		||||
    apiRequest("/comment/update", {
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        comment_id: commentId,
 | 
			
		||||
        status: 0,
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      setComments((prevValue) =>
 | 
			
		||||
        prevValue.filter((item) => item.id !== commentId)
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function editComment(commentId) {
 | 
			
		||||
    apiRequest("/comment/update", {
 | 
			
		||||
  function commentDelete(comment) {
 | 
			
		||||
    setComments((prevValue) =>
 | 
			
		||||
      prevValue.filter((item) => item.id !== comment.id)
 | 
			
		||||
    );
 | 
			
		||||
    if (comment.subComments.length) {
 | 
			
		||||
      // promiseAll
 | 
			
		||||
      comment.subComments.forEach((subComment) => {
 | 
			
		||||
        apiRequest("/comment/update", {
 | 
			
		||||
          method: "PUT",
 | 
			
		||||
          data: {
 | 
			
		||||
            comment_id: subComment.id,
 | 
			
		||||
            status: 0,
 | 
			
		||||
          },
 | 
			
		||||
        }).then(() => {});
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function addSubComment(commentId, subComment) {
 | 
			
		||||
    const addSubComment = comments;
 | 
			
		||||
    addSubComment.forEach((comment) => {
 | 
			
		||||
      if (comment.id === commentId) {
 | 
			
		||||
        comment.subComments.push(subComment);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    setComments(addSubComment);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function subCommentDelete(subComment) {
 | 
			
		||||
    const deleteSubComment = comments;
 | 
			
		||||
    deleteSubComment.forEach((comment, index) => {
 | 
			
		||||
      if (comment.id === subComment.parent_id) {
 | 
			
		||||
        deleteSubComment[index].subComments = comment.subComments.filter(
 | 
			
		||||
          (item) => item.id !== subComment.id
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    setComments([...deleteSubComment]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function startTaskTimer() {
 | 
			
		||||
    apiRequest("/timer/create", {
 | 
			
		||||
      method: "POST",
 | 
			
		||||
      data: {
 | 
			
		||||
        entity_type: 2,
 | 
			
		||||
        entity_id: task.id,
 | 
			
		||||
        created_at: getCorrectRequestDate(new Date()),
 | 
			
		||||
      },
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      setTimerStart(true);
 | 
			
		||||
      setTimerInfo(res);
 | 
			
		||||
      startTimer();
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function stopTaskTimer() {
 | 
			
		||||
    apiRequest("/timer/update", {
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        comment_id: commentId,
 | 
			
		||||
        text: commentsEditText[commentId],
 | 
			
		||||
        timer_id: timerInfo.id,
 | 
			
		||||
        stopped_at: getCorrectRequestDate(new Date()),
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {});
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      setTimerStart(false);
 | 
			
		||||
      clearInterval(timerId);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function taskExecutor(person) {
 | 
			
		||||
@@ -177,20 +223,77 @@ export const ModalTiсket = ({
 | 
			
		||||
    apiRequest(
 | 
			
		||||
      `/comment/get-by-entity?entity_type=2&entity_id=${task.id}`
 | 
			
		||||
    ).then((res) => {
 | 
			
		||||
      setComments(res);
 | 
			
		||||
      res.forEach((item) => {
 | 
			
		||||
        setCommentsEditOpen((prevValue) => ({
 | 
			
		||||
          ...prevValue,
 | 
			
		||||
          [item.id]: false,
 | 
			
		||||
        }));
 | 
			
		||||
        setCommentsEditText((prevValue) => ({
 | 
			
		||||
          ...prevValue,
 | 
			
		||||
          [item.id]: item.text,
 | 
			
		||||
        }));
 | 
			
		||||
      });
 | 
			
		||||
      const comments = res.reduce((acc, cur) => {
 | 
			
		||||
        if (!cur.parent_id) {
 | 
			
		||||
          acc.push({ ...cur, subComments: [] });
 | 
			
		||||
        } else {
 | 
			
		||||
          acc.forEach((item) => {
 | 
			
		||||
            if (item.id === cur.parent_id) item.subComments.push(cur);
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
        return acc;
 | 
			
		||||
      }, []);
 | 
			
		||||
      setComments(comments);
 | 
			
		||||
    });
 | 
			
		||||
    apiRequest(`/timer/get-by-entity?entity_type=2&entity_id=${task.id}`).then(
 | 
			
		||||
      (res) => {
 | 
			
		||||
        let timerSeconds = 0;
 | 
			
		||||
        res.length &&
 | 
			
		||||
          res.forEach((time) => {
 | 
			
		||||
            timerSeconds += time.deltaSeconds;
 | 
			
		||||
            setCurrentTimerCount({
 | 
			
		||||
              hours: Math.floor(timerSeconds / 60 / 60),
 | 
			
		||||
              minute: Math.floor((timerSeconds / 60) % 60),
 | 
			
		||||
              seconds: timerSeconds % 60,
 | 
			
		||||
            });
 | 
			
		||||
            updateTimerHours = Math.floor(timerSeconds / 60 / 60);
 | 
			
		||||
            updateTimerMinute = Math.floor((timerSeconds / 60) % 60);
 | 
			
		||||
            updateTimerSec = timerSeconds % 60;
 | 
			
		||||
            if (!time.stopped_at) {
 | 
			
		||||
              setTimerStart(true);
 | 
			
		||||
              startTimer();
 | 
			
		||||
              setTimerInfo(time);
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  function startTimer() {
 | 
			
		||||
    setTimerId(
 | 
			
		||||
      setInterval(() => {
 | 
			
		||||
        run();
 | 
			
		||||
      }, 1000)
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let updateTimerSec = currentTimerCount.seconds,
 | 
			
		||||
    updateTimerMinute = currentTimerCount.minute,
 | 
			
		||||
    updateTimerHours = currentTimerCount.hours;
 | 
			
		||||
 | 
			
		||||
  function run() {
 | 
			
		||||
    updateTimerSec++;
 | 
			
		||||
    if (updateTimerSec > 60) {
 | 
			
		||||
      updateTimerMinute++;
 | 
			
		||||
      updateTimerSec = 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (updateTimerMinute === 60) {
 | 
			
		||||
      updateTimerMinute = 0;
 | 
			
		||||
      updateTimerHours++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return setCurrentTimerCount({
 | 
			
		||||
      hours: updateTimerHours,
 | 
			
		||||
      minute: updateTimerMinute,
 | 
			
		||||
      seconds: updateTimerSec,
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function correctTimerTime(time) {
 | 
			
		||||
    if (time < 10) return `0${time}`;
 | 
			
		||||
    if (time > 10) return time;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    let ids = members.map((user) => user.user_id);
 | 
			
		||||
    setUsers(
 | 
			
		||||
@@ -202,23 +305,26 @@ export const ModalTiсket = ({
 | 
			
		||||
  }, [members]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <ModalLayout
 | 
			
		||||
        active={active}
 | 
			
		||||
        setActive={setActive}
 | 
			
		||||
        styles={"tracker-ticket"}
 | 
			
		||||
    <div
 | 
			
		||||
      className={active ? "modal-tiket active" : "modal-tiket"}
 | 
			
		||||
      onClick={() => setActive(false)}
 | 
			
		||||
    >
 | 
			
		||||
      <div
 | 
			
		||||
        className="modal-tiket__content"
 | 
			
		||||
        onClick={(e) => e.stopPropagation()}
 | 
			
		||||
      >
 | 
			
		||||
        <div className="content">
 | 
			
		||||
          <h3 className="title-project">
 | 
			
		||||
          <Link to={`/tracker/task/${task.id}`} className="title-project__full">
 | 
			
		||||
            <img src={fullScreen}></img>
 | 
			
		||||
          </Link>
 | 
			
		||||
 | 
			
		||||
          <div className="title-project">
 | 
			
		||||
            <img src={category} className="title-project__category"></img>
 | 
			
		||||
            Проект: {projectName}
 | 
			
		||||
            <Link
 | 
			
		||||
              to={`/tracker/task/${task.id}`}
 | 
			
		||||
              className="title-project__full"
 | 
			
		||||
            >
 | 
			
		||||
              <img src={fullScreen}></img>
 | 
			
		||||
            </Link>
 | 
			
		||||
          </h3>
 | 
			
		||||
            <h2>
 | 
			
		||||
              Проект:
 | 
			
		||||
              <h3>{projectName}</h3>
 | 
			
		||||
            </h2>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <div className="content__task">
 | 
			
		||||
            <span>Задача</span>
 | 
			
		||||
@@ -237,7 +343,7 @@ export const ModalTiсket = ({
 | 
			
		||||
            )}
 | 
			
		||||
            <div className="content__description">
 | 
			
		||||
              {editOpen ? (
 | 
			
		||||
                <input
 | 
			
		||||
                <textarea
 | 
			
		||||
                  value={inputsValue.description}
 | 
			
		||||
                  onChange={(e) => {
 | 
			
		||||
                    setInputsValue((prevValue) => ({
 | 
			
		||||
@@ -258,14 +364,14 @@ export const ModalTiсket = ({
 | 
			
		||||
                    dispatch(modalToggle("addSubtask"));
 | 
			
		||||
                    setAddSubtask(true);
 | 
			
		||||
                  }}
 | 
			
		||||
                  styles={"tasks__button"}
 | 
			
		||||
                  styles={"button-green-add"}
 | 
			
		||||
                >
 | 
			
		||||
                  <img src={plus}></img>
 | 
			
		||||
                  Добавить под задачу
 | 
			
		||||
                </BaseButton>
 | 
			
		||||
              </p>
 | 
			
		||||
              <p className="file">
 | 
			
		||||
                <BaseButton styles={"file__button"}>
 | 
			
		||||
                <BaseButton styles={"button-add-file"}>
 | 
			
		||||
                  <img src={file}></img>
 | 
			
		||||
                  Загрузить файл
 | 
			
		||||
                </BaseButton>
 | 
			
		||||
@@ -289,50 +395,14 @@ export const ModalTiсket = ({
 | 
			
		||||
            <div className="comments__list">
 | 
			
		||||
              {comments.map((comment) => {
 | 
			
		||||
                return (
 | 
			
		||||
                  <div className="comments__list__item" key={comment.id}>
 | 
			
		||||
                    <div className="comments__list__item__info">
 | 
			
		||||
                      <span>{getCorrectDate(comment.created_at)}</span>
 | 
			
		||||
                      <div
 | 
			
		||||
                        className={
 | 
			
		||||
                          commentsEditOpen[comment.id]
 | 
			
		||||
                            ? "edit edit__open"
 | 
			
		||||
                            : "edit"
 | 
			
		||||
                        }
 | 
			
		||||
                      >
 | 
			
		||||
                        <img
 | 
			
		||||
                          src={edit}
 | 
			
		||||
                          alt="edit"
 | 
			
		||||
                          onClick={() => {
 | 
			
		||||
                            if (commentsEditOpen[comment.id]) {
 | 
			
		||||
                              editComment(comment.id);
 | 
			
		||||
                            }
 | 
			
		||||
                            setCommentsEditOpen((prevValue) => ({
 | 
			
		||||
                              ...prevValue,
 | 
			
		||||
                              [comment.id]: !prevValue[comment.id],
 | 
			
		||||
                            }));
 | 
			
		||||
                          }}
 | 
			
		||||
                        />
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <img
 | 
			
		||||
                        src={del}
 | 
			
		||||
                        alt="delete"
 | 
			
		||||
                        onClick={() => deleteComment(comment.id)}
 | 
			
		||||
                      />
 | 
			
		||||
                    </div>
 | 
			
		||||
                    {commentsEditOpen[comment.id] ? (
 | 
			
		||||
                      <input
 | 
			
		||||
                        value={commentsEditText[comment.id]}
 | 
			
		||||
                        onChange={(e) => {
 | 
			
		||||
                          setCommentsEditText((prevValue) => ({
 | 
			
		||||
                            ...prevValue,
 | 
			
		||||
                            [comment.id]: e.target.value,
 | 
			
		||||
                          }));
 | 
			
		||||
                        }}
 | 
			
		||||
                      />
 | 
			
		||||
                    ) : (
 | 
			
		||||
                      <p>{commentsEditText[comment.id]}</p>
 | 
			
		||||
                    )}
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <TrackerTaskComment
 | 
			
		||||
                    key={comment.id}
 | 
			
		||||
                    taskId={task.id}
 | 
			
		||||
                    comment={comment}
 | 
			
		||||
                    commentDelete={commentDelete}
 | 
			
		||||
                    addSubComment={addSubComment}
 | 
			
		||||
                    subCommentDelete={subCommentDelete}
 | 
			
		||||
                  />
 | 
			
		||||
                );
 | 
			
		||||
              })}
 | 
			
		||||
            </div>
 | 
			
		||||
@@ -356,7 +426,12 @@ export const ModalTiсket = ({
 | 
			
		||||
              </div>
 | 
			
		||||
            ) : (
 | 
			
		||||
              <div className="add-worker moreItems ">
 | 
			
		||||
                <button onClick={() => setDropListOpen(true)}>+</button>
 | 
			
		||||
                <BaseButton
 | 
			
		||||
                  onClick={() => setDropListOpen(true)}
 | 
			
		||||
                  styles={"button-add-worker"}
 | 
			
		||||
                >
 | 
			
		||||
                  +
 | 
			
		||||
                </BaseButton>
 | 
			
		||||
                <span>Добавить исполнителя</span>
 | 
			
		||||
                {dropListOpen && (
 | 
			
		||||
                  <div className="dropdownList">
 | 
			
		||||
@@ -404,7 +479,12 @@ export const ModalTiсket = ({
 | 
			
		||||
            )}
 | 
			
		||||
 | 
			
		||||
            <div className="add-worker moreItems">
 | 
			
		||||
              <button onClick={() => setDropListMembersOpen(true)}>+</button>
 | 
			
		||||
              <BaseButton
 | 
			
		||||
                onClick={() => setDropListMembersOpen(true)}
 | 
			
		||||
                styles={"button-add-worker"}
 | 
			
		||||
              >
 | 
			
		||||
                +
 | 
			
		||||
              </BaseButton>
 | 
			
		||||
              <span>Добавить участников</span>
 | 
			
		||||
              {dropListMembersOpen && (
 | 
			
		||||
                <div className="dropdownList">
 | 
			
		||||
@@ -438,12 +518,29 @@ export const ModalTiсket = ({
 | 
			
		||||
            <div className="time">
 | 
			
		||||
              <img src={watch}></img>
 | 
			
		||||
              <span>Длительность : </span>
 | 
			
		||||
              <p>{"0:00:00"}</p>
 | 
			
		||||
              <p>
 | 
			
		||||
                {correctTimerTime(currentTimerCount.hours)}:
 | 
			
		||||
                {correctTimerTime(currentTimerCount.minute)}:
 | 
			
		||||
                {correctTimerTime(currentTimerCount.seconds)}
 | 
			
		||||
              </p>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <button className="start">
 | 
			
		||||
              Начать делать <img src={arrow}></img>
 | 
			
		||||
            </button>
 | 
			
		||||
            {timerStart ? (
 | 
			
		||||
              <button className="stop" onClick={() => stopTaskTimer()}>
 | 
			
		||||
                Остановить
 | 
			
		||||
              </button>
 | 
			
		||||
            ) : (
 | 
			
		||||
              <button
 | 
			
		||||
                className={
 | 
			
		||||
                  task.executor_id === Number(localStorage.getItem("id"))
 | 
			
		||||
                    ? "start"
 | 
			
		||||
                    : "start disable"
 | 
			
		||||
                }
 | 
			
		||||
                onClick={() => startTaskTimer()}
 | 
			
		||||
              >
 | 
			
		||||
                Начать делать <img src={arrow}></img>
 | 
			
		||||
              </button>
 | 
			
		||||
            )}
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <div className="workers_box-bottom">
 | 
			
		||||
@@ -475,14 +572,14 @@ export const ModalTiсket = ({
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </ModalLayout>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <TrackerModal
 | 
			
		||||
        active={addSubtask}
 | 
			
		||||
        setActive={setAddSubtask}
 | 
			
		||||
        defautlInput={task.column_id}
 | 
			
		||||
      ></TrackerModal>
 | 
			
		||||
    </>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,594 +0,0 @@
 | 
			
		||||
.tracker-ticket {
 | 
			
		||||
  background: #ffffff;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  border-radius: 8px;
 | 
			
		||||
  align-items: initial;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row;
 | 
			
		||||
 | 
			
		||||
  .content {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    width: 600px;
 | 
			
		||||
    margin: 26px 0 0 21px;
 | 
			
		||||
 | 
			
		||||
    .title-project {
 | 
			
		||||
      color: #1458dd;
 | 
			
		||||
      font-family: "LabGrotesque", sans-serif;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      font-weight: 700;
 | 
			
		||||
      font-size: 22px;
 | 
			
		||||
      line-height: 32px;
 | 
			
		||||
 | 
			
		||||
      &__category {
 | 
			
		||||
        margin-right: 17px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__full {
 | 
			
		||||
        margin-left: 35%;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__task {
 | 
			
		||||
      margin-top: -5px;
 | 
			
		||||
      padding: 18px;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
 | 
			
		||||
      input {
 | 
			
		||||
        font-style: normal;
 | 
			
		||||
        font-size: 16px;
 | 
			
		||||
        line-height: 24px;
 | 
			
		||||
        max-width: 340px;
 | 
			
		||||
        outline: none;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      button {
 | 
			
		||||
        img {
 | 
			
		||||
          margin-right: 5px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      h5 {
 | 
			
		||||
        font-family: "Inter", sans-serif;
 | 
			
		||||
        font-weight: 500;
 | 
			
		||||
        font-style: normal;
 | 
			
		||||
        font-size: 16px;
 | 
			
		||||
        line-height: 24px;
 | 
			
		||||
        color: #1a1919;
 | 
			
		||||
        margin-bottom: 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .comments__list {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        max-height: 420px;
 | 
			
		||||
        overflow: auto;
 | 
			
		||||
 | 
			
		||||
        &::-webkit-scrollbar {
 | 
			
		||||
          width: 4px;
 | 
			
		||||
          border-radius: 10px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &::-webkit-scrollbar-thumb {
 | 
			
		||||
          background: #cbd9f9;
 | 
			
		||||
          border-radius: 10px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &::-webkit-scrollbar-track {
 | 
			
		||||
          background: #c5c0c6;
 | 
			
		||||
          border-radius: 10px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &__item {
 | 
			
		||||
          padding: 10px 20px;
 | 
			
		||||
          display: flex;
 | 
			
		||||
          flex-direction: column;
 | 
			
		||||
          max-width: 438px;
 | 
			
		||||
          border-radius: 44px;
 | 
			
		||||
          font-size: 14px;
 | 
			
		||||
          width: 100%;
 | 
			
		||||
          position: relative;
 | 
			
		||||
 | 
			
		||||
          &__subComment {
 | 
			
		||||
            &:before {
 | 
			
		||||
              content: '';
 | 
			
		||||
              background: #E4E4E6;
 | 
			
		||||
              height: 1px;
 | 
			
		||||
              width: 7px;
 | 
			
		||||
              position: absolute;
 | 
			
		||||
              top: 36%;
 | 
			
		||||
              left: 2.5%;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &__main {
 | 
			
		||||
            &:after {
 | 
			
		||||
              content: '';
 | 
			
		||||
              position: absolute;
 | 
			
		||||
              background-image: url("../../../images/mainTaskCommentImg.png");
 | 
			
		||||
              width: 10px;
 | 
			
		||||
              height: 8px;
 | 
			
		||||
              top: 50px;
 | 
			
		||||
              left: 25px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &:before {
 | 
			
		||||
              content: '';
 | 
			
		||||
              position: absolute;
 | 
			
		||||
              background: #E4E4E6;
 | 
			
		||||
              width: 1px;
 | 
			
		||||
              height: calc(100% - 120px);
 | 
			
		||||
              left: 29px;
 | 
			
		||||
              top: 65px;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &__fio {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
 | 
			
		||||
            p {
 | 
			
		||||
              font-size: 12px;
 | 
			
		||||
              color: #000000;
 | 
			
		||||
              line-height: 32px;
 | 
			
		||||
              max-width: 150px;
 | 
			
		||||
              overflow: hidden;
 | 
			
		||||
              white-space: nowrap;
 | 
			
		||||
              text-overflow: ellipsis;
 | 
			
		||||
              margin-left: 10px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            img {
 | 
			
		||||
              width: 24px;
 | 
			
		||||
              height: 24px;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &__date {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
            column-gap: 5px;
 | 
			
		||||
 | 
			
		||||
            img {
 | 
			
		||||
              cursor: pointer;
 | 
			
		||||
              width: 15px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            span {
 | 
			
		||||
              font-size: 12px;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &__text {
 | 
			
		||||
            margin-left: 34px;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &__info {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            justify-content: space-between;
 | 
			
		||||
 | 
			
		||||
            .edit {
 | 
			
		||||
              width: 25px;
 | 
			
		||||
              display: flex;
 | 
			
		||||
              align-items: center;
 | 
			
		||||
              justify-content: center;
 | 
			
		||||
              border-radius: 5px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .edit__open {
 | 
			
		||||
              background: green;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &__answer {
 | 
			
		||||
            margin-left: 34px;
 | 
			
		||||
            text-decoration-line: underline;
 | 
			
		||||
            font-weight: 400;
 | 
			
		||||
            font-size: 10px;
 | 
			
		||||
            line-height: 32px;
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
 | 
			
		||||
            &__new {
 | 
			
		||||
              margin-left: 34px;
 | 
			
		||||
              font-size: 14px;
 | 
			
		||||
              border-radius: 5px;
 | 
			
		||||
              border: 1px solid gainsboro;
 | 
			
		||||
              padding: 3px 5px;
 | 
			
		||||
              display: flex;
 | 
			
		||||
              align-items: center;
 | 
			
		||||
              margin-top: 5px;
 | 
			
		||||
 | 
			
		||||
              img {
 | 
			
		||||
                width: 20px;
 | 
			
		||||
                height: 20px;
 | 
			
		||||
                cursor: pointer;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              input {
 | 
			
		||||
                width: 90%;
 | 
			
		||||
                border: none;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__description {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      margin-top: 10px;
 | 
			
		||||
 | 
			
		||||
      p {
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        line-height: 140%;
 | 
			
		||||
        color: #252c32;
 | 
			
		||||
        text-align: justify;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .image-task {
 | 
			
		||||
        margin: 10px 0 20px 0;
 | 
			
		||||
        max-width: 330px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__communication {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: row;
 | 
			
		||||
      margin: 29px 0 0 -5px;
 | 
			
		||||
 | 
			
		||||
      .tasks {
 | 
			
		||||
        justify-content: space-evenly;
 | 
			
		||||
 | 
			
		||||
        &__button {
 | 
			
		||||
          width: 180px;
 | 
			
		||||
          height: 40px;
 | 
			
		||||
          font-size: 12px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .tasks,
 | 
			
		||||
      .file {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .file {
 | 
			
		||||
        justify-content: space-between;
 | 
			
		||||
        margin-left: 20px;
 | 
			
		||||
 | 
			
		||||
        &__button {
 | 
			
		||||
          background: white;
 | 
			
		||||
          width: 166px;
 | 
			
		||||
          height: 40px;
 | 
			
		||||
          border: 0.5px solid #1458dd;
 | 
			
		||||
          font-weight: 400;
 | 
			
		||||
          font-size: 12px;
 | 
			
		||||
          color: #1458dd;
 | 
			
		||||
 | 
			
		||||
          img {
 | 
			
		||||
            margin-right: 9px;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        span {
 | 
			
		||||
          margin: 0 3px 0 11px;
 | 
			
		||||
          font-weight: 500;
 | 
			
		||||
          font-size: 12px;
 | 
			
		||||
          line-height: 15px;
 | 
			
		||||
          color: #6e7c87;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__input {
 | 
			
		||||
      margin: 20px 0 20px 0;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
      width: 438px;
 | 
			
		||||
      height: 40px;
 | 
			
		||||
      background: #f1f1f1;
 | 
			
		||||
      border-radius: 44px;
 | 
			
		||||
 | 
			
		||||
      input {
 | 
			
		||||
        width: 80%;
 | 
			
		||||
        background: inherit;
 | 
			
		||||
        border: none;
 | 
			
		||||
        outline: none;
 | 
			
		||||
        padding-left: 30px;
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
        font-size: 12px;
 | 
			
		||||
        line-height: 32px;
 | 
			
		||||
        border-radius: 44px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      img {
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
        margin-right: 18px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .members {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    font-size: 14px;
 | 
			
		||||
 | 
			
		||||
    &__list {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      row-gap: 8px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .workers {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    border-left: 1px solid #f1f1f1;
 | 
			
		||||
 | 
			
		||||
    .exit {
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 35px;
 | 
			
		||||
      right: 40px;
 | 
			
		||||
 | 
			
		||||
      &:before,
 | 
			
		||||
      &:after {
 | 
			
		||||
        content: "";
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        width: 16px;
 | 
			
		||||
        height: 2px;
 | 
			
		||||
        background: #263238;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &:before {
 | 
			
		||||
        transform: rotate(45deg);
 | 
			
		||||
      }
 | 
			
		||||
      &:after {
 | 
			
		||||
        transform: rotate(-45deg);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    span {
 | 
			
		||||
      font-family: "Inter", sans-serif;
 | 
			
		||||
      font-weight: 500;
 | 
			
		||||
      font-size: 11px;
 | 
			
		||||
      color: #807777;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .nameProject {
 | 
			
		||||
      max-width: 200px;
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
      white-space: nowrap;
 | 
			
		||||
      text-overflow: ellipsis;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .add-worker {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      position: relative;
 | 
			
		||||
 | 
			
		||||
      span {
 | 
			
		||||
        color: #000000;
 | 
			
		||||
        font-size: 12px;
 | 
			
		||||
        line-height: 32px;
 | 
			
		||||
        margin-left: 17px;
 | 
			
		||||
        font-style: normal;
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      button {
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
        background: #8bcc60;
 | 
			
		||||
        border-radius: 44px;
 | 
			
		||||
        width: 33px;
 | 
			
		||||
        height: 33px;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        justify-content: center;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        border: none;
 | 
			
		||||
        color: white;
 | 
			
		||||
        font-size: 17px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .start {
 | 
			
		||||
      font-size: 12px;
 | 
			
		||||
      margin-top: 25px;
 | 
			
		||||
      width: 151px;
 | 
			
		||||
      height: 40px;
 | 
			
		||||
      border: none;
 | 
			
		||||
      color: white;
 | 
			
		||||
      background: #1458dd;
 | 
			
		||||
      border-radius: 44px;
 | 
			
		||||
 | 
			
		||||
      img {
 | 
			
		||||
        margin-left: 10px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .disable {
 | 
			
		||||
      opacity: 0.5;
 | 
			
		||||
      pointer-events: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .stop {
 | 
			
		||||
      font-size: 12px;
 | 
			
		||||
      margin-top: 25px;
 | 
			
		||||
      width: 151px;
 | 
			
		||||
      height: 40px;
 | 
			
		||||
      border: none;
 | 
			
		||||
      color: white;
 | 
			
		||||
      background: red;
 | 
			
		||||
      border-radius: 44px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .time {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
      font-size: 12px;
 | 
			
		||||
      margin-top: 20px;
 | 
			
		||||
      width: 160px;
 | 
			
		||||
 | 
			
		||||
      p {
 | 
			
		||||
        color: #000000;
 | 
			
		||||
        margin: 0;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__creator {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
      line-height: 32px;
 | 
			
		||||
      font-weight: 500;
 | 
			
		||||
      color: #2d4a17;
 | 
			
		||||
      max-width: 200px;
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
      white-space: nowrap;
 | 
			
		||||
      text-overflow: ellipsis;
 | 
			
		||||
 | 
			
		||||
      span {
 | 
			
		||||
        margin-left: 5px;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        line-height: 32px;
 | 
			
		||||
        font-weight: 500;
 | 
			
		||||
        display: flex;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .worker {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: row;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
 | 
			
		||||
      p {
 | 
			
		||||
        max-width: 170px;
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
        white-space: nowrap;
 | 
			
		||||
        text-overflow: ellipsis;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      img {
 | 
			
		||||
        max-width: 25px;
 | 
			
		||||
        max-height: 25px;
 | 
			
		||||
        margin-left: 5px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .task__info {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      row-gap: 5px;
 | 
			
		||||
 | 
			
		||||
      .delete {
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .executor {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
 | 
			
		||||
        p {
 | 
			
		||||
          max-width: 170px;
 | 
			
		||||
          overflow: hidden;
 | 
			
		||||
          white-space: nowrap;
 | 
			
		||||
          text-overflow: ellipsis;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        img {
 | 
			
		||||
          margin-left: 5px;
 | 
			
		||||
          max-width: 25px;
 | 
			
		||||
          max-height: 25px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .dropdownList {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        background: white;
 | 
			
		||||
        padding: 10px;
 | 
			
		||||
        border-radius: 10px;
 | 
			
		||||
        top: 0;
 | 
			
		||||
        z-index: 10;
 | 
			
		||||
        border: 1px solid gray;
 | 
			
		||||
        width: 260px;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        row-gap: 8px;
 | 
			
		||||
 | 
			
		||||
        .noUsers {
 | 
			
		||||
          font-size: 14px;
 | 
			
		||||
          text-align: center;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &__close {
 | 
			
		||||
          cursor: pointer;
 | 
			
		||||
          margin-left: auto;
 | 
			
		||||
          width: 12px;
 | 
			
		||||
          margin-right: 5px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &__person {
 | 
			
		||||
          display: flex;
 | 
			
		||||
          justify-content: space-between;
 | 
			
		||||
          cursor: pointer;
 | 
			
		||||
 | 
			
		||||
          img {
 | 
			
		||||
            max-width: 30px;
 | 
			
		||||
            max-height: 30px;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &_box {
 | 
			
		||||
      padding: 25px 85px 40px 40px;
 | 
			
		||||
      border-bottom: 1px solid #f1f1f1;
 | 
			
		||||
 | 
			
		||||
      &-middle {
 | 
			
		||||
        padding: 0px 40px 25px 40px;
 | 
			
		||||
        border-bottom: 1px solid #f1f1f1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &-bottom {
 | 
			
		||||
        padding: 40px 110px 75px 56px;
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        line-height: 38px;
 | 
			
		||||
 | 
			
		||||
        div {
 | 
			
		||||
          display: flex;
 | 
			
		||||
          cursor: pointer;
 | 
			
		||||
          align-items: center;
 | 
			
		||||
          padding-left: 10px;
 | 
			
		||||
 | 
			
		||||
          p {
 | 
			
		||||
            margin: 0 0 0 12px;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .edit {
 | 
			
		||||
          background: #52b709;
 | 
			
		||||
          border-radius: 50px;
 | 
			
		||||
 | 
			
		||||
          p {
 | 
			
		||||
            font-weight: 700;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.subtask {
 | 
			
		||||
  h4 {
 | 
			
		||||
    width: 90%;
 | 
			
		||||
    p {
 | 
			
		||||
      color: #1458dd;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -17,32 +17,54 @@
 | 
			
		||||
 | 
			
		||||
.modal-tiket__content {
 | 
			
		||||
  background: #ffffff;
 | 
			
		||||
  //border: 1px solid #dde2e4;
 | 
			
		||||
  border-radius: 8px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row;
 | 
			
		||||
 | 
			
		||||
  .content {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    width: 600px;
 | 
			
		||||
    margin: 26px 0 0 21px;
 | 
			
		||||
 | 
			
		||||
    .title-project {
 | 
			
		||||
      color: #1458dd;
 | 
			
		||||
      font-family: "LabGrotesque", sans-serif;
 | 
			
		||||
      max-width: 85%;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      font-weight: 700;
 | 
			
		||||
      font-size: 22px;
 | 
			
		||||
      line-height: 32px;
 | 
			
		||||
      flex-direction: row;
 | 
			
		||||
 | 
			
		||||
      &__category {
 | 
			
		||||
        margin-right: 17px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      h2,
 | 
			
		||||
      h3 {
 | 
			
		||||
        font-weight: 700;
 | 
			
		||||
        font-size: 22px;
 | 
			
		||||
        line-height: 32px;
 | 
			
		||||
        color: #1458dd;
 | 
			
		||||
        margin: 0;
 | 
			
		||||
        font-family: "LabGrotesque", sans-serif;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      h2 {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        flex-wrap: wrap;
 | 
			
		||||
        flex-direction: row;
 | 
			
		||||
 | 
			
		||||
        h3 {
 | 
			
		||||
          margin-left: 5px;
 | 
			
		||||
          word-break: break-all;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__full {
 | 
			
		||||
        margin-left: 35%;
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        right: 28px;
 | 
			
		||||
        top: 0;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -79,7 +101,7 @@
 | 
			
		||||
      .comments__list {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        max-height: 420px;
 | 
			
		||||
        max-height: 300px;
 | 
			
		||||
        overflow: auto;
 | 
			
		||||
 | 
			
		||||
        &::-webkit-scrollbar {
 | 
			
		||||
@@ -109,8 +131,8 @@
 | 
			
		||||
 | 
			
		||||
          &__subComment {
 | 
			
		||||
            &:before {
 | 
			
		||||
              content: '';
 | 
			
		||||
              background: #E4E4E6;
 | 
			
		||||
              content: "";
 | 
			
		||||
              background: #e4e4e6;
 | 
			
		||||
              height: 1px;
 | 
			
		||||
              width: 7px;
 | 
			
		||||
              position: absolute;
 | 
			
		||||
@@ -121,9 +143,9 @@
 | 
			
		||||
 | 
			
		||||
          &__main {
 | 
			
		||||
            &:after {
 | 
			
		||||
              content: '';
 | 
			
		||||
              content: "";
 | 
			
		||||
              position: absolute;
 | 
			
		||||
              background-image: url("../../../assets/images/mainTaskCommentImg.png");
 | 
			
		||||
              background-image: url("assets/images/mainTaskCommentImg.png");
 | 
			
		||||
              width: 10px;
 | 
			
		||||
              height: 8px;
 | 
			
		||||
              top: 50px;
 | 
			
		||||
@@ -131,9 +153,9 @@
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &:before {
 | 
			
		||||
              content: '';
 | 
			
		||||
              content: "";
 | 
			
		||||
              position: absolute;
 | 
			
		||||
              background: #E4E4E6;
 | 
			
		||||
              background: #e4e4e6;
 | 
			
		||||
              width: 1px;
 | 
			
		||||
              height: calc(100% - 120px);
 | 
			
		||||
              left: 29px;
 | 
			
		||||
@@ -236,6 +258,13 @@
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      margin-top: 10px;
 | 
			
		||||
 | 
			
		||||
      textarea {
 | 
			
		||||
        min-height: 120px;
 | 
			
		||||
        max-height: 450px;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      p {
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
@@ -268,16 +297,12 @@
 | 
			
		||||
      .tasks {
 | 
			
		||||
        justify-content: space-evenly;
 | 
			
		||||
 | 
			
		||||
        button {
 | 
			
		||||
        .button-green-add {
 | 
			
		||||
          width: 180px;
 | 
			
		||||
          height: 40px;
 | 
			
		||||
          background: #52b709;
 | 
			
		||||
          border-radius: 44px;
 | 
			
		||||
          font-weight: 400;
 | 
			
		||||
          font-size: 12px;
 | 
			
		||||
          line-height: 32px;
 | 
			
		||||
          border: none;
 | 
			
		||||
          color: #ffffff;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@@ -291,7 +316,7 @@
 | 
			
		||||
        justify-content: space-between;
 | 
			
		||||
        margin-left: 7px;
 | 
			
		||||
 | 
			
		||||
        button {
 | 
			
		||||
        .button-add-file {
 | 
			
		||||
          display: flex;
 | 
			
		||||
          align-items: center;
 | 
			
		||||
          justify-content: center;
 | 
			
		||||
@@ -337,7 +362,7 @@
 | 
			
		||||
        outline: none;
 | 
			
		||||
        padding-left: 30px;
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
        font-size: 12px;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        line-height: 32px;
 | 
			
		||||
        border-radius: 44px;
 | 
			
		||||
      }
 | 
			
		||||
@@ -346,6 +371,10 @@
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
        margin-right: 18px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &:focus-within {
 | 
			
		||||
        border: 1px solid #0000004d;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -406,6 +435,7 @@
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      position: relative;
 | 
			
		||||
      margin-bottom: 5px;
 | 
			
		||||
 | 
			
		||||
      span {
 | 
			
		||||
        color: #000000;
 | 
			
		||||
@@ -416,17 +446,12 @@
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      button {
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
        background: #8bcc60;
 | 
			
		||||
        border-radius: 44px;
 | 
			
		||||
      .button-add-worker {
 | 
			
		||||
        width: 33px;
 | 
			
		||||
        height: 33px;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        justify-content: center;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        border: none;
 | 
			
		||||
        color: white;
 | 
			
		||||
        font-size: 17px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -615,6 +640,10 @@
 | 
			
		||||
            font-weight: 700;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        p:hover {
 | 
			
		||||
          text-decoration: underline;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -1,45 +1,47 @@
 | 
			
		||||
import React, { useEffect, useState } from "react";
 | 
			
		||||
import { useDispatch, useSelector } from "react-redux";
 | 
			
		||||
import { Link, useNavigate, useParams } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
import { ProfileHeader } from "../../../ProfileHeader/ProfileHeader";
 | 
			
		||||
import { ProfileBreadcrumbs } from "../../../ProfileBreadcrumbs/ProfileBreadcrumbs";
 | 
			
		||||
import { Footer } from "@components/Common/Footer/Footer";
 | 
			
		||||
import { Link, useParams, useNavigate } from "react-router-dom";
 | 
			
		||||
import TrackerModal from "../../../Modal/TrackerModal/TrackerModal";
 | 
			
		||||
import TrackerTaskComment from "../../../TrackerTaskComment/TrackerTaskComment";
 | 
			
		||||
import { Navigation } from "../../../Navigation/Navigation";
 | 
			
		||||
import {Loader} from "@components/Common/Loader/Loader";
 | 
			
		||||
 | 
			
		||||
import {useDispatch, useSelector} from "react-redux";
 | 
			
		||||
import {
 | 
			
		||||
  deletePersonOnProject,
 | 
			
		||||
  getBoarderLoader,
 | 
			
		||||
  getProjectBoard,
 | 
			
		||||
  modalToggle,
 | 
			
		||||
  setProjectBoardFetch,
 | 
			
		||||
  setToggleTab,
 | 
			
		||||
  getProjectBoard,
 | 
			
		||||
  getBoarderLoader,
 | 
			
		||||
} from "../../../../redux/projectsTrackerSlice";
 | 
			
		||||
import { apiRequest } from "../../../../api/request";
 | 
			
		||||
} from "@redux/projectsTrackerSlice";
 | 
			
		||||
 | 
			
		||||
import project from "../../../../assets/icons/trackerProject.svg";
 | 
			
		||||
import watch from "../../../../assets/icons/watch.svg";
 | 
			
		||||
import file from "../../../../assets/icons/fileModal.svg";
 | 
			
		||||
import send from "../../../../assets/icons/send.svg";
 | 
			
		||||
import arrow2 from "../../../../assets/icons/arrows/arrowStart.png";
 | 
			
		||||
import plus from "../../../../assets/icons/plus.svg";
 | 
			
		||||
import tasks from "../../../../assets/icons/trackerTasks.svg";
 | 
			
		||||
import archive from "../../../../assets/icons/archive.svg";
 | 
			
		||||
import arrow from "../../../../assets/icons/arrows/arrowCalendar.png";
 | 
			
		||||
import link from "../../../../assets/icons/link.svg";
 | 
			
		||||
import archive2 from "../../../../assets/icons/archive.svg";
 | 
			
		||||
import del from "../../../../assets/icons/delete.svg";
 | 
			
		||||
import edit from "../../../../assets/icons/edit.svg";
 | 
			
		||||
import close from "../../../../assets/icons/close.png";
 | 
			
		||||
import { getCorrectRequestDate, urlForLocal } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import BaseButton from "@components/Common/BaseButton/BaseButton";
 | 
			
		||||
import { Footer } from "@components/Common/Footer/Footer";
 | 
			
		||||
import { Loader } from "@components/Common/Loader/Loader";
 | 
			
		||||
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 TrackerTaskComment from "@components/TrackerTaskComment/TrackerTaskComment";
 | 
			
		||||
 | 
			
		||||
import archive from "assets/icons/archive.svg";
 | 
			
		||||
import archive2 from "assets/icons/archive.svg";
 | 
			
		||||
import arrow from "assets/icons/arrows/arrowCalendar.png";
 | 
			
		||||
import arrow2 from "assets/icons/arrows/arrowStart.png";
 | 
			
		||||
import close from "assets/icons/close.png";
 | 
			
		||||
import del from "assets/icons/delete.svg";
 | 
			
		||||
import edit from "assets/icons/edit.svg";
 | 
			
		||||
import file from "assets/icons/fileModal.svg";
 | 
			
		||||
import link from "assets/icons/link.svg";
 | 
			
		||||
import plus from "assets/icons/plus.svg";
 | 
			
		||||
import send from "assets/icons/send.svg";
 | 
			
		||||
import project from "assets/icons/trackerProject.svg";
 | 
			
		||||
import tasks from "assets/icons/trackerTasks.svg";
 | 
			
		||||
import watch from "assets/icons/watch.svg";
 | 
			
		||||
 | 
			
		||||
import "./ticketFullScreen.scss";
 | 
			
		||||
 | 
			
		||||
import {getCorrectRequestDate, urlForLocal} from "../../../../utils/helper";
 | 
			
		||||
 | 
			
		||||
export const TicketFullScreen = ({}) => {
 | 
			
		||||
export const TicketFullScreen = () => {
 | 
			
		||||
  const [modalAddWorker, setModalAddWorker] = useState(false);
 | 
			
		||||
  const ticketId = useParams();
 | 
			
		||||
  const dispatch = useDispatch();
 | 
			
		||||
@@ -51,35 +53,41 @@ export const TicketFullScreen = ({}) => {
 | 
			
		||||
  const [inputsValue, setInputsValue] = useState({});
 | 
			
		||||
  const [loader, setLoader] = useState(true);
 | 
			
		||||
  const [comments, setComments] = useState([]);
 | 
			
		||||
  const [personListOpen, setPersonListOpen] = useState(false)
 | 
			
		||||
  const [timerStart, setTimerStart] = useState(false)
 | 
			
		||||
  const [timerInfo, setTimerInfo] = useState({})
 | 
			
		||||
  const [personListOpen, setPersonListOpen] = useState(false);
 | 
			
		||||
  const [timerStart, setTimerStart] = useState(false);
 | 
			
		||||
  const [timerInfo, setTimerInfo] = useState({});
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    apiRequest(`/task/get-task?task_id=${ticketId.id}`).then((taskInfo) => {
 | 
			
		||||
      setTaskInfo(taskInfo);
 | 
			
		||||
      setInputsValue({title: taskInfo.title, description: taskInfo.description, comment: ''})
 | 
			
		||||
      apiRequest(`/comment/get-by-entity?entity_type=2&entity_id=${taskInfo.id}`).then((res) => {
 | 
			
		||||
      setInputsValue({
 | 
			
		||||
        title: taskInfo.title,
 | 
			
		||||
        description: taskInfo.description,
 | 
			
		||||
        comment: "",
 | 
			
		||||
      });
 | 
			
		||||
      apiRequest(
 | 
			
		||||
        `/comment/get-by-entity?entity_type=2&entity_id=${taskInfo.id}`
 | 
			
		||||
      ).then((res) => {
 | 
			
		||||
        const comments = res.reduce((acc, cur) => {
 | 
			
		||||
          if (!cur.parent_id) {
 | 
			
		||||
            acc.push({...cur, subComments: []})
 | 
			
		||||
            acc.push({ ...cur, subComments: [] });
 | 
			
		||||
          } else {
 | 
			
		||||
            acc.forEach((item) => {
 | 
			
		||||
              if (item.id === cur.parent_id) item.subComments.push(cur)
 | 
			
		||||
            })
 | 
			
		||||
              if (item.id === cur.parent_id) item.subComments.push(cur);
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
          return acc
 | 
			
		||||
        }, [])
 | 
			
		||||
        setComments(comments)
 | 
			
		||||
      })
 | 
			
		||||
          return acc;
 | 
			
		||||
        }, []);
 | 
			
		||||
        setComments(comments);
 | 
			
		||||
      });
 | 
			
		||||
      taskInfo.timers.forEach((time) => {
 | 
			
		||||
        if (!time.stopped_at) {
 | 
			
		||||
          setTimerStart(true)
 | 
			
		||||
          setTimerInfo(time)
 | 
			
		||||
          setTimerStart(true);
 | 
			
		||||
          setTimerInfo(time);
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      });
 | 
			
		||||
      dispatch(setProjectBoardFetch(taskInfo.project_id));
 | 
			
		||||
      setLoader(boardLoader)
 | 
			
		||||
      setLoader(boardLoader);
 | 
			
		||||
    });
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
@@ -101,10 +109,9 @@ export const TicketFullScreen = ({}) => {
 | 
			
		||||
      data: {
 | 
			
		||||
        task_id: taskInfo.id,
 | 
			
		||||
        title: inputsValue.title,
 | 
			
		||||
        description: inputsValue.description
 | 
			
		||||
        description: inputsValue.description,
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
    });
 | 
			
		||||
    }).then(() => {});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function createComment() {
 | 
			
		||||
@@ -113,15 +120,15 @@ export const TicketFullScreen = ({}) => {
 | 
			
		||||
      data: {
 | 
			
		||||
        text: inputsValue.comment,
 | 
			
		||||
        entity_type: 2,
 | 
			
		||||
        entity_id: taskInfo.id
 | 
			
		||||
      }
 | 
			
		||||
        entity_id: taskInfo.id,
 | 
			
		||||
      },
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      let newComment = res
 | 
			
		||||
      newComment.created_at = new Date()
 | 
			
		||||
      newComment.subComments = []
 | 
			
		||||
      setInputsValue((prevValue) => ({...prevValue, comment: ''}))
 | 
			
		||||
      setComments((prevValue) => ([...prevValue, newComment]))
 | 
			
		||||
    })
 | 
			
		||||
      let newComment = res;
 | 
			
		||||
      newComment.created_at = new Date();
 | 
			
		||||
      newComment.subComments = [];
 | 
			
		||||
      setInputsValue((prevValue) => ({ ...prevValue, comment: "" }));
 | 
			
		||||
      setComments((prevValue) => [...prevValue, newComment]);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function startTaskTimer() {
 | 
			
		||||
@@ -130,12 +137,12 @@ export const TicketFullScreen = ({}) => {
 | 
			
		||||
      data: {
 | 
			
		||||
        entity_type: 2,
 | 
			
		||||
        entity_id: taskInfo.id,
 | 
			
		||||
        created_at: getCorrectRequestDate(new Date())
 | 
			
		||||
      }
 | 
			
		||||
        created_at: getCorrectRequestDate(new Date()),
 | 
			
		||||
      },
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      setTimerStart(true)
 | 
			
		||||
      setTimerInfo(res)
 | 
			
		||||
    })
 | 
			
		||||
      setTimerStart(true);
 | 
			
		||||
      setTimerInfo(res);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function stopTaskTimer() {
 | 
			
		||||
@@ -143,9 +150,9 @@ export const TicketFullScreen = ({}) => {
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        timer_id: timerInfo.id,
 | 
			
		||||
        stopped_at: getCorrectRequestDate(new Date())
 | 
			
		||||
      }
 | 
			
		||||
    }).then(() => setTimerStart(false))
 | 
			
		||||
        stopped_at: getCorrectRequestDate(new Date()),
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => setTimerStart(false));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function deletePerson(userId) {
 | 
			
		||||
@@ -153,47 +160,50 @@ export const TicketFullScreen = ({}) => {
 | 
			
		||||
      method: "DELETE",
 | 
			
		||||
      data: {
 | 
			
		||||
        project_id: projectBoard.id,
 | 
			
		||||
        user_id: userId
 | 
			
		||||
        user_id: userId,
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      dispatch(deletePersonOnProject(userId))
 | 
			
		||||
      dispatch(deletePersonOnProject(userId));
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function commentDelete(comment) {
 | 
			
		||||
    setComments((prevValue) => prevValue.filter((item) => item.id !== comment.id))
 | 
			
		||||
    setComments((prevValue) =>
 | 
			
		||||
      prevValue.filter((item) => item.id !== comment.id)
 | 
			
		||||
    );
 | 
			
		||||
    if (comment.subComments.length) {
 | 
			
		||||
      comment.subComments.forEach((subComment) => {
 | 
			
		||||
        apiRequest("/comment/update", {
 | 
			
		||||
          method: "PUT",
 | 
			
		||||
          data: {
 | 
			
		||||
            comment_id: subComment.id,
 | 
			
		||||
            status: 0
 | 
			
		||||
          }
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
            status: 0,
 | 
			
		||||
          },
 | 
			
		||||
        }).then(() => {});
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function addSubComment(commentId, subComment) {
 | 
			
		||||
    const addSubComment = comments
 | 
			
		||||
    const addSubComment = comments;
 | 
			
		||||
    addSubComment.forEach((comment) => {
 | 
			
		||||
      if (comment.id === commentId) {
 | 
			
		||||
        comment.subComments.push(subComment)
 | 
			
		||||
        comment.subComments.push(subComment);
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    setComments(addSubComment)
 | 
			
		||||
    });
 | 
			
		||||
    setComments(addSubComment);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function subCommentDelete(subComment) {
 | 
			
		||||
    const deleteSubComment = comments
 | 
			
		||||
    const deleteSubComment = comments;
 | 
			
		||||
    deleteSubComment.forEach((comment, index) => {
 | 
			
		||||
      if (comment.id === subComment.parent_id) {
 | 
			
		||||
        deleteSubComment[index].subComments = comment.subComments.filter((item) => item.id !== subComment.id)
 | 
			
		||||
        deleteSubComment[index].subComments = comment.subComments.filter(
 | 
			
		||||
          (item) => item.id !== subComment.id
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    setComments([...deleteSubComment])
 | 
			
		||||
    });
 | 
			
		||||
    setComments([...deleteSubComment]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const toggleTabs = (index) => {
 | 
			
		||||
@@ -201,256 +211,323 @@ export const TicketFullScreen = ({}) => {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
      <section className="ticket-full-screen">
 | 
			
		||||
        <ProfileHeader />
 | 
			
		||||
        <Navigation />
 | 
			
		||||
        <div className="container">
 | 
			
		||||
          <div className="tracker__content">
 | 
			
		||||
            <ProfileBreadcrumbs
 | 
			
		||||
                links={[
 | 
			
		||||
                  { name: "Главная", link: "/profile" },
 | 
			
		||||
                  { name: "Трекер", link: "/profile/tracker" },
 | 
			
		||||
                ]}
 | 
			
		||||
            />
 | 
			
		||||
            <h2 className="tracker__title">Управление проектами с трекером</h2>
 | 
			
		||||
          </div>
 | 
			
		||||
    <section className="ticket-full-screen">
 | 
			
		||||
      <ProfileHeader />
 | 
			
		||||
      <Navigation />
 | 
			
		||||
      <div className="container">
 | 
			
		||||
        <div className="tracker__content">
 | 
			
		||||
          <ProfileBreadcrumbs
 | 
			
		||||
            links={[
 | 
			
		||||
              { name: "Главная", link: "/profile" },
 | 
			
		||||
              { name: "Трекер", link: "/profile/tracker" },
 | 
			
		||||
            ]}
 | 
			
		||||
          />
 | 
			
		||||
          <h2 className="tracker__title">Управление проектами с трекером</h2>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className="tracker__tabs">
 | 
			
		||||
          <div className="tracker__tabs__head">
 | 
			
		||||
            <Link
 | 
			
		||||
                to="/profile/tracker"
 | 
			
		||||
                className="tab active-tab"
 | 
			
		||||
                onClick={() => toggleTabs(1)}
 | 
			
		||||
            >
 | 
			
		||||
              <img src={project} alt="img" />
 | 
			
		||||
              <p>Проекты </p>
 | 
			
		||||
            </Link>
 | 
			
		||||
            <Link
 | 
			
		||||
                to="/profile/tracker"
 | 
			
		||||
                className="tab"
 | 
			
		||||
                onClick={() => toggleTabs(2)}
 | 
			
		||||
            >
 | 
			
		||||
              <img src={tasks} alt="img" />
 | 
			
		||||
              <p>Все мои задачи</p>
 | 
			
		||||
            </Link>
 | 
			
		||||
            <Link
 | 
			
		||||
                to="/profile/tracker"
 | 
			
		||||
                className="tab"
 | 
			
		||||
                onClick={() => toggleTabs(3)}
 | 
			
		||||
            >
 | 
			
		||||
              <img src={archive} alt="img" />
 | 
			
		||||
              <p>Архив</p>
 | 
			
		||||
            </Link>
 | 
			
		||||
          </div>
 | 
			
		||||
          {loader ? <Loader /> :
 | 
			
		||||
              <>
 | 
			
		||||
                <div className="tracker__tabs__content content-tabs">
 | 
			
		||||
                  <div className="tasks__head">
 | 
			
		||||
                    <div className="tasks__head__wrapper">
 | 
			
		||||
                      <h4>Проект : {projectBoard.name}</h4>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div className="tracker__tabs">
 | 
			
		||||
        <div className="tracker__tabs__head">
 | 
			
		||||
          <Link
 | 
			
		||||
            to="/profile/tracker"
 | 
			
		||||
            className="tab active-tab"
 | 
			
		||||
            onClick={() => toggleTabs(1)}
 | 
			
		||||
          >
 | 
			
		||||
            <img src={project} alt="img" />
 | 
			
		||||
            <p>Проекты </p>
 | 
			
		||||
          </Link>
 | 
			
		||||
          <Link
 | 
			
		||||
            to="/profile/tracker"
 | 
			
		||||
            className="tab"
 | 
			
		||||
            onClick={() => toggleTabs(2)}
 | 
			
		||||
          >
 | 
			
		||||
            <img src={tasks} alt="img" />
 | 
			
		||||
            <p>Все мои задачи</p>
 | 
			
		||||
          </Link>
 | 
			
		||||
          <Link
 | 
			
		||||
            to="/profile/tracker"
 | 
			
		||||
            className="tab"
 | 
			
		||||
            onClick={() => toggleTabs(3)}
 | 
			
		||||
          >
 | 
			
		||||
            <img src={archive} alt="img" />
 | 
			
		||||
            <p>Архив</p>
 | 
			
		||||
          </Link>
 | 
			
		||||
        </div>
 | 
			
		||||
        {loader ? (
 | 
			
		||||
          <Loader />
 | 
			
		||||
        ) : (
 | 
			
		||||
          <>
 | 
			
		||||
            <div className="tracker__tabs__content content-tabs">
 | 
			
		||||
              <div className="tasks__head">
 | 
			
		||||
                <div className="tasks__head__wrapper">
 | 
			
		||||
                  <h5>Проект : {projectBoard.name}</h5>
 | 
			
		||||
 | 
			
		||||
                      <TrackerModal
 | 
			
		||||
                          active={modalAddWorker}
 | 
			
		||||
                          setActive={setModalAddWorker}
 | 
			
		||||
                      ></TrackerModal>
 | 
			
		||||
                  <TrackerModal
 | 
			
		||||
                    active={modalAddWorker}
 | 
			
		||||
                    setActive={setModalAddWorker}
 | 
			
		||||
                  ></TrackerModal>
 | 
			
		||||
 | 
			
		||||
                      <div className="tasks__head__persons">
 | 
			
		||||
                        {/*<img src={avatarTest} alt="avatar" />*/}
 | 
			
		||||
                        {/*<img src={avatarTest} alt="avatar" />*/}
 | 
			
		||||
                        <span className="countPersons">{projectBoard.projectUsers?.length}</span>
 | 
			
		||||
                        <span
 | 
			
		||||
                            className="addPerson"
 | 
			
		||||
                            onClick={() => {
 | 
			
		||||
                              setPersonListOpen(true)
 | 
			
		||||
                            }}
 | 
			
		||||
                        >
 | 
			
		||||
                  +
 | 
			
		||||
                </span>
 | 
			
		||||
                        <p>добавить участника</p>
 | 
			
		||||
                        {personListOpen &&
 | 
			
		||||
                            <div className='persons__list'>
 | 
			
		||||
                              <img className='persons__list__close' src={close} alt='close' onClick={() => setPersonListOpen(false)} />
 | 
			
		||||
                              <div className='persons__list__count'><span>{projectBoard.projectUsers?.length}</span>участник</div>
 | 
			
		||||
                              <div className='persons__list__info'>В проекте - <span>“{projectBoard.name}”</span></div>
 | 
			
		||||
                              <div className='persons__list__items'>
 | 
			
		||||
                                {projectBoard.projectUsers?.map((person) => {
 | 
			
		||||
                                  return <div className='persons__list__item' key={person.user_id}>
 | 
			
		||||
                                    <img className='avatar' src={urlForLocal(person.user.avatar)} alt='avatar' />
 | 
			
		||||
                                    <span>{person.user.fio}</span>
 | 
			
		||||
                                    <img className='delete' src={close} alt='delete' onClick={() => deletePerson(person.user_id)}/>
 | 
			
		||||
                                  </div>
 | 
			
		||||
                                })
 | 
			
		||||
                                }
 | 
			
		||||
                              </div>
 | 
			
		||||
                              <div className='persons__list__add'
 | 
			
		||||
                                   onClick={() => {
 | 
			
		||||
                                     dispatch(modalToggle("addWorker"));
 | 
			
		||||
                                     setModalAddWorker(true);
 | 
			
		||||
                                     setPersonListOpen(false)
 | 
			
		||||
                                   }}
 | 
			
		||||
                              >
 | 
			
		||||
                                <span className='addPerson'>+</span>
 | 
			
		||||
                                <p>Добавить участников</p>
 | 
			
		||||
                              </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        }
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <Link to={`/profile/tracker`} className="link">
 | 
			
		||||
                        <div className="tasks__head__back">
 | 
			
		||||
                          <p>Вернуться на проекты</p>
 | 
			
		||||
                          <img src={arrow} alt="arrow" />
 | 
			
		||||
                  <div className="tasks__head__persons">
 | 
			
		||||
                    <span className="countPersons">
 | 
			
		||||
                      {projectBoard.projectUsers?.length}
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <span
 | 
			
		||||
                      className="addPerson"
 | 
			
		||||
                      onClick={() => {
 | 
			
		||||
                        setPersonListOpen(true);
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      +
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <p>добавить участника</p>
 | 
			
		||||
                    {personListOpen && (
 | 
			
		||||
                      <div className="persons__list">
 | 
			
		||||
                        <img
 | 
			
		||||
                          className="persons__list__close"
 | 
			
		||||
                          src={close}
 | 
			
		||||
                          alt="close"
 | 
			
		||||
                          onClick={() => setPersonListOpen(false)}
 | 
			
		||||
                        />
 | 
			
		||||
                        <div className="persons__list__count">
 | 
			
		||||
                          <span>{projectBoard.projectUsers?.length}</span>
 | 
			
		||||
                          участник
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </Link>
 | 
			
		||||
                        <div className="persons__list__info">
 | 
			
		||||
                          В проекте - <span>“{projectBoard.name}”</span>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div className="persons__list__items">
 | 
			
		||||
                          {projectBoard.projectUsers?.map((person) => {
 | 
			
		||||
                            return (
 | 
			
		||||
                              <div
 | 
			
		||||
                                className="persons__list__item"
 | 
			
		||||
                                key={person.user_id}
 | 
			
		||||
                              >
 | 
			
		||||
                                <img
 | 
			
		||||
                                  className="avatar"
 | 
			
		||||
                                  src={urlForLocal(person.user.avatar)}
 | 
			
		||||
                                  alt="avatar"
 | 
			
		||||
                                />
 | 
			
		||||
                                <span>{person.user.fio}</span>
 | 
			
		||||
                                <img
 | 
			
		||||
                                  className="delete"
 | 
			
		||||
                                  src={close}
 | 
			
		||||
                                  alt="delete"
 | 
			
		||||
                                  onClick={() => deletePerson(person.user_id)}
 | 
			
		||||
                                />
 | 
			
		||||
                              </div>
 | 
			
		||||
                            );
 | 
			
		||||
                          })}
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div
 | 
			
		||||
                          className="persons__list__add"
 | 
			
		||||
                          onClick={() => {
 | 
			
		||||
                            dispatch(modalToggle("addWorker"));
 | 
			
		||||
                            setModalAddWorker(true);
 | 
			
		||||
                            setPersonListOpen(false);
 | 
			
		||||
                          }}
 | 
			
		||||
                        >
 | 
			
		||||
                          <span className="addPerson">+</span>
 | 
			
		||||
                          <p>Добавить участников</p>
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    )}
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <Link to={`/profile/tracker`} className="link">
 | 
			
		||||
                    <div className="tasks__head__back">
 | 
			
		||||
                      <p>Вернуться на проекты</p>
 | 
			
		||||
                      <img src={arrow} alt="arrow" />
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </Link>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className="modal-tiket__content ticket">
 | 
			
		||||
              <div className="content ticket-whith">
 | 
			
		||||
                <div className="content__task">
 | 
			
		||||
                  <span>Задача</span>
 | 
			
		||||
                  {editOpen ? (
 | 
			
		||||
                    <input
 | 
			
		||||
                      value={inputsValue.title}
 | 
			
		||||
                      onChange={(e) => {
 | 
			
		||||
                        setInputsValue((prevValue) => ({
 | 
			
		||||
                          ...prevValue,
 | 
			
		||||
                          title: e.target.value,
 | 
			
		||||
                        }));
 | 
			
		||||
                      }}
 | 
			
		||||
                    />
 | 
			
		||||
                  ) : (
 | 
			
		||||
                    <h5>{inputsValue.title}</h5>
 | 
			
		||||
                  )}
 | 
			
		||||
                  <div className="content__description">
 | 
			
		||||
                    {editOpen ? (
 | 
			
		||||
                      <input
 | 
			
		||||
                        value={inputsValue.description}
 | 
			
		||||
                        onChange={(e) => {
 | 
			
		||||
                          setInputsValue((prevValue) => ({
 | 
			
		||||
                            ...prevValue,
 | 
			
		||||
                            description: e.target.value,
 | 
			
		||||
                          }));
 | 
			
		||||
                        }}
 | 
			
		||||
                      />
 | 
			
		||||
                    ) : (
 | 
			
		||||
                      <p>{inputsValue.description}</p>
 | 
			
		||||
                    )}
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div className="content__communication">
 | 
			
		||||
                    <p className="tasks">
 | 
			
		||||
                      <BaseButton
 | 
			
		||||
                        onClick={() => {
 | 
			
		||||
                          dispatch(modalToggle("addSubtask"));
 | 
			
		||||
                          setModalAddWorker(true);
 | 
			
		||||
                        }}
 | 
			
		||||
                        styles={"button-green-add"}
 | 
			
		||||
                      >
 | 
			
		||||
                        <img src={plus}></img>
 | 
			
		||||
                        Добавить под задачу
 | 
			
		||||
                      </BaseButton>
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <p className="file">
 | 
			
		||||
                      <BaseButton styles={"button-add-file"}>
 | 
			
		||||
                        <img src={file}></img>
 | 
			
		||||
                        Загрузить файл
 | 
			
		||||
                      </BaseButton>
 | 
			
		||||
                      <span>{0}</span>
 | 
			
		||||
                      Файлов
 | 
			
		||||
                    </p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div className="content__input">
 | 
			
		||||
                    <input
 | 
			
		||||
                      placeholder="Оставить комментарий"
 | 
			
		||||
                      value={inputsValue.comment}
 | 
			
		||||
                      onChange={(e) => {
 | 
			
		||||
                        setInputsValue((prevValue) => ({
 | 
			
		||||
                          ...prevValue,
 | 
			
		||||
                          comment: e.target.value,
 | 
			
		||||
                        }));
 | 
			
		||||
                      }}
 | 
			
		||||
                    />
 | 
			
		||||
                    <img src={send} onClick={createComment} alt="send"></img>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div className="comments__list">
 | 
			
		||||
                    {comments.map((comment) => {
 | 
			
		||||
                      return (
 | 
			
		||||
                        <TrackerTaskComment
 | 
			
		||||
                          key={comment.id}
 | 
			
		||||
                          taskId={taskInfo.id}
 | 
			
		||||
                          comment={comment}
 | 
			
		||||
                          commentDelete={commentDelete}
 | 
			
		||||
                          addSubComment={addSubComment}
 | 
			
		||||
                          subCommentDelete={subCommentDelete}
 | 
			
		||||
                        />
 | 
			
		||||
                      );
 | 
			
		||||
                    })}
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className="modal-tiket__content ticket">
 | 
			
		||||
                  <div className="content ticket-whith">
 | 
			
		||||
                    <div className="content__task">
 | 
			
		||||
                      <span>Задача</span>
 | 
			
		||||
                      {editOpen ? <input value={inputsValue.title} onChange={(e) => {
 | 
			
		||||
                        setInputsValue((prevValue) => ({...prevValue, title: e.target.value}))
 | 
			
		||||
                      }} /> :<h5>{inputsValue.title}</h5>}
 | 
			
		||||
                      <div className="content__description">
 | 
			
		||||
                        {editOpen ? <input value={inputsValue.description} onChange={(e) => {
 | 
			
		||||
                          setInputsValue((prevValue) => ({...prevValue, description: e.target.value}))
 | 
			
		||||
                        }}/> :<p>{inputsValue.description}</p>}
 | 
			
		||||
                        {/*<img src={task} className="image-task"></img>*/}
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div className="content__communication">
 | 
			
		||||
                        <p className="tasks">
 | 
			
		||||
                          <button
 | 
			
		||||
                              onClick={() => {
 | 
			
		||||
                                dispatch(modalToggle("addSubtask"));
 | 
			
		||||
                                setModalAddWorker(true);
 | 
			
		||||
                              }}
 | 
			
		||||
                          >
 | 
			
		||||
                            <img src={plus} alt='plus'></img>
 | 
			
		||||
                            Добавить под задачу
 | 
			
		||||
                          </button>
 | 
			
		||||
                        </p>
 | 
			
		||||
                        <p className="file">
 | 
			
		||||
                          <button>
 | 
			
		||||
                            <img src={file} alt='file'></img>
 | 
			
		||||
                            Загрузить файл
 | 
			
		||||
                          </button>
 | 
			
		||||
                          <span>{0}</span>
 | 
			
		||||
                          Файлов
 | 
			
		||||
                        </p>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div className="content__input">
 | 
			
		||||
                        <input placeholder="Оставить комментарий" value={inputsValue.comment} onChange={(e) => {
 | 
			
		||||
                          setInputsValue((prevValue) => ({...prevValue, comment: e.target.value}))
 | 
			
		||||
                        }} />
 | 
			
		||||
                        <img src={send} onClick={createComment} alt='send'></img>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div className='comments__list'>
 | 
			
		||||
                        {comments.map((comment) => {
 | 
			
		||||
                          return <TrackerTaskComment
 | 
			
		||||
                              key={comment.id}
 | 
			
		||||
                              taskId={taskInfo.id}
 | 
			
		||||
                              comment={comment}
 | 
			
		||||
                              commentDelete={commentDelete}
 | 
			
		||||
                              addSubComment={addSubComment}
 | 
			
		||||
                              subCommentDelete={subCommentDelete}
 | 
			
		||||
                          />
 | 
			
		||||
                        })
 | 
			
		||||
 | 
			
		||||
                        }
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div className="workers">
 | 
			
		||||
                <div className="workers_box">
 | 
			
		||||
                  <p className="workers__creator">
 | 
			
		||||
                    Создатель : <span>{taskInfo.user?.fio}</span>
 | 
			
		||||
                  </p>
 | 
			
		||||
                  <div>
 | 
			
		||||
                    {Boolean(taskInfo.taskUsers?.length) &&
 | 
			
		||||
                      taskInfo.taskUsers.map((worker, index) => {
 | 
			
		||||
                        return (
 | 
			
		||||
                          <div className="worker" key={index}>
 | 
			
		||||
                            <img src={worker.avatar} alt="worket"></img>
 | 
			
		||||
                            <p>{worker.name}</p>
 | 
			
		||||
                          </div>
 | 
			
		||||
                        );
 | 
			
		||||
                      })}
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div className="workers">
 | 
			
		||||
                    <div className="workers_box">
 | 
			
		||||
                      <p className="workers__creator">
 | 
			
		||||
                        Создатель : <span>{taskInfo.user?.fio}</span>
 | 
			
		||||
                      </p>
 | 
			
		||||
                      <div>
 | 
			
		||||
                        {Boolean(taskInfo.taskUsers?.length) &&
 | 
			
		||||
                            taskInfo.taskUsers.map((worker, index) => {
 | 
			
		||||
                              return (
 | 
			
		||||
                                  <div className="worker" key={index}>
 | 
			
		||||
                                    <img src={worker.avatar} alt='worket'></img>
 | 
			
		||||
                                    <p>{worker.name}</p>
 | 
			
		||||
                                  </div>
 | 
			
		||||
                              );
 | 
			
		||||
                            })}
 | 
			
		||||
                      </div>
 | 
			
		||||
 | 
			
		||||
                      <div className="add-worker moreItems">
 | 
			
		||||
                        <button
 | 
			
		||||
                            onClick={() => {
 | 
			
		||||
                              dispatch(modalToggle("addWorker"));
 | 
			
		||||
                              setModalAddWorker(true);
 | 
			
		||||
                            }}
 | 
			
		||||
                        >
 | 
			
		||||
                          +
 | 
			
		||||
                        </button>
 | 
			
		||||
                        <span>Добавить исполнителя</span>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div className="add-worker moreItems">
 | 
			
		||||
                        <button
 | 
			
		||||
                            onClick={() => {
 | 
			
		||||
                              dispatch(modalToggle("addWorker"));
 | 
			
		||||
                              setModalAddWorker(true);
 | 
			
		||||
                            }}
 | 
			
		||||
                        >
 | 
			
		||||
                          +
 | 
			
		||||
                        </button>
 | 
			
		||||
                        <span>Добавить участников</span>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  <div className="add-worker moreItems">
 | 
			
		||||
                    <BaseButton
 | 
			
		||||
                      onClick={() => {
 | 
			
		||||
                        dispatch(modalToggle("addWorker"));
 | 
			
		||||
                        setModalAddWorker(true);
 | 
			
		||||
                      }}
 | 
			
		||||
                      styles={"button-add-worker"}
 | 
			
		||||
                    >
 | 
			
		||||
                      +
 | 
			
		||||
                    </BaseButton>
 | 
			
		||||
                    <span>Добавить исполнителя</span>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div className="add-worker moreItems">
 | 
			
		||||
                    <BaseButton
 | 
			
		||||
                      onClick={() => {
 | 
			
		||||
                        dispatch(modalToggle("addWorker"));
 | 
			
		||||
                        setModalAddWorker(true);
 | 
			
		||||
                      }}
 | 
			
		||||
                      styles={"button-add-worker"}
 | 
			
		||||
                    >
 | 
			
		||||
                      +
 | 
			
		||||
                    </BaseButton>
 | 
			
		||||
 | 
			
		||||
                    <div className="workers_box-middle">
 | 
			
		||||
                      <div className="time">
 | 
			
		||||
                        <img src={watch} alt='watch'></img>
 | 
			
		||||
                        <span>Длительность : </span>
 | 
			
		||||
                        <p>{"0:00:00"}</p>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    <span>Добавить участников</span>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                      {timerStart ?
 | 
			
		||||
                          <button className="stop" onClick={() => stopTaskTimer()}>
 | 
			
		||||
                            Остановить
 | 
			
		||||
                          </button>
 | 
			
		||||
                          :
 | 
			
		||||
                          <button className={taskInfo.executor_id === Number(localStorage.getItem('id')) ? 'start' : 'start disable'} onClick={() => startTaskTimer()}>
 | 
			
		||||
                            Начать делать <img src={arrow2} alt='arrow'></img>
 | 
			
		||||
                          </button>
 | 
			
		||||
                <div className="workers_box-middle">
 | 
			
		||||
                  <div className="time">
 | 
			
		||||
                    <img src={watch} alt="watch"></img>
 | 
			
		||||
                    <span>Длительность : </span>
 | 
			
		||||
                    <p>{"0:00:00"}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
 | 
			
		||||
                  {timerStart ? (
 | 
			
		||||
                    <button className="stop" onClick={() => stopTaskTimer()}>
 | 
			
		||||
                      Остановить
 | 
			
		||||
                    </button>
 | 
			
		||||
                  ) : (
 | 
			
		||||
                    <button
 | 
			
		||||
                      className={
 | 
			
		||||
                        taskInfo.executor_id ===
 | 
			
		||||
                        Number(localStorage.getItem("id"))
 | 
			
		||||
                          ? "start"
 | 
			
		||||
                          : "start disable"
 | 
			
		||||
                      }
 | 
			
		||||
                    </div>
 | 
			
		||||
                      onClick={() => startTaskTimer()}
 | 
			
		||||
                    >
 | 
			
		||||
                      Начать делать <img src={arrow2} alt="arrow"></img>
 | 
			
		||||
                    </button>
 | 
			
		||||
                  )}
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                    <div className="workers_box-bottom">
 | 
			
		||||
                      <div className={editOpen ? 'edit' : ''} onClick={() => {
 | 
			
		||||
                        if(editOpen) {
 | 
			
		||||
                          setEditOpen(!editOpen)
 | 
			
		||||
                          editTask()
 | 
			
		||||
                        } else {
 | 
			
		||||
                          setEditOpen(!editOpen)
 | 
			
		||||
                        }
 | 
			
		||||
                      }}>
 | 
			
		||||
                        <img src={edit} alt='edit'></img>
 | 
			
		||||
                        <p>{editOpen ? 'сохранить' : 'редактировать'}</p>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div>
 | 
			
		||||
                        <img src={link} alt='link'></img>
 | 
			
		||||
                        <p>ссылка на проект</p>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div>
 | 
			
		||||
                        <img src={archive2} alt='arch'></img>
 | 
			
		||||
                        <p>в архив</p>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div onClick={deleteTask}>
 | 
			
		||||
                        <img src={del} alt='delete'></img>
 | 
			
		||||
                        <p>удалить</p>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                <div className="workers_box-bottom">
 | 
			
		||||
                  <div
 | 
			
		||||
                    className={editOpen ? "edit" : ""}
 | 
			
		||||
                    onClick={() => {
 | 
			
		||||
                      if (editOpen) {
 | 
			
		||||
                        setEditOpen(!editOpen);
 | 
			
		||||
                        editTask();
 | 
			
		||||
                      } else {
 | 
			
		||||
                        setEditOpen(!editOpen);
 | 
			
		||||
                      }
 | 
			
		||||
                    }}
 | 
			
		||||
                  >
 | 
			
		||||
                    <img src={edit} alt="edit"></img>
 | 
			
		||||
                    <p>{editOpen ? "сохранить" : "редактировать"}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div>
 | 
			
		||||
                    <img src={link} alt="link"></img>
 | 
			
		||||
                    <p>ссылка на проект</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div>
 | 
			
		||||
                    <img src={archive2} alt="arch"></img>
 | 
			
		||||
                    <p>в архив</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div onClick={deleteTask}>
 | 
			
		||||
                    <img src={del} alt="delete"></img>
 | 
			
		||||
                    <p>удалить</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
              </>
 | 
			
		||||
          }
 | 
			
		||||
        </div>
 | 
			
		||||
        <Footer />
 | 
			
		||||
      </section>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </>
 | 
			
		||||
        )}
 | 
			
		||||
      </div>
 | 
			
		||||
      <Footer />
 | 
			
		||||
    </section>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +1,28 @@
 | 
			
		||||
import React, {useEffect, useState} from "react";
 | 
			
		||||
 | 
			
		||||
import React, { useEffect, useState } from "react";
 | 
			
		||||
import { useDispatch, useSelector } from "react-redux";
 | 
			
		||||
import { apiRequest } from "../../../api/request";
 | 
			
		||||
import { urlForLocal } from '../../../utils/helper'
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  setColumnName,
 | 
			
		||||
  setColumnPriority,
 | 
			
		||||
  addPersonToProject,
 | 
			
		||||
  editColumnName,
 | 
			
		||||
  editProjectName,
 | 
			
		||||
  getColumnId,
 | 
			
		||||
  getColumnName,
 | 
			
		||||
  getColumnPriority,
 | 
			
		||||
  getProjectBoard,
 | 
			
		||||
  getValueModalType,
 | 
			
		||||
  setColumnName,
 | 
			
		||||
  setColumnPriority,
 | 
			
		||||
  setProject,
 | 
			
		||||
  setProjectBoardFetch,
 | 
			
		||||
  editProjectName,
 | 
			
		||||
  editColumnName,
 | 
			
		||||
  getColumnName,
 | 
			
		||||
  getColumnId,
 | 
			
		||||
  addPersonToProject, getColumnPriority
 | 
			
		||||
} from "../../../redux/projectsTrackerSlice";
 | 
			
		||||
} from "@redux/projectsTrackerSlice";
 | 
			
		||||
 | 
			
		||||
import arrowDown from "../../../assets/icons/arrows/selectArrow.png"
 | 
			
		||||
import { urlForLocal } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import BaseButton from "@components/Common/BaseButton/BaseButton";
 | 
			
		||||
 | 
			
		||||
import arrowDown from "assets/icons/arrows/selectArrow.png";
 | 
			
		||||
 | 
			
		||||
import "./trackerModal.scss";
 | 
			
		||||
 | 
			
		||||
@@ -33,8 +38,8 @@ export const TrackerModal = ({
 | 
			
		||||
  const dispatch = useDispatch();
 | 
			
		||||
  const projectBoard = useSelector(getProjectBoard);
 | 
			
		||||
  const columnName = useSelector(getColumnName);
 | 
			
		||||
  const columnId = useSelector(getColumnId)
 | 
			
		||||
  const columnPriority = useSelector(getColumnPriority)
 | 
			
		||||
  const columnId = useSelector(getColumnId);
 | 
			
		||||
  const columnPriority = useSelector(getColumnPriority);
 | 
			
		||||
 | 
			
		||||
  const modalType = useSelector(getValueModalType);
 | 
			
		||||
  const [projectName, setProjectName] = useState(defautlInput);
 | 
			
		||||
@@ -42,9 +47,9 @@ export const TrackerModal = ({
 | 
			
		||||
  const [nameProject, setNameProject] = useState("");
 | 
			
		||||
  const [valueTiket, setValueTiket] = useState("");
 | 
			
		||||
  const [descriptionTicket, setDescriptionTicket] = useState("");
 | 
			
		||||
  const [workers, setWorkers] = useState([])
 | 
			
		||||
  const [selectWorkersOpen, setSelectWorkersOpen] = useState(false)
 | 
			
		||||
  const [selectedWorker, setSelectedWorker] = useState(null)
 | 
			
		||||
  const [workers, setWorkers] = useState([]);
 | 
			
		||||
  const [selectWorkersOpen, setSelectWorkersOpen] = useState(false);
 | 
			
		||||
  const [selectedWorker, setSelectedWorker] = useState(null);
 | 
			
		||||
 | 
			
		||||
  function createTab() {
 | 
			
		||||
    if (!valueColumn) {
 | 
			
		||||
@@ -55,7 +60,9 @@ export const TrackerModal = ({
 | 
			
		||||
      method: "POST",
 | 
			
		||||
      data: {
 | 
			
		||||
        project_id: projectBoard.id,
 | 
			
		||||
        priority: projectBoard.columns.length ? projectBoard.columns.at(-1).priority + 1 : 1,
 | 
			
		||||
        priority: projectBoard.columns.length
 | 
			
		||||
          ? projectBoard.columns.at(-1).priority + 1
 | 
			
		||||
          : 1,
 | 
			
		||||
        title: valueColumn,
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
@@ -106,36 +113,38 @@ export const TrackerModal = ({
 | 
			
		||||
  function changeColumnParams() {
 | 
			
		||||
    projectBoard.columns.forEach((column) => {
 | 
			
		||||
      if (column.id === columnId && column.priority !== columnPriority) {
 | 
			
		||||
        const priorityColumns = [{
 | 
			
		||||
          column_id: column.id,
 | 
			
		||||
          priority: Number(columnPriority)
 | 
			
		||||
        }]
 | 
			
		||||
        const priorityColumns = [
 | 
			
		||||
          {
 | 
			
		||||
            column_id: column.id,
 | 
			
		||||
            priority: Number(columnPriority),
 | 
			
		||||
          },
 | 
			
		||||
        ];
 | 
			
		||||
        for (let i = column.priority; i < columnPriority; i++) {
 | 
			
		||||
          const currentColumn = {
 | 
			
		||||
            column_id: projectBoard.columns[i].id,
 | 
			
		||||
            priority: i
 | 
			
		||||
          }
 | 
			
		||||
          priorityColumns.push(currentColumn)
 | 
			
		||||
            priority: i,
 | 
			
		||||
          };
 | 
			
		||||
          priorityColumns.push(currentColumn);
 | 
			
		||||
        }
 | 
			
		||||
        for (let i = column.priority; i > columnPriority; i--) {
 | 
			
		||||
          const currentColumn = {
 | 
			
		||||
            column_id: projectBoard.columns[i - 2].id,
 | 
			
		||||
            priority: i
 | 
			
		||||
          }
 | 
			
		||||
          priorityColumns.push(currentColumn)
 | 
			
		||||
            priority: i,
 | 
			
		||||
          };
 | 
			
		||||
          priorityColumns.push(currentColumn);
 | 
			
		||||
        }
 | 
			
		||||
        apiRequest("/project-column/set-priority", {
 | 
			
		||||
          method: "POST",
 | 
			
		||||
          data: {
 | 
			
		||||
            project_id: projectBoard.id,
 | 
			
		||||
            data: JSON.stringify(priorityColumns)
 | 
			
		||||
          }
 | 
			
		||||
            data: JSON.stringify(priorityColumns),
 | 
			
		||||
          },
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          dispatch(setProjectBoardFetch(projectBoard.id));
 | 
			
		||||
        })
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    changeColumnTitle()
 | 
			
		||||
    });
 | 
			
		||||
    changeColumnTitle();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function changeColumnTitle() {
 | 
			
		||||
@@ -263,9 +272,9 @@ export const TrackerModal = ({
 | 
			
		||||
                )}
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <button className="button-add" onClick={addUserToProject}>
 | 
			
		||||
            <BaseButton styles={"button-add"} onClick={addUserToProject}>
 | 
			
		||||
              Добавить
 | 
			
		||||
            </button>
 | 
			
		||||
            </BaseButton>
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
        {modalType === "createTiketProject" && (
 | 
			
		||||
@@ -289,9 +298,9 @@ export const TrackerModal = ({
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <button className="button-add" onClick={createTiket}>
 | 
			
		||||
            <BaseButton styles={"button-add"} onClick={createTiket}>
 | 
			
		||||
              Создать
 | 
			
		||||
            </button>
 | 
			
		||||
            </BaseButton>
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
        {modalType === "editProject" && (
 | 
			
		||||
@@ -306,9 +315,10 @@ export const TrackerModal = ({
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <button className="button-add" onClick={editProject}>
 | 
			
		||||
 | 
			
		||||
            <BaseButton styles={"button-add"} onClick={editProject}>
 | 
			
		||||
              Сохранить
 | 
			
		||||
            </button>
 | 
			
		||||
            </BaseButton>
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
        {modalType === "createProject" && (
 | 
			
		||||
@@ -322,9 +332,9 @@ export const TrackerModal = ({
 | 
			
		||||
                  onChange={(e) => setNameProject(e.target.value)}
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
              <button className="button-add" onClick={createProject}>
 | 
			
		||||
              <BaseButton styles={"button-add"} onClick={createProject}>
 | 
			
		||||
                Создать
 | 
			
		||||
              </button>
 | 
			
		||||
              </BaseButton>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
@@ -340,9 +350,12 @@ export const TrackerModal = ({
 | 
			
		||||
                <textarea className="title-project__textarea"></textarea>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <button className="button-add" onClick={(e) => e.preventDefault()}>
 | 
			
		||||
            <BaseButton
 | 
			
		||||
              styles={"button-add"}
 | 
			
		||||
              onClick={(e) => e.preventDefault()}
 | 
			
		||||
            >
 | 
			
		||||
              Добавить
 | 
			
		||||
            </button>
 | 
			
		||||
            </BaseButton>
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
        {modalType === "createColumn" && (
 | 
			
		||||
@@ -357,9 +370,9 @@ export const TrackerModal = ({
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <button className="button-add" onClick={createTab}>
 | 
			
		||||
            <BaseButton styles={"button-add"} onClick={createTab}>
 | 
			
		||||
              Создать
 | 
			
		||||
            </button>
 | 
			
		||||
            </BaseButton>
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
        {modalType === "editColumn" && (
 | 
			
		||||
@@ -376,18 +389,18 @@ export const TrackerModal = ({
 | 
			
		||||
              <h4>Приоритет колонки</h4>
 | 
			
		||||
              <div className="input-container">
 | 
			
		||||
                <input
 | 
			
		||||
                    className="name-project"
 | 
			
		||||
                    placeholder='Приоритет колонки'
 | 
			
		||||
                    type='number'
 | 
			
		||||
                    step='1'
 | 
			
		||||
                    value={columnPriority}
 | 
			
		||||
                    onChange={(e) => dispatch(setColumnPriority(e.target.value))}
 | 
			
		||||
                  className="name-project"
 | 
			
		||||
                  placeholder="Приоритет колонки"
 | 
			
		||||
                  type="number"
 | 
			
		||||
                  step="1"
 | 
			
		||||
                  value={columnPriority}
 | 
			
		||||
                  onChange={(e) => dispatch(setColumnPriority(e.target.value))}
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <button className="button-add" onClick={changeColumnParams}>
 | 
			
		||||
            <BaseButton styles={"button-add"} onClick={changeColumnParams}>
 | 
			
		||||
              Сохранить
 | 
			
		||||
            </button>
 | 
			
		||||
            </BaseButton>
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										171
									
								
								src/components/Modal/Tracker/TrackerModal/trackerModal.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								src/components/Modal/Tracker/TrackerModal/trackerModal.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,171 @@
 | 
			
		||||
//Удалить при переходе всех модалок в обертку modalLayout
 | 
			
		||||
.modal-add {
 | 
			
		||||
  z-index: 9;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  background-color: rgba(0, 0, 0, 0.11);
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  transform: scale(0);
 | 
			
		||||
 | 
			
		||||
  &__content {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    width: 424px;
 | 
			
		||||
    background: linear-gradient(180deg, #ffffff 0%, #ebebeb 100%);
 | 
			
		||||
    border-radius: 24px;
 | 
			
		||||
 | 
			
		||||
    padding: 60px 60px 30px 60px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.title-project {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  margin: 0 0 15px 0;
 | 
			
		||||
 | 
			
		||||
  .input-container {
 | 
			
		||||
    width: 287px;
 | 
			
		||||
    height: 35px;
 | 
			
		||||
    background: #ffffff;
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
    margin: 12px 0;
 | 
			
		||||
 | 
			
		||||
    input::-webkit-inner-spin-button {
 | 
			
		||||
      -webkit-appearance: none;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  h4 {
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
    font-size: 22px;
 | 
			
		||||
    line-height: 26px;
 | 
			
		||||
    color: #263238 !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__decs {
 | 
			
		||||
    font-weight: 300;
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
    line-height: 14px;
 | 
			
		||||
    margin: 12px 0 16px 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__textarea {
 | 
			
		||||
    resize: none;
 | 
			
		||||
    width: 302px;
 | 
			
		||||
    height: 83px;
 | 
			
		||||
    background: #ffffff;
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
    border: none;
 | 
			
		||||
    font-size: 15px;
 | 
			
		||||
    line-height: 18px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .select__worker {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: space-between;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    padding: 5px;
 | 
			
		||||
    background: white;
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    position: relative;
 | 
			
		||||
 | 
			
		||||
    p {
 | 
			
		||||
      max-width: 150px;
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
      white-space: nowrap;
 | 
			
		||||
      text-overflow: ellipsis;
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    img {
 | 
			
		||||
      transition: all 0.3s ease;
 | 
			
		||||
      width: 16px;
 | 
			
		||||
      height: 16px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__dropDown {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      padding: 5px;
 | 
			
		||||
      top: 35px;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      background: white;
 | 
			
		||||
      border-radius: 5px;
 | 
			
		||||
      row-gap: 5px;
 | 
			
		||||
 | 
			
		||||
      .worker {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        justify-content: space-between;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .open {
 | 
			
		||||
    .arrow {
 | 
			
		||||
      transform: rotate(180deg);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.name-project {
 | 
			
		||||
  margin-left: 10px;
 | 
			
		||||
  border: none;
 | 
			
		||||
  outline: none;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 90%;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-add {
 | 
			
		||||
  width: 130px;
 | 
			
		||||
  height: 37px;
 | 
			
		||||
 | 
			
		||||
  font-weight: 400;
 | 
			
		||||
  font-size: 15px;
 | 
			
		||||
  line-height: 32px;
 | 
			
		||||
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  margin: 0 auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.modal-add.active {
 | 
			
		||||
  transform: scale(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.exit {
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 35px;
 | 
			
		||||
  right: 40px;
 | 
			
		||||
 | 
			
		||||
  &:before,
 | 
			
		||||
  &:after {
 | 
			
		||||
    content: "";
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    width: 16px;
 | 
			
		||||
    height: 2px;
 | 
			
		||||
    background: #263238;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &:before {
 | 
			
		||||
    transform: rotate(45deg);
 | 
			
		||||
  }
 | 
			
		||||
  &:after {
 | 
			
		||||
    transform: rotate(-45deg);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -7,7 +7,7 @@ import { deleteProject, modalToggle } from "@redux/projectsTrackerSlice";
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import { ModalSelect } from "@components/Modal/ModalSelect/ModalSelect";
 | 
			
		||||
import TrackerModal from "@components/Modal/TrackerModal/TrackerModal";
 | 
			
		||||
import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal";
 | 
			
		||||
 | 
			
		||||
import archiveSet from "assets/icons/archive.svg";
 | 
			
		||||
import del from "assets/icons/delete.svg";
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,12 @@
 | 
			
		||||
  padding: 17px 26px 16px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  max-width: 440px;
 | 
			
		||||
  transition: 0.4s;
 | 
			
		||||
 | 
			
		||||
  &:hover {
 | 
			
		||||
    transition: 0.4s;
 | 
			
		||||
    box-shadow: 4px 4px 8px 0px rgba(34, 60, 80, 0.11);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media (max-width: 1068px) {
 | 
			
		||||
    width: 47%;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,129 +1,164 @@
 | 
			
		||||
import React, { useState } from "react";
 | 
			
		||||
import TrackerTaskSubComment from "../TrackerTaskComment/TrackerTaskComment";
 | 
			
		||||
import { apiRequest } from "../../api/request";
 | 
			
		||||
import {urlForLocal} from '../../utils/helper';
 | 
			
		||||
import {getCorrectDate} from "../Calendar/calendarHelper";
 | 
			
		||||
import edit from "../../assets/icons/edit.svg";
 | 
			
		||||
import del from "../../assets/icons/delete.svg";
 | 
			
		||||
import accept from "../../assets/images/accept.png";
 | 
			
		||||
 | 
			
		||||
import { urlForLocal } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import { getCorrectDate } from "@components/Calendar/calendarHelper";
 | 
			
		||||
import TrackerTaskSubComment from "@components/TrackerTaskComment/TrackerTaskComment";
 | 
			
		||||
 | 
			
		||||
import del from "assets/icons/delete.svg";
 | 
			
		||||
import edit from "assets/icons/edit.svg";
 | 
			
		||||
import accept from "assets/images/accept.png";
 | 
			
		||||
 | 
			
		||||
export const TrackerTaskComment = ({
 | 
			
		||||
    taskId,
 | 
			
		||||
    comment,
 | 
			
		||||
    commentDelete,
 | 
			
		||||
    addSubComment,
 | 
			
		||||
    subCommentDelete
 | 
			
		||||
  taskId,
 | 
			
		||||
  comment,
 | 
			
		||||
  commentDelete,
 | 
			
		||||
  addSubComment,
 | 
			
		||||
  subCommentDelete,
 | 
			
		||||
}) => {
 | 
			
		||||
    const [commentsEditOpen, setCommentsEditOpen] = useState(false)
 | 
			
		||||
    const [commentsEditText, setCommentsEditText] = useState(comment.text)
 | 
			
		||||
    const [subCommentsCreateOpen, setSubCommentsCreateOpen] = useState(false)
 | 
			
		||||
    const [subCommentsCreateText, setSubCommentsCreateText] = useState('')
 | 
			
		||||
  const [commentsEditOpen, setCommentsEditOpen] = useState(false);
 | 
			
		||||
  const [commentsEditText, setCommentsEditText] = useState(comment.text);
 | 
			
		||||
  const [subCommentsCreateOpen, setSubCommentsCreateOpen] = useState(false);
 | 
			
		||||
  const [subCommentsCreateText, setSubCommentsCreateText] = useState("");
 | 
			
		||||
 | 
			
		||||
    function editComment() {
 | 
			
		||||
        if (commentsEditText === comment.text) return
 | 
			
		||||
        apiRequest("/comment/update", {
 | 
			
		||||
            method: "PUT",
 | 
			
		||||
            data: {
 | 
			
		||||
                comment_id: comment.id,
 | 
			
		||||
                text: commentsEditText
 | 
			
		||||
            }
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
  function editComment() {
 | 
			
		||||
    if (commentsEditText === comment.text) return;
 | 
			
		||||
    apiRequest("/comment/update", {
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        comment_id: comment.id,
 | 
			
		||||
        text: commentsEditText,
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    function deleteComment() {
 | 
			
		||||
        apiRequest("/comment/update", {
 | 
			
		||||
            method: "PUT",
 | 
			
		||||
            data: {
 | 
			
		||||
                comment_id: comment.id,
 | 
			
		||||
                status: 0
 | 
			
		||||
            }
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
            if (comment.parent_id) {
 | 
			
		||||
                subCommentDelete(comment)
 | 
			
		||||
            } else {
 | 
			
		||||
                commentDelete(comment)
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
  function deleteComment() {
 | 
			
		||||
    apiRequest("/comment/update", {
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        comment_id: comment.id,
 | 
			
		||||
        status: 0,
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      if (comment.parent_id) {
 | 
			
		||||
        subCommentDelete(comment);
 | 
			
		||||
      } else {
 | 
			
		||||
        commentDelete(comment);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    function createSubComment() {
 | 
			
		||||
        setSubCommentsCreateOpen(false)
 | 
			
		||||
        if(!subCommentsCreateText) return
 | 
			
		||||
        apiRequest("/comment/create", {
 | 
			
		||||
            method: "POST",
 | 
			
		||||
            data: {
 | 
			
		||||
                text: subCommentsCreateText,
 | 
			
		||||
                entity_type: 2,
 | 
			
		||||
                entity_id: taskId,
 | 
			
		||||
                parent_id: comment.id
 | 
			
		||||
            }
 | 
			
		||||
        }).then((res) => {
 | 
			
		||||
            let newSubComment = res
 | 
			
		||||
            newSubComment.created_at = new Date()
 | 
			
		||||
            setSubCommentsCreateText('')
 | 
			
		||||
            addSubComment(comment.id, newSubComment)
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
  function createSubComment() {
 | 
			
		||||
    setSubCommentsCreateOpen(false);
 | 
			
		||||
    if (!subCommentsCreateText) return;
 | 
			
		||||
    apiRequest("/comment/create", {
 | 
			
		||||
      method: "POST",
 | 
			
		||||
      data: {
 | 
			
		||||
        text: subCommentsCreateText,
 | 
			
		||||
        entity_type: 2,
 | 
			
		||||
        entity_id: taskId,
 | 
			
		||||
        parent_id: comment.id,
 | 
			
		||||
      },
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      let newSubComment = res;
 | 
			
		||||
      newSubComment.created_at = new Date();
 | 
			
		||||
      setSubCommentsCreateText("");
 | 
			
		||||
      addSubComment(comment.id, newSubComment);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div className={[!comment.parent_id && comment.subComments.length ? 'comments__list__item__main': '',
 | 
			
		||||
            'comments__list__item',
 | 
			
		||||
            comment.parent_id ? 'comments__list__item__subComment' : ''].join(' ')}>
 | 
			
		||||
            <div className='comments__list__item__info'>
 | 
			
		||||
                <div className='comments__list__item__fio'>
 | 
			
		||||
                    <img src={urlForLocal(comment.user.avatar)} alt='avatar' />
 | 
			
		||||
                    <p>{comment.user.fio}</p>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className='comments__list__item__date'>
 | 
			
		||||
                    <span>{getCorrectDate(comment.created_at)}</span>
 | 
			
		||||
                    {comment.user_id === Number(localStorage.getItem('id')) &&
 | 
			
		||||
                        <>
 | 
			
		||||
                        <div className={commentsEditOpen ? 'edit edit__open' : 'edit'} >
 | 
			
		||||
                            <img src={edit} alt='edit' onClick={() => {
 | 
			
		||||
                                if (commentsEditOpen) {
 | 
			
		||||
                                    editComment()
 | 
			
		||||
                                }
 | 
			
		||||
                                setCommentsEditOpen(!commentsEditOpen)
 | 
			
		||||
                            }} />
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <img src={del} alt='delete' onClick={() => deleteComment()} />
 | 
			
		||||
                        </>
 | 
			
		||||
                    }
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            {commentsEditOpen ?
 | 
			
		||||
                <input className='comments__list__item__text' value={commentsEditText} onChange={(e) =>  {
 | 
			
		||||
                    setCommentsEditText(e.target.value)
 | 
			
		||||
                }} /> :
 | 
			
		||||
                <p className='comments__list__item__text'>{commentsEditText}</p>}
 | 
			
		||||
            {!comment.parent_id &&
 | 
			
		||||
                <>
 | 
			
		||||
                {
 | 
			
		||||
                    subCommentsCreateOpen ?
 | 
			
		||||
                        <div className='comments__list__item__answer__new'>
 | 
			
		||||
                            <input value={subCommentsCreateText} onChange={(e) => {
 | 
			
		||||
                                setSubCommentsCreateText(e.target.value)
 | 
			
		||||
                            }}/>
 | 
			
		||||
                            <img src={accept} alt='accept'
 | 
			
		||||
                                 onClick={() => {
 | 
			
		||||
                                     createSubComment()
 | 
			
		||||
                                 }}
 | 
			
		||||
                            />
 | 
			
		||||
                        </div>
 | 
			
		||||
                        :
 | 
			
		||||
                        <span onClick={() => {
 | 
			
		||||
                            setSubCommentsCreateOpen(true)
 | 
			
		||||
                        }} className='comments__list__item__answer'>Ответить</span>
 | 
			
		||||
                    }
 | 
			
		||||
                </>
 | 
			
		||||
            }
 | 
			
		||||
            {Boolean(comment.subComments?.length) && comment.subComments.map((subComment) => {
 | 
			
		||||
                return <TrackerTaskSubComment key={subComment.id} taskId={taskId} comment={subComment} subCommentDelete={subCommentDelete}/>
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      className={[
 | 
			
		||||
        !comment.parent_id && comment.subComments.length
 | 
			
		||||
          ? "comments__list__item__main"
 | 
			
		||||
          : "",
 | 
			
		||||
        "comments__list__item",
 | 
			
		||||
        comment.parent_id ? "comments__list__item__subComment" : "",
 | 
			
		||||
      ].join(" ")}
 | 
			
		||||
    >
 | 
			
		||||
      <div className="comments__list__item__info">
 | 
			
		||||
        <div className="comments__list__item__fio">
 | 
			
		||||
          <img src={urlForLocal(comment.user.avatar)} alt="avatar" />
 | 
			
		||||
          <p>{comment.user.fio}</p>
 | 
			
		||||
        </div>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
        <div className="comments__list__item__date">
 | 
			
		||||
          <span>{getCorrectDate(comment.created_at)}</span>
 | 
			
		||||
          {comment.user_id === Number(localStorage.getItem("id")) && (
 | 
			
		||||
            <>
 | 
			
		||||
              <div className={commentsEditOpen ? "edit edit__open" : "edit"}>
 | 
			
		||||
                <img
 | 
			
		||||
                  src={edit}
 | 
			
		||||
                  alt="edit"
 | 
			
		||||
                  onClick={() => {
 | 
			
		||||
                    if (commentsEditOpen) {
 | 
			
		||||
                      editComment();
 | 
			
		||||
                    }
 | 
			
		||||
                    setCommentsEditOpen(!commentsEditOpen);
 | 
			
		||||
                  }}
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
              <img src={del} alt="delete" onClick={() => deleteComment()} />
 | 
			
		||||
            </>
 | 
			
		||||
          )}
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      {commentsEditOpen ? (
 | 
			
		||||
        <input
 | 
			
		||||
          className="comments__list__item__text"
 | 
			
		||||
          value={commentsEditText}
 | 
			
		||||
          onChange={(e) => {
 | 
			
		||||
            setCommentsEditText(e.target.value);
 | 
			
		||||
          }}
 | 
			
		||||
        />
 | 
			
		||||
      ) : (
 | 
			
		||||
        <p className="comments__list__item__text">{commentsEditText}</p>
 | 
			
		||||
      )}
 | 
			
		||||
      {!comment.parent_id && (
 | 
			
		||||
        <>
 | 
			
		||||
          {subCommentsCreateOpen ? (
 | 
			
		||||
            <div className="comments__list__item__answer__new">
 | 
			
		||||
              <input
 | 
			
		||||
                value={subCommentsCreateText}
 | 
			
		||||
                onChange={(e) => {
 | 
			
		||||
                  setSubCommentsCreateText(e.target.value);
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
              <img
 | 
			
		||||
                src={accept}
 | 
			
		||||
                alt="accept"
 | 
			
		||||
                onClick={() => {
 | 
			
		||||
                  createSubComment();
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            </div>
 | 
			
		||||
          ) : (
 | 
			
		||||
            <span
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
                setSubCommentsCreateOpen(true);
 | 
			
		||||
              }}
 | 
			
		||||
              className="comments__list__item__answer"
 | 
			
		||||
            >
 | 
			
		||||
              Ответить
 | 
			
		||||
            </span>
 | 
			
		||||
          )}
 | 
			
		||||
        </>
 | 
			
		||||
      )}
 | 
			
		||||
      {Boolean(comment.subComments?.length) &&
 | 
			
		||||
        comment.subComments.map((subComment) => {
 | 
			
		||||
          return (
 | 
			
		||||
            <TrackerTaskSubComment
 | 
			
		||||
              key={subComment.id}
 | 
			
		||||
              taskId={taskId}
 | 
			
		||||
              comment={subComment}
 | 
			
		||||
              subCommentDelete={subCommentDelete}
 | 
			
		||||
            />
 | 
			
		||||
          );
 | 
			
		||||
        })}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default TrackerTaskComment
 | 
			
		||||
export default TrackerTaskComment;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +1,30 @@
 | 
			
		||||
import React, {useEffect, useState} from "react";
 | 
			
		||||
import React, { useEffect, useState } from "react";
 | 
			
		||||
import { useDispatch, useSelector } from "react-redux";
 | 
			
		||||
import { Link } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
import { getProfileInfo } from "@redux/outstaffingSlice";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "../../../api/request";
 | 
			
		||||
import archive from "../../../assets/icons/archive.svg";
 | 
			
		||||
import arrow from "../../../assets/icons/arrows/arrowStart.png";
 | 
			
		||||
import fullScreen from "../../../assets/icons/arrows/inFullScreen.svg";
 | 
			
		||||
import category from "../../../assets/icons/category.svg";
 | 
			
		||||
import close from "../../../assets/icons/closeProjectPersons.svg";
 | 
			
		||||
import del from "../../../assets/icons/delete.svg";
 | 
			
		||||
import edit from "../../../assets/icons/edit.svg";
 | 
			
		||||
import file from "../../../assets/icons/fileModal.svg";
 | 
			
		||||
import link from "../../../assets/icons/link.svg";
 | 
			
		||||
import plus from "../../../assets/icons/plus.svg";
 | 
			
		||||
import send from "../../../assets/icons/send.svg";
 | 
			
		||||
import watch from "../../../assets/icons/watch.svg";
 | 
			
		||||
import TrackerModal from "../../../components/Modal/TrackerModal/TrackerModal";
 | 
			
		||||
import TrackerTaskComment from "../../../components/TrackerTaskComment/TrackerTaskComment";
 | 
			
		||||
import { apiRequest } from "../../../api/request";
 | 
			
		||||
import {useDispatch, useSelector} from "react-redux";
 | 
			
		||||
import "./modalTicket.scss"
 | 
			
		||||
import {
 | 
			
		||||
  modalToggle,
 | 
			
		||||
  setProjectBoardFetch,
 | 
			
		||||
} from "../../../redux/projectsTrackerSlice";
 | 
			
		||||
 | 
			
		||||
import category from "../../../assets/icons/category.svg";
 | 
			
		||||
import watch from "../../../assets/icons/watch.svg";
 | 
			
		||||
import file from "../../../assets/icons/fileModal.svg";
 | 
			
		||||
import arrow from "../../../assets/icons/arrows/arrowStart.png";
 | 
			
		||||
import link from "../../../assets/icons/link.svg";
 | 
			
		||||
import archive from "../../../assets/icons/archive.svg";
 | 
			
		||||
import del from "../../../assets/icons/delete.svg";
 | 
			
		||||
import edit from "../../../assets/icons/edit.svg";
 | 
			
		||||
import send from "../../../assets/icons/send.svg";
 | 
			
		||||
import plus from "../../../assets/icons/plus.svg";
 | 
			
		||||
import fullScreen from "../../../assets/icons/arrows/inFullScreen.svg";
 | 
			
		||||
import close from "../../../assets/icons/closeProjectPersons.svg";
 | 
			
		||||
 | 
			
		||||
import {urlForLocal, getCorrectRequestDate} from "../../../utils/helper";
 | 
			
		||||
import {getProfileInfo} from "@redux/outstaffingSlice";
 | 
			
		||||
import { getCorrectRequestDate, urlForLocal } from "../../../utils/helper";
 | 
			
		||||
import "./modalTicket.scss";
 | 
			
		||||
 | 
			
		||||
export const ModalTiсket = ({
 | 
			
		||||
  active,
 | 
			
		||||
@@ -32,28 +32,32 @@ export const ModalTiсket = ({
 | 
			
		||||
  task,
 | 
			
		||||
  projectId,
 | 
			
		||||
  projectName,
 | 
			
		||||
  projectUsers
 | 
			
		||||
  projectUsers,
 | 
			
		||||
}) => {
 | 
			
		||||
  const dispatch = useDispatch();
 | 
			
		||||
  const [addSubtask, setAddSubtask] = useState(false);
 | 
			
		||||
  const [editOpen, setEditOpen] = useState(false);
 | 
			
		||||
  const [inputsValue, setInputsValue] = useState({title: task.title, description: task.description, comment: ''});
 | 
			
		||||
  const [inputsValue, setInputsValue] = useState({
 | 
			
		||||
    title: task.title,
 | 
			
		||||
    description: task.description,
 | 
			
		||||
    comment: "",
 | 
			
		||||
  });
 | 
			
		||||
  const [comments, setComments] = useState([]);
 | 
			
		||||
  const [dropListOpen, setDropListOpen] = useState(false)
 | 
			
		||||
  const [dropListMembersOpen, setDropListMembersOpen] = useState(false)
 | 
			
		||||
  const [executor, setExecutor] = useState(task.executor)
 | 
			
		||||
  const [members, setMembers] = useState(task.taskUsers)
 | 
			
		||||
  const [users, setUsers] = useState([])
 | 
			
		||||
  const [timerStart, setTimerStart] = useState(false)
 | 
			
		||||
  const [timerInfo, setTimerInfo] = useState({})
 | 
			
		||||
  const [dropListOpen, setDropListOpen] = useState(false);
 | 
			
		||||
  const [dropListMembersOpen, setDropListMembersOpen] = useState(false);
 | 
			
		||||
  const [executor, setExecutor] = useState(task.executor);
 | 
			
		||||
  const [members, setMembers] = useState(task.taskUsers);
 | 
			
		||||
  const [users, setUsers] = useState([]);
 | 
			
		||||
  const [timerStart, setTimerStart] = useState(false);
 | 
			
		||||
  const [timerInfo, setTimerInfo] = useState({});
 | 
			
		||||
  const [currentTimerCount, setCurrentTimerCount] = useState({
 | 
			
		||||
    hours: 0,
 | 
			
		||||
    minute: 0,
 | 
			
		||||
    seconds: 0
 | 
			
		||||
  })
 | 
			
		||||
  const [timerId, setTimerId] = useState(null)
 | 
			
		||||
  const [correctProjectUsers, setCorrectProjectUsers] = useState(projectUsers)
 | 
			
		||||
  const [executorId, setExecutorId] = useState(task.executor_id)
 | 
			
		||||
    seconds: 0,
 | 
			
		||||
  });
 | 
			
		||||
  const [timerId, setTimerId] = useState(null);
 | 
			
		||||
  const [correctProjectUsers, setCorrectProjectUsers] = useState(projectUsers);
 | 
			
		||||
  const [executorId, setExecutorId] = useState(task.executor_id);
 | 
			
		||||
  const profileInfo = useSelector(getProfileInfo);
 | 
			
		||||
 | 
			
		||||
  function deleteTask() {
 | 
			
		||||
@@ -75,7 +79,7 @@ export const ModalTiсket = ({
 | 
			
		||||
      data: {
 | 
			
		||||
        task_id: task.id,
 | 
			
		||||
        title: inputsValue.title,
 | 
			
		||||
        description: inputsValue.description
 | 
			
		||||
        description: inputsValue.description,
 | 
			
		||||
      },
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectId));
 | 
			
		||||
@@ -88,19 +92,21 @@ export const ModalTiсket = ({
 | 
			
		||||
      data: {
 | 
			
		||||
        text: inputsValue.comment,
 | 
			
		||||
        entity_type: 2,
 | 
			
		||||
        entity_id: task.id
 | 
			
		||||
      }
 | 
			
		||||
        entity_id: task.id,
 | 
			
		||||
      },
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      let newComment = res
 | 
			
		||||
      newComment.created_at = new Date()
 | 
			
		||||
      newComment.subComments = []
 | 
			
		||||
      setInputsValue((prevValue) => ({...prevValue, comment: ''}))
 | 
			
		||||
      setComments((prevValue) => ([...prevValue, newComment]))
 | 
			
		||||
    })
 | 
			
		||||
      let newComment = res;
 | 
			
		||||
      newComment.created_at = new Date();
 | 
			
		||||
      newComment.subComments = [];
 | 
			
		||||
      setInputsValue((prevValue) => ({ ...prevValue, comment: "" }));
 | 
			
		||||
      setComments((prevValue) => [...prevValue, newComment]);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function commentDelete(comment) {
 | 
			
		||||
    setComments((prevValue) => prevValue.filter((item) => item.id !== comment.id))
 | 
			
		||||
    setComments((prevValue) =>
 | 
			
		||||
      prevValue.filter((item) => item.id !== comment.id)
 | 
			
		||||
    );
 | 
			
		||||
    if (comment.subComments.length) {
 | 
			
		||||
      // promiseAll
 | 
			
		||||
      comment.subComments.forEach((subComment) => {
 | 
			
		||||
@@ -108,32 +114,33 @@ export const ModalTiсket = ({
 | 
			
		||||
          method: "PUT",
 | 
			
		||||
          data: {
 | 
			
		||||
            comment_id: subComment.id,
 | 
			
		||||
            status: 0
 | 
			
		||||
          }
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
            status: 0,
 | 
			
		||||
          },
 | 
			
		||||
        }).then(() => {});
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function addSubComment(commentId, subComment) {
 | 
			
		||||
    const addSubComment = comments
 | 
			
		||||
    const addSubComment = comments;
 | 
			
		||||
    addSubComment.forEach((comment) => {
 | 
			
		||||
      if (comment.id === commentId) {
 | 
			
		||||
        comment.subComments.push(subComment)
 | 
			
		||||
        comment.subComments.push(subComment);
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    setComments(addSubComment)
 | 
			
		||||
    });
 | 
			
		||||
    setComments(addSubComment);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function subCommentDelete(subComment) {
 | 
			
		||||
    const deleteSubComment = comments
 | 
			
		||||
    const deleteSubComment = comments;
 | 
			
		||||
    deleteSubComment.forEach((comment, index) => {
 | 
			
		||||
      if (comment.id === subComment.parent_id) {
 | 
			
		||||
        deleteSubComment[index].subComments = comment.subComments.filter((item) => item.id !== subComment.id)
 | 
			
		||||
        deleteSubComment[index].subComments = comment.subComments.filter(
 | 
			
		||||
          (item) => item.id !== subComment.id
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    setComments([...deleteSubComment])
 | 
			
		||||
    });
 | 
			
		||||
    setComments([...deleteSubComment]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function startTaskTimer() {
 | 
			
		||||
@@ -142,13 +149,13 @@ export const ModalTiсket = ({
 | 
			
		||||
      data: {
 | 
			
		||||
        entity_type: 2,
 | 
			
		||||
        entity_id: task.id,
 | 
			
		||||
        created_at: getCorrectRequestDate(new Date())
 | 
			
		||||
      }
 | 
			
		||||
        created_at: getCorrectRequestDate(new Date()),
 | 
			
		||||
      },
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      setTimerStart(true)
 | 
			
		||||
      setTimerInfo(res)
 | 
			
		||||
      startTimer()
 | 
			
		||||
    })
 | 
			
		||||
      setTimerStart(true);
 | 
			
		||||
      setTimerInfo(res);
 | 
			
		||||
      startTimer();
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function stopTaskTimer() {
 | 
			
		||||
@@ -156,12 +163,12 @@ export const ModalTiсket = ({
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        timer_id: timerInfo.id,
 | 
			
		||||
        stopped_at: getCorrectRequestDate(new Date())
 | 
			
		||||
      }
 | 
			
		||||
        stopped_at: getCorrectRequestDate(new Date()),
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      setTimerStart(false)
 | 
			
		||||
      clearInterval(timerId)
 | 
			
		||||
    })
 | 
			
		||||
      setTimerStart(false);
 | 
			
		||||
      clearInterval(timerId);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function taskExecutor(person) {
 | 
			
		||||
@@ -169,12 +176,12 @@ export const ModalTiсket = ({
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        task_id: task.id,
 | 
			
		||||
        executor_id: person.user_id
 | 
			
		||||
        executor_id: person.user_id,
 | 
			
		||||
      },
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      setExecutorId(person.user_id)
 | 
			
		||||
      setDropListOpen(false)
 | 
			
		||||
      setExecutor(res.executor)
 | 
			
		||||
      setExecutorId(person.user_id);
 | 
			
		||||
      setDropListOpen(false);
 | 
			
		||||
      setExecutor(res.executor);
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectId));
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
@@ -184,10 +191,10 @@ export const ModalTiсket = ({
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        task_id: task.id,
 | 
			
		||||
        executor_id: 0
 | 
			
		||||
        executor_id: 0,
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      setExecutorId(null)
 | 
			
		||||
      setExecutorId(null);
 | 
			
		||||
      setExecutor(null);
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectId));
 | 
			
		||||
    });
 | 
			
		||||
@@ -198,11 +205,11 @@ export const ModalTiсket = ({
 | 
			
		||||
      method: "POST",
 | 
			
		||||
      data: {
 | 
			
		||||
        task_id: task.id,
 | 
			
		||||
        user_id: person.user_id
 | 
			
		||||
        user_id: person.user_id,
 | 
			
		||||
      },
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      setDropListMembersOpen(false)
 | 
			
		||||
      setMembers((prevValue) => ([...prevValue, res]))
 | 
			
		||||
      setDropListMembersOpen(false);
 | 
			
		||||
      setMembers((prevValue) => [...prevValue, res]);
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectId));
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
@@ -212,7 +219,7 @@ export const ModalTiсket = ({
 | 
			
		||||
      method: "DELETE",
 | 
			
		||||
      data: {
 | 
			
		||||
        task_id: task.id,
 | 
			
		||||
        user_id: person.user_id
 | 
			
		||||
        user_id: person.user_id,
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      setMembers(members.filter((item) => item.user_id !== person.user_id));
 | 
			
		||||
@@ -221,90 +228,109 @@ export const ModalTiсket = ({
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    apiRequest(`/comment/get-by-entity?entity_type=2&entity_id=${task.id}`).then((res) => {
 | 
			
		||||
    apiRequest(
 | 
			
		||||
      `/comment/get-by-entity?entity_type=2&entity_id=${task.id}`
 | 
			
		||||
    ).then((res) => {
 | 
			
		||||
      const comments = res.reduce((acc, cur) => {
 | 
			
		||||
        if (!cur.parent_id) {
 | 
			
		||||
          acc.push({...cur, subComments: []})
 | 
			
		||||
          acc.push({ ...cur, subComments: [] });
 | 
			
		||||
        } else {
 | 
			
		||||
          acc.forEach((item) => {
 | 
			
		||||
            if (item.id === cur.parent_id) item.subComments.push(cur)
 | 
			
		||||
          })
 | 
			
		||||
            if (item.id === cur.parent_id) item.subComments.push(cur);
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
        return acc
 | 
			
		||||
      }, [])
 | 
			
		||||
      setComments(comments)
 | 
			
		||||
    })
 | 
			
		||||
    apiRequest(`/timer/get-by-entity?entity_type=2&entity_id=${task.id}`).then((res) => {
 | 
			
		||||
      let timerSeconds = 0
 | 
			
		||||
      res.length && res.forEach((time) => {
 | 
			
		||||
        timerSeconds += time.deltaSeconds
 | 
			
		||||
        setCurrentTimerCount({
 | 
			
		||||
          hours: Math.floor(timerSeconds / 60 / 60),
 | 
			
		||||
          minute: Math.floor(timerSeconds / 60 % 60),
 | 
			
		||||
          seconds: timerSeconds % 60}
 | 
			
		||||
        return acc;
 | 
			
		||||
      }, []);
 | 
			
		||||
      setComments(comments);
 | 
			
		||||
    });
 | 
			
		||||
    apiRequest(`/timer/get-by-entity?entity_type=2&entity_id=${task.id}`).then(
 | 
			
		||||
      (res) => {
 | 
			
		||||
        let timerSeconds = 0;
 | 
			
		||||
        res.length &&
 | 
			
		||||
          res.forEach((time) => {
 | 
			
		||||
            timerSeconds += time.deltaSeconds;
 | 
			
		||||
            setCurrentTimerCount({
 | 
			
		||||
              hours: Math.floor(timerSeconds / 60 / 60),
 | 
			
		||||
              minute: Math.floor((timerSeconds / 60) % 60),
 | 
			
		||||
              seconds: timerSeconds % 60,
 | 
			
		||||
            });
 | 
			
		||||
            updateTimerHours = Math.floor(timerSeconds / 60 / 60);
 | 
			
		||||
            updateTimerMinute = Math.floor((timerSeconds / 60) % 60);
 | 
			
		||||
            updateTimerSec = timerSeconds % 60;
 | 
			
		||||
            if (!time.stopped_at) {
 | 
			
		||||
              setTimerStart(true);
 | 
			
		||||
              startTimer();
 | 
			
		||||
              setTimerInfo(time);
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
      localStorage.getItem("role_status") !== "18" &&
 | 
			
		||||
      Boolean(
 | 
			
		||||
        !correctProjectUsers.find(
 | 
			
		||||
          (item) => item.user_id === profileInfo.id_user
 | 
			
		||||
        )
 | 
			
		||||
        updateTimerHours = Math.floor(timerSeconds / 60 / 60)
 | 
			
		||||
        updateTimerMinute = Math.floor(timerSeconds / 60 % 60)
 | 
			
		||||
        updateTimerSec = timerSeconds % 60
 | 
			
		||||
        if (!time.stopped_at) {
 | 
			
		||||
          setTimerStart(true)
 | 
			
		||||
          startTimer()
 | 
			
		||||
          setTimerInfo(time)
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    if (localStorage.getItem("role_status") !== "18" && Boolean(!correctProjectUsers.find((item) => item.user_id === profileInfo.id_user))) {
 | 
			
		||||
      setCorrectProjectUsers((prevState) => [...prevState, {
 | 
			
		||||
        user: {
 | 
			
		||||
          avatar: profileInfo.photo,
 | 
			
		||||
          fio: profileInfo.fio
 | 
			
		||||
      )
 | 
			
		||||
    ) {
 | 
			
		||||
      setCorrectProjectUsers((prevState) => [
 | 
			
		||||
        ...prevState,
 | 
			
		||||
        {
 | 
			
		||||
          user: {
 | 
			
		||||
            avatar: profileInfo.photo,
 | 
			
		||||
            fio: profileInfo.fio,
 | 
			
		||||
          },
 | 
			
		||||
          user_id: profileInfo.id_user,
 | 
			
		||||
        },
 | 
			
		||||
        user_id: profileInfo.id_user
 | 
			
		||||
      }])
 | 
			
		||||
      ]);
 | 
			
		||||
    }
 | 
			
		||||
  }, [])
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  function startTimer () {
 | 
			
		||||
    setTimerId(setInterval(() => {
 | 
			
		||||
      run()
 | 
			
		||||
    }, 1000))
 | 
			
		||||
  function startTimer() {
 | 
			
		||||
    setTimerId(
 | 
			
		||||
      setInterval(() => {
 | 
			
		||||
        run();
 | 
			
		||||
      }, 1000)
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let updateTimerSec = currentTimerCount.seconds, updateTimerMinute = currentTimerCount.minute, updateTimerHours = currentTimerCount.hours
 | 
			
		||||
  let updateTimerSec = currentTimerCount.seconds,
 | 
			
		||||
    updateTimerMinute = currentTimerCount.minute,
 | 
			
		||||
    updateTimerHours = currentTimerCount.hours;
 | 
			
		||||
 | 
			
		||||
  function run () {
 | 
			
		||||
    updateTimerSec++
 | 
			
		||||
  function run() {
 | 
			
		||||
    updateTimerSec++;
 | 
			
		||||
    if (updateTimerSec > 60) {
 | 
			
		||||
      updateTimerMinute++
 | 
			
		||||
      updateTimerSec = 0
 | 
			
		||||
      updateTimerMinute++;
 | 
			
		||||
      updateTimerSec = 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (updateTimerMinute === 60) {
 | 
			
		||||
      updateTimerMinute = 0
 | 
			
		||||
      updateTimerHours++
 | 
			
		||||
      updateTimerMinute = 0;
 | 
			
		||||
      updateTimerHours++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return setCurrentTimerCount({
 | 
			
		||||
      hours: updateTimerHours,
 | 
			
		||||
      minute: updateTimerMinute,
 | 
			
		||||
      seconds: updateTimerSec
 | 
			
		||||
    })
 | 
			
		||||
      seconds: updateTimerSec,
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function correctTimerTime (time) {
 | 
			
		||||
    if (time < 10) return `0${time}`
 | 
			
		||||
    if (time > 10) return time
 | 
			
		||||
  function correctTimerTime(time) {
 | 
			
		||||
    if (time < 10) return `0${time}`;
 | 
			
		||||
    if (time > 10) return time;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    let ids = members.map((user) => user.user_id)
 | 
			
		||||
    setUsers(projectUsers.reduce((acc, cur) => {
 | 
			
		||||
      if (!ids.includes(cur.user_id)) acc.push(cur)
 | 
			
		||||
      return acc
 | 
			
		||||
    }, []))
 | 
			
		||||
  }, [members])
 | 
			
		||||
 | 
			
		||||
    let ids = members.map((user) => user.user_id);
 | 
			
		||||
    setUsers(
 | 
			
		||||
      projectUsers.reduce((acc, cur) => {
 | 
			
		||||
        if (!ids.includes(cur.user_id)) acc.push(cur);
 | 
			
		||||
        return acc;
 | 
			
		||||
      }, [])
 | 
			
		||||
    );
 | 
			
		||||
  }, [members]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
@@ -329,14 +355,33 @@ export const ModalTiсket = ({
 | 
			
		||||
 | 
			
		||||
          <div className="content__task">
 | 
			
		||||
            <span>Задача</span>
 | 
			
		||||
            {editOpen ? <input value={inputsValue.title} onChange={(e) => {
 | 
			
		||||
              setInputsValue((prevValue) => ({...prevValue, title: e.target.value}))
 | 
			
		||||
            }} /> :<h5>{inputsValue.title}</h5>}
 | 
			
		||||
            {editOpen ? (
 | 
			
		||||
              <input
 | 
			
		||||
                value={inputsValue.title}
 | 
			
		||||
                onChange={(e) => {
 | 
			
		||||
                  setInputsValue((prevValue) => ({
 | 
			
		||||
                    ...prevValue,
 | 
			
		||||
                    title: e.target.value,
 | 
			
		||||
                  }));
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            ) : (
 | 
			
		||||
              <h5>{inputsValue.title}</h5>
 | 
			
		||||
            )}
 | 
			
		||||
            <div className="content__description">
 | 
			
		||||
              {editOpen ?
 | 
			
		||||
                  <textarea value={inputsValue.description} onChange={(e) => {
 | 
			
		||||
                setInputsValue((prevValue) => ({...prevValue, description: e.target.value}))
 | 
			
		||||
              }}/> :<p>{inputsValue.description}</p>}
 | 
			
		||||
              {editOpen ? (
 | 
			
		||||
                <textarea
 | 
			
		||||
                  value={inputsValue.description}
 | 
			
		||||
                  onChange={(e) => {
 | 
			
		||||
                    setInputsValue((prevValue) => ({
 | 
			
		||||
                      ...prevValue,
 | 
			
		||||
                      description: e.target.value,
 | 
			
		||||
                    }));
 | 
			
		||||
                  }}
 | 
			
		||||
                />
 | 
			
		||||
              ) : (
 | 
			
		||||
                <p>{inputsValue.description}</p>
 | 
			
		||||
              )}
 | 
			
		||||
              {/*<img src={taskImg} className="image-task"></img>*/}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className="content__communication">
 | 
			
		||||
@@ -361,87 +406,127 @@ export const ModalTiсket = ({
 | 
			
		||||
              </p>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className="content__input">
 | 
			
		||||
              <input placeholder="Оставить комментарий" value={inputsValue.comment} onChange={(e) => {
 | 
			
		||||
                setInputsValue((prevValue) => ({...prevValue, comment: e.target.value}))
 | 
			
		||||
              }} />
 | 
			
		||||
              <input
 | 
			
		||||
                placeholder="Оставить комментарий"
 | 
			
		||||
                value={inputsValue.comment}
 | 
			
		||||
                onChange={(e) => {
 | 
			
		||||
                  setInputsValue((prevValue) => ({
 | 
			
		||||
                    ...prevValue,
 | 
			
		||||
                    comment: e.target.value,
 | 
			
		||||
                  }));
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
              <img src={send} onClick={createComment}></img>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className='comments__list'>
 | 
			
		||||
            <div className="comments__list">
 | 
			
		||||
              {comments.map((comment) => {
 | 
			
		||||
                return <TrackerTaskComment
 | 
			
		||||
                return (
 | 
			
		||||
                  <TrackerTaskComment
 | 
			
		||||
                    key={comment.id}
 | 
			
		||||
                    taskId={task.id}
 | 
			
		||||
                    comment={comment}
 | 
			
		||||
                    commentDelete={commentDelete}
 | 
			
		||||
                    addSubComment={addSubComment}
 | 
			
		||||
                    subCommentDelete={subCommentDelete}
 | 
			
		||||
                />
 | 
			
		||||
                })
 | 
			
		||||
              }
 | 
			
		||||
                  />
 | 
			
		||||
                );
 | 
			
		||||
              })}
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className="workers">
 | 
			
		||||
          <div className="workers_box task__info">
 | 
			
		||||
            <span className="exit" onClick={() => setActive(false)}></span>
 | 
			
		||||
            <span className='nameProject'>{task.title}</span>
 | 
			
		||||
            <span className="nameProject">{task.title}</span>
 | 
			
		||||
            <p className="workers__creator">Создатель : {task.user?.fio}</p>
 | 
			
		||||
 | 
			
		||||
            {executor ?
 | 
			
		||||
              <div className='executor'>
 | 
			
		||||
            {executor ? (
 | 
			
		||||
              <div className="executor">
 | 
			
		||||
                <p>Исполнитель: {executor.fio}</p>
 | 
			
		||||
                <img src={urlForLocal(executor.avatar)} alt='avatar' />
 | 
			
		||||
                <img src={close} className='delete' onClick={() => deleteTaskExecutor()} />
 | 
			
		||||
              </div> :
 | 
			
		||||
                <img src={urlForLocal(executor.avatar)} alt="avatar" />
 | 
			
		||||
                <img
 | 
			
		||||
                  src={close}
 | 
			
		||||
                  className="delete"
 | 
			
		||||
                  onClick={() => deleteTaskExecutor()}
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
            ) : (
 | 
			
		||||
              <div className="add-worker moreItems ">
 | 
			
		||||
                <button onClick={() => setDropListOpen(true)}>+</button>
 | 
			
		||||
                <span>Добавить исполнителя</span>
 | 
			
		||||
                {dropListOpen &&
 | 
			
		||||
                  <div className='dropdownList'>
 | 
			
		||||
                    <img src={close} className='dropdownList__close' onClick={() => setDropListOpen(false)} />
 | 
			
		||||
                {dropListOpen && (
 | 
			
		||||
                  <div className="dropdownList">
 | 
			
		||||
                    <img
 | 
			
		||||
                      src={close}
 | 
			
		||||
                      className="dropdownList__close"
 | 
			
		||||
                      onClick={() => setDropListOpen(false)}
 | 
			
		||||
                    />
 | 
			
		||||
                    {correctProjectUsers.map((person) => {
 | 
			
		||||
                      return <div className='dropdownList__person' key={person.user_id} onClick={() => taskExecutor(person)}>
 | 
			
		||||
                        <span>{person.user.fio}</span>
 | 
			
		||||
                        <img src={urlForLocal(person.user.avatar)} />
 | 
			
		||||
                      </div>
 | 
			
		||||
                    })
 | 
			
		||||
                    }
 | 
			
		||||
                      return (
 | 
			
		||||
                        <div
 | 
			
		||||
                          className="dropdownList__person"
 | 
			
		||||
                          key={person.user_id}
 | 
			
		||||
                          onClick={() => taskExecutor(person)}
 | 
			
		||||
                        >
 | 
			
		||||
                          <span>{person.user.fio}</span>
 | 
			
		||||
                          <img src={urlForLocal(person.user.avatar)} />
 | 
			
		||||
                        </div>
 | 
			
		||||
                      );
 | 
			
		||||
                    })}
 | 
			
		||||
                  </div>
 | 
			
		||||
                }
 | 
			
		||||
                )}
 | 
			
		||||
              </div>
 | 
			
		||||
            }
 | 
			
		||||
            )}
 | 
			
		||||
 | 
			
		||||
            {Boolean(members.length) &&
 | 
			
		||||
            <div className='members'>
 | 
			
		||||
              <p>Участники:</p>
 | 
			
		||||
                <div className='members__list'>
 | 
			
		||||
            {Boolean(members.length) && (
 | 
			
		||||
              <div className="members">
 | 
			
		||||
                <p>Участники:</p>
 | 
			
		||||
                <div className="members__list">
 | 
			
		||||
                  {members.map((member) => {
 | 
			
		||||
                    return <div className='worker' key={member.user_id}>
 | 
			
		||||
                      <p>{member.fio}</p>
 | 
			
		||||
                      <img src={urlForLocal(member.avatar)} />
 | 
			
		||||
                      <img src={close} className='delete' onClick={() => deleteMember(member)} />
 | 
			
		||||
                    </div>
 | 
			
		||||
                  })
 | 
			
		||||
                  }
 | 
			
		||||
                    return (
 | 
			
		||||
                      <div className="worker" key={member.user_id}>
 | 
			
		||||
                        <p>{member.fio}</p>
 | 
			
		||||
                        <img src={urlForLocal(member.avatar)} />
 | 
			
		||||
                        <img
 | 
			
		||||
                          src={close}
 | 
			
		||||
                          className="delete"
 | 
			
		||||
                          onClick={() => deleteMember(member)}
 | 
			
		||||
                        />
 | 
			
		||||
                      </div>
 | 
			
		||||
                    );
 | 
			
		||||
                  })}
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            }
 | 
			
		||||
              </div>
 | 
			
		||||
            )}
 | 
			
		||||
 | 
			
		||||
            <div className="add-worker moreItems">
 | 
			
		||||
              <button onClick={() => setDropListMembersOpen(true)}>+</button>
 | 
			
		||||
              <span>Добавить участников</span>
 | 
			
		||||
              {dropListMembersOpen &&
 | 
			
		||||
              <div className='dropdownList'>
 | 
			
		||||
                <img src={close} className='dropdownList__close' onClick={() => setDropListMembersOpen(false)} />
 | 
			
		||||
                {users.length ? users.map((person) => {
 | 
			
		||||
                  return <div className='dropdownList__person' key={person.user_id} onClick={() => addMember(person)}>
 | 
			
		||||
                    <span>{person.user.fio}</span>
 | 
			
		||||
                    <img src={urlForLocal(person.user.avatar)} />
 | 
			
		||||
                  </div>
 | 
			
		||||
                }) : <p className='noUsers'>Нет пользователей</p>
 | 
			
		||||
                }
 | 
			
		||||
              </div>
 | 
			
		||||
              }
 | 
			
		||||
              {dropListMembersOpen && (
 | 
			
		||||
                <div className="dropdownList">
 | 
			
		||||
                  <img
 | 
			
		||||
                    src={close}
 | 
			
		||||
                    className="dropdownList__close"
 | 
			
		||||
                    onClick={() => setDropListMembersOpen(false)}
 | 
			
		||||
                  />
 | 
			
		||||
                  {users.length ? (
 | 
			
		||||
                    users.map((person) => {
 | 
			
		||||
                      return (
 | 
			
		||||
                        <div
 | 
			
		||||
                          className="dropdownList__person"
 | 
			
		||||
                          key={person.user_id}
 | 
			
		||||
                          onClick={() => addMember(person)}
 | 
			
		||||
                        >
 | 
			
		||||
                          <span>{person.user.fio}</span>
 | 
			
		||||
                          <img src={urlForLocal(person.user.avatar)} />
 | 
			
		||||
                        </div>
 | 
			
		||||
                      );
 | 
			
		||||
                    })
 | 
			
		||||
                  ) : (
 | 
			
		||||
                    <p className="noUsers">Нет пользователей</p>
 | 
			
		||||
                  )}
 | 
			
		||||
                </div>
 | 
			
		||||
              )}
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
@@ -450,37 +535,52 @@ export const ModalTiсket = ({
 | 
			
		||||
              <img src={watch}></img>
 | 
			
		||||
              <span>Длительность : </span>
 | 
			
		||||
              <p>
 | 
			
		||||
                {correctTimerTime(currentTimerCount.hours)}:{correctTimerTime(currentTimerCount.minute)}:{correctTimerTime(currentTimerCount.seconds)}
 | 
			
		||||
                {correctTimerTime(currentTimerCount.hours)}:
 | 
			
		||||
                {correctTimerTime(currentTimerCount.minute)}:
 | 
			
		||||
                {correctTimerTime(currentTimerCount.seconds)}
 | 
			
		||||
              </p>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            {timerStart ?
 | 
			
		||||
            {timerStart ? (
 | 
			
		||||
              <button
 | 
			
		||||
                  className={executorId === Number(localStorage.getItem('id')) ? 'stop' : 'stop disable'}
 | 
			
		||||
                  onClick={() => stopTaskTimer()}>
 | 
			
		||||
                className={
 | 
			
		||||
                  executorId === Number(localStorage.getItem("id"))
 | 
			
		||||
                    ? "stop"
 | 
			
		||||
                    : "stop disable"
 | 
			
		||||
                }
 | 
			
		||||
                onClick={() => stopTaskTimer()}
 | 
			
		||||
              >
 | 
			
		||||
                Остановить
 | 
			
		||||
              </button>
 | 
			
		||||
                :
 | 
			
		||||
            ) : (
 | 
			
		||||
              <button
 | 
			
		||||
                  className={executorId === Number(localStorage.getItem('id')) ? 'start' : 'start disable'}
 | 
			
		||||
                  onClick={() => startTaskTimer()}>
 | 
			
		||||
                className={
 | 
			
		||||
                  executorId === Number(localStorage.getItem("id"))
 | 
			
		||||
                    ? "start"
 | 
			
		||||
                    : "start disable"
 | 
			
		||||
                }
 | 
			
		||||
                onClick={() => startTaskTimer()}
 | 
			
		||||
              >
 | 
			
		||||
                Начать делать
 | 
			
		||||
                <img src={arrow}></img>
 | 
			
		||||
              </button>
 | 
			
		||||
            }
 | 
			
		||||
            )}
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <div className="workers_box-bottom">
 | 
			
		||||
            <div className={editOpen ? 'edit' : ''} onClick={() => {
 | 
			
		||||
              if(editOpen) {
 | 
			
		||||
                setEditOpen(!editOpen)
 | 
			
		||||
                editTask()
 | 
			
		||||
              } else {
 | 
			
		||||
                setEditOpen(!editOpen)
 | 
			
		||||
              }
 | 
			
		||||
            }}>
 | 
			
		||||
            <div
 | 
			
		||||
              className={editOpen ? "edit" : ""}
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
                if (editOpen) {
 | 
			
		||||
                  setEditOpen(!editOpen);
 | 
			
		||||
                  editTask();
 | 
			
		||||
                } else {
 | 
			
		||||
                  setEditOpen(!editOpen);
 | 
			
		||||
                }
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              <img src={edit}></img>
 | 
			
		||||
              <p>{editOpen ? 'сохранить' : 'редактировать'}</p>
 | 
			
		||||
              <p>{editOpen ? "сохранить" : "редактировать"}</p>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div>
 | 
			
		||||
              <img src={link}></img>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,456 +0,0 @@
 | 
			
		||||
import React, { useEffect, useState } from "react";
 | 
			
		||||
 | 
			
		||||
import { ProfileHeader } from "../../ProfileHeader/ProfileHeader";
 | 
			
		||||
import { ProfileBreadcrumbs } from "../../ProfileBreadcrumbs/ProfileBreadcrumbs";
 | 
			
		||||
import { Footer } from "@components/Common/Footer/Footer";
 | 
			
		||||
import { Link, useParams, useNavigate } from "react-router-dom";
 | 
			
		||||
import TrackerModal from "../../Modal/TrackerModal/TrackerModal";
 | 
			
		||||
import TrackerTaskComment from "../../../components/TrackerTaskComment/TrackerTaskComment";
 | 
			
		||||
import { Navigation } from "../../Navigation/Navigation";
 | 
			
		||||
import {Loader} from "@components/Common/Loader/Loader";
 | 
			
		||||
 | 
			
		||||
import {useDispatch, useSelector} from "react-redux";
 | 
			
		||||
import {
 | 
			
		||||
  deletePersonOnProject,
 | 
			
		||||
  modalToggle,
 | 
			
		||||
  setProjectBoardFetch,
 | 
			
		||||
  setToggleTab,
 | 
			
		||||
  getProjectBoard,
 | 
			
		||||
  getBoarderLoader,
 | 
			
		||||
} from "../../../redux/projectsTrackerSlice";
 | 
			
		||||
import { apiRequest } from "../../../api/request";
 | 
			
		||||
 | 
			
		||||
import project from "../../../images/trackerProject.svg";
 | 
			
		||||
import watch from "../../../images/watch.png";
 | 
			
		||||
import file from "../../../images/fileModal.svg";
 | 
			
		||||
import send from "../../../images/send.svg";
 | 
			
		||||
import arrow2 from "../../../images/arrowStart.png";
 | 
			
		||||
import plus from "../../../images/plus.svg";
 | 
			
		||||
import tasks from "../../../images/trackerTasks.svg";
 | 
			
		||||
import archive from "../../../images/archiveTracker.svg";
 | 
			
		||||
import arrow from "../../../images/arrowCalendar.png";
 | 
			
		||||
import link from "../../../images/link.svg";
 | 
			
		||||
import archive2 from "../../../images/archive.svg";
 | 
			
		||||
import del from "../../../images/delete.svg";
 | 
			
		||||
import edit from "../../../images/edit.svg";
 | 
			
		||||
import close from "../../../images/closeProjectPersons.svg";
 | 
			
		||||
 | 
			
		||||
import "./ticketFullScreen.scss";
 | 
			
		||||
import {getCorrectRequestDate, urlForLocal} from "../../../helper";
 | 
			
		||||
 | 
			
		||||
export const TicketFullScreen = ({}) => {
 | 
			
		||||
  const [modalAddWorker, setModalAddWorker] = useState(false);
 | 
			
		||||
  const ticketId = useParams();
 | 
			
		||||
  const dispatch = useDispatch();
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
  const projectBoard = useSelector(getProjectBoard);
 | 
			
		||||
  const boardLoader = useSelector(getBoarderLoader);
 | 
			
		||||
  const [taskInfo, setTaskInfo] = useState({});
 | 
			
		||||
  const [editOpen, setEditOpen] = useState(false);
 | 
			
		||||
  const [inputsValue, setInputsValue] = useState({});
 | 
			
		||||
  const [loader, setLoader] = useState(true);
 | 
			
		||||
  const [comments, setComments] = useState([]);
 | 
			
		||||
  const [personListOpen, setPersonListOpen] = useState(false)
 | 
			
		||||
  const [timerStart, setTimerStart] = useState(false)
 | 
			
		||||
  const [timerInfo, setTimerInfo] = useState({})
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    apiRequest(`/task/get-task?task_id=${ticketId.id}`).then((taskInfo) => {
 | 
			
		||||
      setTaskInfo(taskInfo);
 | 
			
		||||
      setInputsValue({title: taskInfo.title, description: taskInfo.description, comment: ''})
 | 
			
		||||
      apiRequest(`/comment/get-by-entity?entity_type=2&entity_id=${taskInfo.id}`).then((res) => {
 | 
			
		||||
        const comments = res.reduce((acc, cur) => {
 | 
			
		||||
          if (!cur.parent_id) {
 | 
			
		||||
            acc.push({...cur, subComments: []})
 | 
			
		||||
          } else {
 | 
			
		||||
            acc.forEach((item) => {
 | 
			
		||||
              if (item.id === cur.parent_id) item.subComments.push(cur)
 | 
			
		||||
            })
 | 
			
		||||
          }
 | 
			
		||||
          return acc
 | 
			
		||||
        }, [])
 | 
			
		||||
        setComments(comments)
 | 
			
		||||
      })
 | 
			
		||||
      taskInfo.timers.forEach((time) => {
 | 
			
		||||
        if (!time.stopped_at) {
 | 
			
		||||
          setTimerStart(true)
 | 
			
		||||
          setTimerInfo(time)
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      dispatch(setProjectBoardFetch(taskInfo.project_id));
 | 
			
		||||
      setLoader(boardLoader)
 | 
			
		||||
    });
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  function deleteTask() {
 | 
			
		||||
    apiRequest("/task/update-task", {
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        task_id: ticketId.id,
 | 
			
		||||
        status: 0,
 | 
			
		||||
      },
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      navigate(`/tracker/project/${taskInfo.project_id}`);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function editTask() {
 | 
			
		||||
    apiRequest("/task/update-task", {
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        task_id: taskInfo.id,
 | 
			
		||||
        title: inputsValue.title,
 | 
			
		||||
        description: inputsValue.description
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function createComment() {
 | 
			
		||||
    apiRequest("/comment/create", {
 | 
			
		||||
      method: "POST",
 | 
			
		||||
      data: {
 | 
			
		||||
        text: inputsValue.comment,
 | 
			
		||||
        entity_type: 2,
 | 
			
		||||
        entity_id: taskInfo.id
 | 
			
		||||
      }
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      let newComment = res
 | 
			
		||||
      newComment.created_at = new Date()
 | 
			
		||||
      newComment.subComments = []
 | 
			
		||||
      setInputsValue((prevValue) => ({...prevValue, comment: ''}))
 | 
			
		||||
      setComments((prevValue) => ([...prevValue, newComment]))
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function startTaskTimer() {
 | 
			
		||||
    apiRequest("/timer/create", {
 | 
			
		||||
      method: "POST",
 | 
			
		||||
      data: {
 | 
			
		||||
        entity_type: 2,
 | 
			
		||||
        entity_id: taskInfo.id,
 | 
			
		||||
        created_at: getCorrectRequestDate(new Date())
 | 
			
		||||
      }
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      setTimerStart(true)
 | 
			
		||||
      setTimerInfo(res)
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function stopTaskTimer() {
 | 
			
		||||
    apiRequest("/timer/update", {
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        timer_id: timerInfo.id,
 | 
			
		||||
        stopped_at: getCorrectRequestDate(new Date())
 | 
			
		||||
      }
 | 
			
		||||
    }).then(() => setTimerStart(false))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function deletePerson(userId) {
 | 
			
		||||
    apiRequest("/project/del-user", {
 | 
			
		||||
      method: "DELETE",
 | 
			
		||||
      data: {
 | 
			
		||||
        project_id: projectBoard.id,
 | 
			
		||||
        user_id: userId
 | 
			
		||||
      },
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      dispatch(deletePersonOnProject(userId))
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function commentDelete(comment) {
 | 
			
		||||
    setComments((prevValue) => prevValue.filter((item) => item.id !== comment.id))
 | 
			
		||||
    if (comment.subComments.length) {
 | 
			
		||||
      comment.subComments.forEach((subComment) => {
 | 
			
		||||
        apiRequest("/comment/update", {
 | 
			
		||||
          method: "PUT",
 | 
			
		||||
          data: {
 | 
			
		||||
            comment_id: subComment.id,
 | 
			
		||||
            status: 0
 | 
			
		||||
          }
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function addSubComment(commentId, subComment) {
 | 
			
		||||
    const addSubComment = comments
 | 
			
		||||
    addSubComment.forEach((comment) => {
 | 
			
		||||
      if (comment.id === commentId) {
 | 
			
		||||
        comment.subComments.push(subComment)
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    setComments(addSubComment)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function subCommentDelete(subComment) {
 | 
			
		||||
    const deleteSubComment = comments
 | 
			
		||||
    deleteSubComment.forEach((comment, index) => {
 | 
			
		||||
      if (comment.id === subComment.parent_id) {
 | 
			
		||||
        deleteSubComment[index].subComments = comment.subComments.filter((item) => item.id !== subComment.id)
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    setComments([...deleteSubComment])
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const toggleTabs = (index) => {
 | 
			
		||||
    dispatch(setToggleTab(index));
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <section className="ticket-full-screen">
 | 
			
		||||
      <ProfileHeader />
 | 
			
		||||
      <Navigation />
 | 
			
		||||
      <div className="container">
 | 
			
		||||
        <div className="tracker__content">
 | 
			
		||||
          <ProfileBreadcrumbs
 | 
			
		||||
            links={[
 | 
			
		||||
              { name: "Главная", link: "/profile" },
 | 
			
		||||
              { name: "Трекер", link: "/profile/tracker" },
 | 
			
		||||
            ]}
 | 
			
		||||
          />
 | 
			
		||||
          <h2 className="tracker__title">Управление проектами с трекером</h2>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div className="tracker__tabs">
 | 
			
		||||
        <div className="tracker__tabs__head">
 | 
			
		||||
          <Link
 | 
			
		||||
            to="/profile/tracker"
 | 
			
		||||
            className="tab active-tab"
 | 
			
		||||
            onClick={() => toggleTabs(1)}
 | 
			
		||||
          >
 | 
			
		||||
            <img src={project} alt="img" />
 | 
			
		||||
            <p>Проекты </p>
 | 
			
		||||
          </Link>
 | 
			
		||||
          <Link
 | 
			
		||||
            to="/profile/tracker"
 | 
			
		||||
            className="tab"
 | 
			
		||||
            onClick={() => toggleTabs(2)}
 | 
			
		||||
          >
 | 
			
		||||
            <img src={tasks} alt="img" />
 | 
			
		||||
            <p>Все мои задачи</p>
 | 
			
		||||
          </Link>
 | 
			
		||||
          <Link
 | 
			
		||||
            to="/profile/tracker"
 | 
			
		||||
            className="tab"
 | 
			
		||||
            onClick={() => toggleTabs(3)}
 | 
			
		||||
          >
 | 
			
		||||
            <img src={archive} alt="img" />
 | 
			
		||||
            <p>Архив</p>
 | 
			
		||||
          </Link>
 | 
			
		||||
        </div>
 | 
			
		||||
        {loader ? <Loader /> :
 | 
			
		||||
        <>
 | 
			
		||||
        <div className="tracker__tabs__content content-tabs">
 | 
			
		||||
          <div className="tasks__head">
 | 
			
		||||
            <div className="tasks__head__wrapper">
 | 
			
		||||
              <h4>Проект : {projectBoard.name}</h4>
 | 
			
		||||
 | 
			
		||||
              <TrackerModal
 | 
			
		||||
                active={modalAddWorker}
 | 
			
		||||
                setActive={setModalAddWorker}
 | 
			
		||||
              ></TrackerModal>
 | 
			
		||||
 | 
			
		||||
              <div className="tasks__head__persons">
 | 
			
		||||
                {/*<img src={avatarTest} alt="avatar" />*/}
 | 
			
		||||
                {/*<img src={avatarTest} alt="avatar" />*/}
 | 
			
		||||
                <span className="countPersons">{projectBoard.projectUsers?.length}</span>
 | 
			
		||||
                <span
 | 
			
		||||
                  className="addPerson"
 | 
			
		||||
                  onClick={() => {
 | 
			
		||||
                    setPersonListOpen(true)
 | 
			
		||||
                  }}
 | 
			
		||||
                >
 | 
			
		||||
                  +
 | 
			
		||||
                </span>
 | 
			
		||||
                <p>добавить участника</p>
 | 
			
		||||
                {personListOpen &&
 | 
			
		||||
                <div className='persons__list'>
 | 
			
		||||
                  <img className='persons__list__close' src={close} alt='close' onClick={() => setPersonListOpen(false)} />
 | 
			
		||||
                  <div className='persons__list__count'><span>{projectBoard.projectUsers?.length}</span>участник</div>
 | 
			
		||||
                  <div className='persons__list__info'>В проекте - <span>“{projectBoard.name}”</span></div>
 | 
			
		||||
                  <div className='persons__list__items'>
 | 
			
		||||
                    {projectBoard.projectUsers?.map((person) => {
 | 
			
		||||
                      return <div className='persons__list__item' key={person.user_id}>
 | 
			
		||||
                        <img className='avatar' src={urlForLocal(person.user.avatar)} alt='avatar' />
 | 
			
		||||
                        <span>{person.user.fio}</span>
 | 
			
		||||
                        <img className='delete' src={close} alt='delete' onClick={() => deletePerson(person.user_id)}/>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    })
 | 
			
		||||
                    }
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div className='persons__list__add'
 | 
			
		||||
                       onClick={() => {
 | 
			
		||||
                         dispatch(modalToggle("addWorker"));
 | 
			
		||||
                         setModalAddWorker(true);
 | 
			
		||||
                         setPersonListOpen(false)
 | 
			
		||||
                       }}
 | 
			
		||||
                  >
 | 
			
		||||
                    <span className='addPerson'>+</span>
 | 
			
		||||
                    <p>Добавить участников</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                }
 | 
			
		||||
              </div>
 | 
			
		||||
              <Link to={`/profile/tracker`} className="link">
 | 
			
		||||
                <div className="tasks__head__back">
 | 
			
		||||
                  <p>Вернуться на проекты</p>
 | 
			
		||||
                  <img src={arrow} alt="arrow" />
 | 
			
		||||
                </div>
 | 
			
		||||
              </Link>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className="modal-tiket__content ticket">
 | 
			
		||||
          <div className="content ticket-whith">
 | 
			
		||||
            <div className="content__task">
 | 
			
		||||
              <span>Задача</span>
 | 
			
		||||
              {editOpen ? <input value={inputsValue.title} onChange={(e) => {
 | 
			
		||||
                setInputsValue((prevValue) => ({...prevValue, title: e.target.value}))
 | 
			
		||||
              }} /> :<h5>{inputsValue.title}</h5>}
 | 
			
		||||
              <div className="content__description">
 | 
			
		||||
                {editOpen ? <input value={inputsValue.description} onChange={(e) => {
 | 
			
		||||
                  setInputsValue((prevValue) => ({...prevValue, description: e.target.value}))
 | 
			
		||||
                }}/> :<p>{inputsValue.description}</p>}
 | 
			
		||||
                {/*<img src={task} className="image-task"></img>*/}
 | 
			
		||||
              </div>
 | 
			
		||||
              <div className="content__communication">
 | 
			
		||||
                <p className="tasks">
 | 
			
		||||
                  <button
 | 
			
		||||
                    onClick={() => {
 | 
			
		||||
                      dispatch(modalToggle("addSubtask"));
 | 
			
		||||
                      setModalAddWorker(true);
 | 
			
		||||
                    }}
 | 
			
		||||
                  >
 | 
			
		||||
                    <img src={plus}></img>
 | 
			
		||||
                    Добавить под задачу
 | 
			
		||||
                  </button>
 | 
			
		||||
                </p>
 | 
			
		||||
                <p className="file">
 | 
			
		||||
                  <button>
 | 
			
		||||
                    <img src={file}></img>
 | 
			
		||||
                    Загрузить файл
 | 
			
		||||
                  </button>
 | 
			
		||||
                  <span>{0}</span>
 | 
			
		||||
                  Файлов
 | 
			
		||||
                </p>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div className="content__input">
 | 
			
		||||
                <input placeholder="Оставить комментарий" value={inputsValue.comment} onChange={(e) => {
 | 
			
		||||
                  setInputsValue((prevValue) => ({...prevValue, comment: e.target.value}))
 | 
			
		||||
                }} />
 | 
			
		||||
                <img src={send} onClick={createComment}></img>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div className='comments__list'>
 | 
			
		||||
                {comments.map((comment) => {
 | 
			
		||||
                  return <TrackerTaskComment
 | 
			
		||||
                      key={comment.id}
 | 
			
		||||
                      taskId={taskInfo.id}
 | 
			
		||||
                      comment={comment}
 | 
			
		||||
                      commentDelete={commentDelete}
 | 
			
		||||
                      addSubComment={addSubComment}
 | 
			
		||||
                      subCommentDelete={subCommentDelete}
 | 
			
		||||
                  />
 | 
			
		||||
                })
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className="workers">
 | 
			
		||||
            <div className="workers_box">
 | 
			
		||||
              <p className="workers__creator">
 | 
			
		||||
                Создатель : <span>{taskInfo.user?.fio}</span>
 | 
			
		||||
              </p>
 | 
			
		||||
              <div>
 | 
			
		||||
                {Boolean(taskInfo.taskUsers?.length) &&
 | 
			
		||||
                  taskInfo.taskUsers.map((worker, index) => {
 | 
			
		||||
                    return (
 | 
			
		||||
                      <div className="worker" key={index}>
 | 
			
		||||
                        <img src={worker.avatar}></img>
 | 
			
		||||
                        <p>{worker.name}</p>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    );
 | 
			
		||||
                  })}
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
              <div className="add-worker moreItems">
 | 
			
		||||
                <button
 | 
			
		||||
                    onClick={() => {
 | 
			
		||||
                      dispatch(modalToggle("addWorker"));
 | 
			
		||||
                      setModalAddWorker(true);
 | 
			
		||||
                    }}
 | 
			
		||||
                >
 | 
			
		||||
                  +
 | 
			
		||||
                </button>
 | 
			
		||||
                <span>Добавить исполнителя</span>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div className="add-worker moreItems">
 | 
			
		||||
                <button
 | 
			
		||||
                  onClick={() => {
 | 
			
		||||
                    dispatch(modalToggle("addWorker"));
 | 
			
		||||
                    setModalAddWorker(true);
 | 
			
		||||
                  }}
 | 
			
		||||
                >
 | 
			
		||||
                  +
 | 
			
		||||
                </button>
 | 
			
		||||
                <span>Добавить участников</span>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div className="workers_box-middle">
 | 
			
		||||
              <div className="time">
 | 
			
		||||
                <img src={watch}></img>
 | 
			
		||||
                <span>Длительность : </span>
 | 
			
		||||
                <p>{"0:00:00"}</p>
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
              {timerStart ?
 | 
			
		||||
                  <button className="stop" onClick={() => stopTaskTimer()}>
 | 
			
		||||
                    Остановить
 | 
			
		||||
                  </button>
 | 
			
		||||
                  :
 | 
			
		||||
                  <button className={taskInfo.executor_id === Number(localStorage.getItem('id')) ? 'start' : 'start disable'} onClick={() => startTaskTimer()}>
 | 
			
		||||
                    Начать делать <img src={arrow2}></img>
 | 
			
		||||
                  </button>
 | 
			
		||||
              }
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div className="workers_box-bottom">
 | 
			
		||||
              <div className={editOpen ? 'edit' : ''} onClick={() => {
 | 
			
		||||
                if(editOpen) {
 | 
			
		||||
                  setEditOpen(!editOpen)
 | 
			
		||||
                  editTask()
 | 
			
		||||
                } else {
 | 
			
		||||
                  setEditOpen(!editOpen)
 | 
			
		||||
                }
 | 
			
		||||
              }}>
 | 
			
		||||
                <img src={edit}></img>
 | 
			
		||||
                <p>{editOpen ? 'сохранить' : 'редактировать'}</p>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div>
 | 
			
		||||
                <img src={link}></img>
 | 
			
		||||
                <p>ссылка на проект</p>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div>
 | 
			
		||||
                <img src={archive2}></img>
 | 
			
		||||
                <p>в архив</p>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div onClick={deleteTask}>
 | 
			
		||||
                <img src={del}></img>
 | 
			
		||||
                <p>удалить</p>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        </>
 | 
			
		||||
        }
 | 
			
		||||
      </div>
 | 
			
		||||
      <Footer />
 | 
			
		||||
    </section>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default TicketFullScreen;
 | 
			
		||||
@@ -1,44 +1,48 @@
 | 
			
		||||
import React, { useEffect, useRef, useState } from "react";
 | 
			
		||||
import { Link, useParams } from "react-router-dom";
 | 
			
		||||
import { ProfileHeader } from "../../components/ProfileHeader/ProfileHeader";
 | 
			
		||||
import { ProfileBreadcrumbs } from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs";
 | 
			
		||||
import { Footer } from "@components/Common/Footer/Footer";
 | 
			
		||||
import { Navigation } from "../../components/Navigation/Navigation";
 | 
			
		||||
import { Loader } from "@components/Common/Loader/Loader";
 | 
			
		||||
import { urlForLocal } from '../../utils/helper'
 | 
			
		||||
 | 
			
		||||
import { useDispatch, useSelector } from "react-redux";
 | 
			
		||||
import { apiRequest } from "../../api/request";
 | 
			
		||||
import { Link, useParams } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  getProjectBoard,
 | 
			
		||||
  getBoarderLoader,
 | 
			
		||||
  modalToggle,
 | 
			
		||||
  moveProjectTask,
 | 
			
		||||
  setProjectBoardFetch,
 | 
			
		||||
  setToggleTab,
 | 
			
		||||
  activeLoader,
 | 
			
		||||
  setColumnName,
 | 
			
		||||
  setColumnId,
 | 
			
		||||
  setColumnPriority,
 | 
			
		||||
  deletePersonOnProject,
 | 
			
		||||
  filterCreatedByMe,
 | 
			
		||||
  filteredParticipateTasks,
 | 
			
		||||
  movePositionProjectTask
 | 
			
		||||
} from "../../redux/projectsTrackerSlice";
 | 
			
		||||
  getBoarderLoader,
 | 
			
		||||
  getProjectBoard,
 | 
			
		||||
  modalToggle,
 | 
			
		||||
  movePositionProjectTask,
 | 
			
		||||
  moveProjectTask,
 | 
			
		||||
  setColumnId,
 | 
			
		||||
  setColumnName,
 | 
			
		||||
  setColumnPriority,
 | 
			
		||||
  setProjectBoardFetch,
 | 
			
		||||
  setToggleTab,
 | 
			
		||||
} from "@redux/projectsTrackerSlice";
 | 
			
		||||
 | 
			
		||||
import ModalTicket from "../../components/UI/ModalTicket/ModalTicket";
 | 
			
		||||
import TrackerModal from "../../components/Modal/TrackerModal/TrackerModal";
 | 
			
		||||
import { urlForLocal } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import project from "../../assets/icons/trackerProject.svg";
 | 
			
		||||
import tasks from "../../assets/icons/trackerTasks.svg";
 | 
			
		||||
import archive from "../../assets/icons/archiveTracker.svg";
 | 
			
		||||
import commentsBoard from "../../assets/icons/commentsBoard.svg";
 | 
			
		||||
import filesBoard from "../../assets/icons/filesBoard.svg";
 | 
			
		||||
import arrow from "../../assets/icons/arrows/arrowCalendar.png";
 | 
			
		||||
import del from "../../assets/icons/delete.svg";
 | 
			
		||||
import edit from "../../assets/icons/edit.svg";
 | 
			
		||||
import close from "../../assets/icons/close.png"
 | 
			
		||||
import accept from "../../assets/images/accept.png";
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import BaseButton from "@components/Common/BaseButton/BaseButton";
 | 
			
		||||
import { Footer } from "@components/Common/Footer/Footer";
 | 
			
		||||
import { Loader } from "@components/Common/Loader/Loader";
 | 
			
		||||
import ModalTicket from "@components/Modal/Tracker/ModalTicket/ModalTicket";
 | 
			
		||||
import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal";
 | 
			
		||||
// import TrackerModal from "@components/Modal/TrackerModal/TrackerModal";
 | 
			
		||||
import { Navigation } from "@components/Navigation/Navigation";
 | 
			
		||||
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
 | 
			
		||||
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
 | 
			
		||||
 | 
			
		||||
import archive from "assets/icons/archiveTracker.svg";
 | 
			
		||||
import arrow from "assets/icons/arrows/arrowCalendar.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 project from "assets/icons/trackerProject.svg";
 | 
			
		||||
import tasks from "assets/icons/trackerTasks.svg";
 | 
			
		||||
import accept from "assets/images/accept.png";
 | 
			
		||||
 | 
			
		||||
export const ProjectTracker = () => {
 | 
			
		||||
  const dispatch = useDispatch();
 | 
			
		||||
@@ -48,13 +52,14 @@ export const ProjectTracker = () => {
 | 
			
		||||
  const [selectedTab, setSelectedTab] = useState(0);
 | 
			
		||||
  const [priorityTask, setPriorityTask] = useState(0);
 | 
			
		||||
  const [wrapperHover, setWrapperHover] = useState({});
 | 
			
		||||
  const [taskHover, setTaskHover] = 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 [checkBoxParticipateTasks, setCheckBoxParticipateTasks] = useState(false)
 | 
			
		||||
  const [checkBoxMyTasks, setCheckBoxMyTasks] = useState(false)
 | 
			
		||||
  const [personListOpen, setPersonListOpen] = useState(false);
 | 
			
		||||
  const [checkBoxParticipateTasks, setCheckBoxParticipateTasks] =
 | 
			
		||||
    useState(false);
 | 
			
		||||
  const [checkBoxMyTasks, setCheckBoxMyTasks] = useState(false);
 | 
			
		||||
  const startWrapperIndexTest = useRef({});
 | 
			
		||||
  const projectBoard = useSelector(getProjectBoard);
 | 
			
		||||
  const loader = useSelector(getBoarderLoader);
 | 
			
		||||
@@ -65,20 +70,20 @@ export const ProjectTracker = () => {
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const tasksHover = {}
 | 
			
		||||
    const columnHover = {}
 | 
			
		||||
    const tasksHover = {};
 | 
			
		||||
    const columnHover = {};
 | 
			
		||||
    if (Object.keys(projectBoard).length) {
 | 
			
		||||
      projectBoard.columns.forEach((column) => {
 | 
			
		||||
        setOpenColumnSelect((prevState) => ({
 | 
			
		||||
          ...prevState,
 | 
			
		||||
          [column.id]: false,
 | 
			
		||||
        }));
 | 
			
		||||
        columnHover[column.id] = false
 | 
			
		||||
        column.tasks.forEach(task => tasksHover[task.id] = false)
 | 
			
		||||
        columnHover[column.id] = false;
 | 
			
		||||
        column.tasks.forEach((task) => (tasksHover[task.id] = false));
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    setWrapperHover(columnHover)
 | 
			
		||||
    setTaskHover(tasksHover)
 | 
			
		||||
    setWrapperHover(columnHover);
 | 
			
		||||
    setTaskHover(tasksHover);
 | 
			
		||||
  }, [projectBoard]);
 | 
			
		||||
 | 
			
		||||
  function dragStartHandler(e, task, columnId) {
 | 
			
		||||
@@ -86,35 +91,37 @@ export const ProjectTracker = () => {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function dragOverTaskHandler(e, task) {
 | 
			
		||||
    e.preventDefault()
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    if (startWrapperIndexTest.current.task.id === task.id) {
 | 
			
		||||
      return
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    setTaskHover((prevState) => ({[prevState]: false, [task.id]: true}))
 | 
			
		||||
    setTaskHover((prevState) => ({ [prevState]: false, [task.id]: true }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function dragLeaveTaskHandler(e) {
 | 
			
		||||
    setTaskHover((prevState) => ({[prevState]: false}))
 | 
			
		||||
  function dragLeaveTaskHandler() {
 | 
			
		||||
    setTaskHover((prevState) => ({ [prevState]: false }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function dragEndTaskHandler() {
 | 
			
		||||
    setTaskHover((prevState) => ({[prevState]: false}))
 | 
			
		||||
    setTaskHover((prevState) => ({ [prevState]: false }));
 | 
			
		||||
    setWrapperHover((prevState) => ({
 | 
			
		||||
      [prevState]: false,
 | 
			
		||||
    }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function dragDropTaskHandler(e, task, column) {
 | 
			
		||||
    e.preventDefault()
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    if (task.id === startWrapperIndexTest.current.task.id) {
 | 
			
		||||
      return
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    const finishTask = column.tasks.indexOf(task)
 | 
			
		||||
    dispatch(movePositionProjectTask({
 | 
			
		||||
      startTask: startWrapperIndexTest.current.task,
 | 
			
		||||
      finishTask: task,
 | 
			
		||||
      finishIndex: finishTask
 | 
			
		||||
    }))
 | 
			
		||||
    const finishTask = column.tasks.indexOf(task);
 | 
			
		||||
    dispatch(
 | 
			
		||||
      movePositionProjectTask({
 | 
			
		||||
        startTask: startWrapperIndexTest.current.task,
 | 
			
		||||
        finishTask: task,
 | 
			
		||||
        finishIndex: finishTask,
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function dragOverHandler(e) {
 | 
			
		||||
@@ -139,9 +146,10 @@ export const ProjectTracker = () => {
 | 
			
		||||
      [prevState]: false,
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    if (startWrapperIndexTest.current.index === columnId
 | 
			
		||||
        ||
 | 
			
		||||
        e.target.className.includes('__item')) {
 | 
			
		||||
    if (
 | 
			
		||||
      startWrapperIndexTest.current.index === columnId ||
 | 
			
		||||
      e.target.className.includes("__item")
 | 
			
		||||
    ) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -159,7 +167,7 @@ export const ProjectTracker = () => {
 | 
			
		||||
    setSelectedTab(columnId);
 | 
			
		||||
    dispatch(modalToggle("createTiketProject"));
 | 
			
		||||
    setModalAdd(true);
 | 
			
		||||
    setPriorityTask(length)
 | 
			
		||||
    setPriorityTask(length);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function openTicket(e, task) {
 | 
			
		||||
@@ -168,7 +176,7 @@ export const ProjectTracker = () => {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function deleteColumn(column) {
 | 
			
		||||
    const priorityColumns = []
 | 
			
		||||
    const priorityColumns = [];
 | 
			
		||||
    apiRequest("/project-column/update-column", {
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
@@ -181,19 +189,19 @@ export const ProjectTracker = () => {
 | 
			
		||||
        for (let i = column.priority; i < projectBoard.columns.length; i++) {
 | 
			
		||||
          const currentColumn = {
 | 
			
		||||
            column_id: projectBoard.columns[i].id,
 | 
			
		||||
            priority: i
 | 
			
		||||
          }
 | 
			
		||||
          priorityColumns.push(currentColumn)
 | 
			
		||||
            priority: i,
 | 
			
		||||
          };
 | 
			
		||||
          priorityColumns.push(currentColumn);
 | 
			
		||||
        }
 | 
			
		||||
        apiRequest("/project-column/set-priority", {
 | 
			
		||||
          method: "POST",
 | 
			
		||||
          data: {
 | 
			
		||||
            project_id: projectBoard.id,
 | 
			
		||||
            data: JSON.stringify(priorityColumns)
 | 
			
		||||
          }
 | 
			
		||||
            data: JSON.stringify(priorityColumns),
 | 
			
		||||
          },
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          dispatch(setProjectBoardFetch(projectBoard.id));
 | 
			
		||||
        })
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        dispatch(setProjectBoardFetch(projectBoard.id));
 | 
			
		||||
      }
 | 
			
		||||
@@ -205,33 +213,33 @@ export const ProjectTracker = () => {
 | 
			
		||||
      method: "DELETE",
 | 
			
		||||
      data: {
 | 
			
		||||
        project_id: projectBoard.id,
 | 
			
		||||
        user_id: userId
 | 
			
		||||
        user_id: userId,
 | 
			
		||||
      },
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      dispatch(deletePersonOnProject(userId))
 | 
			
		||||
      dispatch(deletePersonOnProject(userId));
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function filterParticipateTasks() {
 | 
			
		||||
    if (!checkBoxParticipateTasks) {
 | 
			
		||||
      dispatch(filteredParticipateTasks(Number(localStorage.getItem('id'))))
 | 
			
		||||
      dispatch(filteredParticipateTasks(Number(localStorage.getItem("id"))));
 | 
			
		||||
    } else {
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectId.id))
 | 
			
		||||
      setCheckBoxParticipateTasks(false)
 | 
			
		||||
      setCheckBoxMyTasks(false)
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectId.id));
 | 
			
		||||
      setCheckBoxParticipateTasks(false);
 | 
			
		||||
      setCheckBoxMyTasks(false);
 | 
			
		||||
    }
 | 
			
		||||
    setCheckBoxParticipateTasks(!checkBoxParticipateTasks)
 | 
			
		||||
    setCheckBoxParticipateTasks(!checkBoxParticipateTasks);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function filterMyTask() {
 | 
			
		||||
    if (!checkBoxMyTasks) {
 | 
			
		||||
      dispatch(filterCreatedByMe(Number(localStorage.getItem('id'))))
 | 
			
		||||
      dispatch(filterCreatedByMe(Number(localStorage.getItem("id"))));
 | 
			
		||||
    } else {
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectId.id))
 | 
			
		||||
      setCheckBoxParticipateTasks(false)
 | 
			
		||||
      setCheckBoxMyTasks(false)
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectId.id));
 | 
			
		||||
      setCheckBoxParticipateTasks(false);
 | 
			
		||||
      setCheckBoxMyTasks(false);
 | 
			
		||||
    }
 | 
			
		||||
    setCheckBoxMyTasks(!checkBoxMyTasks)
 | 
			
		||||
    setCheckBoxMyTasks(!checkBoxMyTasks);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
@@ -289,72 +297,108 @@ export const ProjectTracker = () => {
 | 
			
		||||
            <div className="tracker__tabs__content__tasks tasks active__content">
 | 
			
		||||
              <div className="tasks__head">
 | 
			
		||||
                <div className="tasks__head__wrapper">
 | 
			
		||||
                  <h4>Проект : {projectBoard.name}</h4>
 | 
			
		||||
                  <h5>Проект : {projectBoard.name}</h5>
 | 
			
		||||
 | 
			
		||||
                  <div className="tasks__head__add">
 | 
			
		||||
                    <span
 | 
			
		||||
                    <BaseButton
 | 
			
		||||
                      onClick={() => {
 | 
			
		||||
                        dispatch(modalToggle("createColumn"));
 | 
			
		||||
                        setModalAdd(true);
 | 
			
		||||
                      }}
 | 
			
		||||
                      styles={"button-add-column"}
 | 
			
		||||
                    >
 | 
			
		||||
                      +
 | 
			
		||||
                    </BaseButton>
 | 
			
		||||
                    {/* <span
 | 
			
		||||
                      onClick={() => {
 | 
			
		||||
                        dispatch(modalToggle("createColumn"));
 | 
			
		||||
                        setModalAdd(true);
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      +
 | 
			
		||||
                    </span>
 | 
			
		||||
                    </span> */}
 | 
			
		||||
                    <p>добавить колонку</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div className="tasks__head__persons">
 | 
			
		||||
                    <span className="countPersons">{projectBoard.projectUsers?.length}</span>
 | 
			
		||||
                    <span className="countPersons">
 | 
			
		||||
                      {projectBoard.projectUsers?.length}
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <span
 | 
			
		||||
                      className="addPerson"
 | 
			
		||||
                      onClick={() => {
 | 
			
		||||
                        setPersonListOpen(true)
 | 
			
		||||
                        setPersonListOpen(true);
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      +
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <p>добавить участника</p>
 | 
			
		||||
                    {personListOpen &&
 | 
			
		||||
                    <div className='persons__list'>
 | 
			
		||||
                      <img className='persons__list__close' src={close} alt='close' onClick={() => setPersonListOpen(false)} />
 | 
			
		||||
                      <div className='persons__list__count'><span>{projectBoard.projectUsers?.length}</span>участник</div>
 | 
			
		||||
                      <div className='persons__list__info'>В проекте - <span>“{projectBoard.name}”</span></div>
 | 
			
		||||
                      <div className='persons__list__items'>
 | 
			
		||||
                        {projectBoard.projectUsers?.map((person) => {
 | 
			
		||||
                          return <div className='persons__list__item' key={person.user_id}>
 | 
			
		||||
                                    <img className='avatar' src={urlForLocal(person.user.avatar)} alt='avatar' />
 | 
			
		||||
                                    <span>{person.user.fio}</span>
 | 
			
		||||
                                    <img className='delete' src={close} alt='delete' onClick={() => deletePerson(person.user_id)}/>
 | 
			
		||||
                                </div>
 | 
			
		||||
                        })
 | 
			
		||||
                        }
 | 
			
		||||
                    {personListOpen && (
 | 
			
		||||
                      <div className="persons__list">
 | 
			
		||||
                        <img
 | 
			
		||||
                          className="persons__list__close"
 | 
			
		||||
                          src={close}
 | 
			
		||||
                          alt="close"
 | 
			
		||||
                          onClick={() => setPersonListOpen(false)}
 | 
			
		||||
                        />
 | 
			
		||||
                        <div className="persons__list__count">
 | 
			
		||||
                          <span>{projectBoard.projectUsers?.length}</span>
 | 
			
		||||
                          участник
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div className="persons__list__info">
 | 
			
		||||
                          В проекте - <span>“{projectBoard.name}”</span>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div className="persons__list__items">
 | 
			
		||||
                          {projectBoard.projectUsers?.map((person) => {
 | 
			
		||||
                            return (
 | 
			
		||||
                              <div
 | 
			
		||||
                                className="persons__list__item"
 | 
			
		||||
                                key={person.user_id}
 | 
			
		||||
                              >
 | 
			
		||||
                                <img
 | 
			
		||||
                                  className="avatar"
 | 
			
		||||
                                  src={urlForLocal(person.user.avatar)}
 | 
			
		||||
                                  alt="avatar"
 | 
			
		||||
                                />
 | 
			
		||||
                                <span>{person.user.fio}</span>
 | 
			
		||||
                                <img
 | 
			
		||||
                                  className="delete"
 | 
			
		||||
                                  src={close}
 | 
			
		||||
                                  alt="delete"
 | 
			
		||||
                                  onClick={() => deletePerson(person.user_id)}
 | 
			
		||||
                                />
 | 
			
		||||
                              </div>
 | 
			
		||||
                            );
 | 
			
		||||
                          })}
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div
 | 
			
		||||
                          className="persons__list__add"
 | 
			
		||||
                          onClick={() => {
 | 
			
		||||
                            dispatch(modalToggle("addWorker"));
 | 
			
		||||
                            setModalAdd(true);
 | 
			
		||||
                            setPersonListOpen(false);
 | 
			
		||||
                          }}
 | 
			
		||||
                        >
 | 
			
		||||
                          <span className="addPerson">+</span>
 | 
			
		||||
                          <p>Добавить участников</p>
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div className='persons__list__add'
 | 
			
		||||
                           onClick={() => {
 | 
			
		||||
                             dispatch(modalToggle("addWorker"));
 | 
			
		||||
                             setModalAdd(true);
 | 
			
		||||
                             setPersonListOpen(false)
 | 
			
		||||
                           }}
 | 
			
		||||
                      >
 | 
			
		||||
                        <span className='addPerson'>+</span>
 | 
			
		||||
                        <p>Добавить участников</p>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    }
 | 
			
		||||
                    )}
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div className="tasks__head__checkBox" onClick={filterParticipateTasks}>
 | 
			
		||||
                  <div
 | 
			
		||||
                    className="tasks__head__checkBox"
 | 
			
		||||
                    onClick={filterParticipateTasks}
 | 
			
		||||
                  >
 | 
			
		||||
                    <span>Участвую</span>
 | 
			
		||||
                    <div className="tasks__head__checkBox__box">
 | 
			
		||||
                      {checkBoxParticipateTasks &&
 | 
			
		||||
                        <img src={accept} alt='accept' />
 | 
			
		||||
                      }
 | 
			
		||||
                      {checkBoxParticipateTasks && (
 | 
			
		||||
                        <img src={accept} alt="accept" />
 | 
			
		||||
                      )}
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div className="tasks__head__checkBox" onClick={filterMyTask}>
 | 
			
		||||
                    <span>Мои</span>
 | 
			
		||||
                    <div className="tasks__head__checkBox__box">
 | 
			
		||||
                      {checkBoxMyTasks &&
 | 
			
		||||
                          <img src={accept} alt='accept' />
 | 
			
		||||
                      }
 | 
			
		||||
                      {checkBoxMyTasks && <img src={accept} alt="accept" />}
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <Link to="/profile/tracker" className="tasks__head__back">
 | 
			
		||||
@@ -364,14 +408,16 @@ export const ProjectTracker = () => {
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
              {Boolean(modalActiveTicket) && <ModalTicket
 | 
			
		||||
              {Boolean(modalActiveTicket) && (
 | 
			
		||||
                <ModalTicket
 | 
			
		||||
                  active={modalActiveTicket}
 | 
			
		||||
                  setActive={setModalActiveTicket}
 | 
			
		||||
                  task={selectedTicket}
 | 
			
		||||
                  projectId={projectBoard.id}
 | 
			
		||||
                  projectName={projectBoard.name}
 | 
			
		||||
                  projectUsers={projectBoard.projectUsers}
 | 
			
		||||
              />}
 | 
			
		||||
                />
 | 
			
		||||
              )}
 | 
			
		||||
 | 
			
		||||
              <div className="tasks__container">
 | 
			
		||||
                {Boolean(projectBoard?.columns) &&
 | 
			
		||||
@@ -381,7 +427,7 @@ export const ProjectTracker = () => {
 | 
			
		||||
                      <div
 | 
			
		||||
                        key={column.id}
 | 
			
		||||
                        onDragOver={(e) => dragOverHandler(e)}
 | 
			
		||||
                        onDragEnter={(e) => dragEnterHandler(column.id)}
 | 
			
		||||
                        onDragEnter={() => dragEnterHandler(column.id)}
 | 
			
		||||
                        onDrop={(e) => dragDropHandler(e, column.id)}
 | 
			
		||||
                        className={`tasks__board ${
 | 
			
		||||
                          wrapperHover[column.id] ? "tasks__board__hover" : ""
 | 
			
		||||
@@ -392,7 +438,9 @@ export const ProjectTracker = () => {
 | 
			
		||||
                          <div>
 | 
			
		||||
                            <span
 | 
			
		||||
                              className="add"
 | 
			
		||||
                              onClick={() => selectedTabTask(column.id, column.tasks.length)}
 | 
			
		||||
                              onClick={() =>
 | 
			
		||||
                                selectedTabTask(column.id, column.tasks.length)
 | 
			
		||||
                              }
 | 
			
		||||
                            >
 | 
			
		||||
                              +
 | 
			
		||||
                            </span>
 | 
			
		||||
@@ -419,9 +467,9 @@ export const ProjectTracker = () => {
 | 
			
		||||
                                  [column.id]: false,
 | 
			
		||||
                                }));
 | 
			
		||||
                                dispatch(modalToggle("editColumn"));
 | 
			
		||||
                                dispatch(setColumnName(column.title))
 | 
			
		||||
                                dispatch(setColumnId(column.id))
 | 
			
		||||
                                dispatch(setColumnPriority(column.priority))
 | 
			
		||||
                                dispatch(setColumnName(column.title));
 | 
			
		||||
                                dispatch(setColumnId(column.id));
 | 
			
		||||
                                dispatch(setColumnPriority(column.priority));
 | 
			
		||||
                                setModalAdd(true);
 | 
			
		||||
                              }}
 | 
			
		||||
                            >
 | 
			
		||||
@@ -442,18 +490,24 @@ export const ProjectTracker = () => {
 | 
			
		||||
                            <div
 | 
			
		||||
                              key={task.id}
 | 
			
		||||
                              className={`tasks__board__item ${
 | 
			
		||||
                                  taskHover[task.id] ? "task__hover" : ""
 | 
			
		||||
                                taskHover[task.id] ? "task__hover" : ""
 | 
			
		||||
                              }`}
 | 
			
		||||
                              draggable={true}
 | 
			
		||||
                              onDragStart={(e) => dragStartHandler(e, task, column.id)}
 | 
			
		||||
                              onDragStart={(e) =>
 | 
			
		||||
                                dragStartHandler(e, task, column.id)
 | 
			
		||||
                              }
 | 
			
		||||
                              onDragOver={(e) => dragOverTaskHandler(e, task)}
 | 
			
		||||
                              onDragLeave={(e) => dragLeaveTaskHandler(e)}
 | 
			
		||||
                              onDragEnd={(e) => dragEndTaskHandler()}
 | 
			
		||||
                              onDrop={(e) => dragDropTaskHandler(e, task, column)}
 | 
			
		||||
                              onDragEnd={() => dragEndTaskHandler()}
 | 
			
		||||
                              onDrop={(e) =>
 | 
			
		||||
                                dragDropTaskHandler(e, task, column)
 | 
			
		||||
                              }
 | 
			
		||||
                              onClick={(e) => openTicket(e, task)}
 | 
			
		||||
                            >
 | 
			
		||||
                              <div className="tasks__board__item__title">
 | 
			
		||||
                                <p className='task__board__item__title'>{task.title}</p>
 | 
			
		||||
                                <p className="task__board__item__title">
 | 
			
		||||
                                  {task.title}
 | 
			
		||||
                                </p>
 | 
			
		||||
                              </div>
 | 
			
		||||
                              <p className="tasks__board__item__description">
 | 
			
		||||
                                {task.description}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,9 +14,10 @@ import { urlForLocal } from "@utils/helper";
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import { getCorrectDate } from "@components/Calendar/calendarHelper";
 | 
			
		||||
import BaseButton from "@components/Common/BaseButton/BaseButton";
 | 
			
		||||
import { Footer } from "@components/Common/Footer/Footer";
 | 
			
		||||
import { Loader } from "@components/Common/Loader/Loader";
 | 
			
		||||
import TrackerModal from "@components/Modal/TrackerModal/TrackerModal";
 | 
			
		||||
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";
 | 
			
		||||
@@ -190,15 +191,16 @@ export const Tracker = () => {
 | 
			
		||||
                      <img src={noProjects} alt="noProjectImg" />
 | 
			
		||||
                      <p>Создайте свой первый проект</p>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <button
 | 
			
		||||
                      className="createProjectBtn"
 | 
			
		||||
 | 
			
		||||
                    <BaseButton
 | 
			
		||||
                      styles={"createProjectBtn"}
 | 
			
		||||
                      onClick={() => {
 | 
			
		||||
                        dispatch(modalToggle("createProject"));
 | 
			
		||||
                        setModalCreateProject(true);
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      <span>+</span>Создать проект
 | 
			
		||||
                    </button>
 | 
			
		||||
                    </BaseButton>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <p className="no-projects__info">
 | 
			
		||||
                    Ставьте задачи, следите за прогрессом, ведите учёт рабочего
 | 
			
		||||
@@ -208,15 +210,15 @@ export const Tracker = () => {
 | 
			
		||||
              )}
 | 
			
		||||
            {Boolean(projects.length) && !loader && (
 | 
			
		||||
              <div className="create-newProject">
 | 
			
		||||
                <button
 | 
			
		||||
                  className="createProjectBtn"
 | 
			
		||||
                <BaseButton
 | 
			
		||||
                  styles="createProjectBtn"
 | 
			
		||||
                  onClick={() => {
 | 
			
		||||
                    dispatch(modalToggle("createProject"));
 | 
			
		||||
                    setModalCreateProject(true);
 | 
			
		||||
                  }}
 | 
			
		||||
                >
 | 
			
		||||
                  <span>+</span>Создать проект
 | 
			
		||||
                </button>
 | 
			
		||||
                </BaseButton>
 | 
			
		||||
                <p>
 | 
			
		||||
                  Ставьте задачи, следите за прогрессом, ведите учёт рабочего
 | 
			
		||||
                  времени
 | 
			
		||||
 
 | 
			
		||||
@@ -142,8 +142,6 @@
 | 
			
		||||
                margin-left: 17px;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            button {
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &__info {
 | 
			
		||||
@@ -155,16 +153,11 @@
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .createProjectBtn {
 | 
			
		||||
          background: #52b709;
 | 
			
		||||
          border-radius: 44px;
 | 
			
		||||
          max-width: 188px;
 | 
			
		||||
          height: 50px;
 | 
			
		||||
          width: 100%;
 | 
			
		||||
          border: none;
 | 
			
		||||
          font-weight: 400;
 | 
			
		||||
          font-size: 15px;
 | 
			
		||||
          line-height: 32px;
 | 
			
		||||
          color: #ffffff;
 | 
			
		||||
          display: flex;
 | 
			
		||||
          align-items: center;
 | 
			
		||||
          justify-content: center;
 | 
			
		||||
@@ -222,23 +215,23 @@
 | 
			
		||||
            align-items: center;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          h4 {
 | 
			
		||||
          h5 {
 | 
			
		||||
            color: #1458dd;
 | 
			
		||||
            font-weight: 700;
 | 
			
		||||
            font-size: 22px;
 | 
			
		||||
            line-height: 32px;
 | 
			
		||||
            margin-bottom: 0;
 | 
			
		||||
            max-width: 30%;
 | 
			
		||||
            word-break: break-all;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &__add {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            span {
 | 
			
		||||
            margin: 0 15px 0 10px;
 | 
			
		||||
 | 
			
		||||
            .button-add-column {
 | 
			
		||||
              width: 33px;
 | 
			
		||||
              height: 33px;
 | 
			
		||||
              background: #52b709;
 | 
			
		||||
              border-radius: 44px;
 | 
			
		||||
              color: whitesmoke;
 | 
			
		||||
              cursor: pointer;
 | 
			
		||||
              font-size: 15px;
 | 
			
		||||
              display: flex;
 | 
			
		||||
              align-items: center;
 | 
			
		||||
@@ -315,7 +308,7 @@
 | 
			
		||||
              z-index: 2;
 | 
			
		||||
              display: flex;
 | 
			
		||||
              flex-direction: column;
 | 
			
		||||
              background: linear-gradient(180deg, #FFFFFF 0%, #EBEBEB 100%);
 | 
			
		||||
              background: linear-gradient(180deg, #ffffff 0%, #ebebeb 100%);
 | 
			
		||||
              border-radius: 40px;
 | 
			
		||||
              padding: 33px 24px 44px 34px;
 | 
			
		||||
              width: 425px;
 | 
			
		||||
@@ -323,15 +316,16 @@
 | 
			
		||||
 | 
			
		||||
              &__close {
 | 
			
		||||
                cursor: pointer;
 | 
			
		||||
                width: 8px;
 | 
			
		||||
                height: 8px;
 | 
			
		||||
                position: absolute;
 | 
			
		||||
                right: 20px;
 | 
			
		||||
                top: 15px;
 | 
			
		||||
                margin-left: auto;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              &__count {
 | 
			
		||||
                display: flex;
 | 
			
		||||
                align-items: end;
 | 
			
		||||
                color: #1458DD;
 | 
			
		||||
                color: #1458dd;
 | 
			
		||||
                font-size: 22px;
 | 
			
		||||
                margin-top: 10px;
 | 
			
		||||
                span {
 | 
			
		||||
@@ -355,7 +349,7 @@
 | 
			
		||||
                span {
 | 
			
		||||
                  width: auto;
 | 
			
		||||
                  height: auto;
 | 
			
		||||
                  color: #1458DD;
 | 
			
		||||
                  color: #1458dd;
 | 
			
		||||
                  font-weight: 600;
 | 
			
		||||
                  font-size: 18px;
 | 
			
		||||
                  line-height: 22px;
 | 
			
		||||
@@ -397,8 +391,8 @@
 | 
			
		||||
 | 
			
		||||
                .delete {
 | 
			
		||||
                  cursor: pointer;
 | 
			
		||||
                  width: 14px;
 | 
			
		||||
                  height: 14px;
 | 
			
		||||
                  width: 20px;
 | 
			
		||||
                  height: 20px;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
@@ -407,7 +401,7 @@
 | 
			
		||||
                cursor: pointer;
 | 
			
		||||
 | 
			
		||||
                span {
 | 
			
		||||
                  background: #8BCC60;
 | 
			
		||||
                  background: #8bcc60;
 | 
			
		||||
                  left: 0;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@@ -424,6 +418,7 @@
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &__checkBox {
 | 
			
		||||
            margin: 0 15px 0 0;
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
@@ -551,6 +546,13 @@
 | 
			
		||||
            display: flex;
 | 
			
		||||
            flex-direction: column;
 | 
			
		||||
            justify-content: space-between;
 | 
			
		||||
            transition: 0.4s;
 | 
			
		||||
 | 
			
		||||
            &:hover {
 | 
			
		||||
              transform: scale(0.99);
 | 
			
		||||
              box-shadow: 4px 4px 8px 0px rgba(34, 60, 80, 0.11);
 | 
			
		||||
              transition: 0.4s;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &__hide {
 | 
			
		||||
              opacity: 0;
 | 
			
		||||
@@ -771,6 +773,10 @@
 | 
			
		||||
              max-width: 450px;
 | 
			
		||||
              width: 100%;
 | 
			
		||||
 | 
			
		||||
              &:focus-within {
 | 
			
		||||
                border: 1px solid #0000004d;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              @media (max-width: 690px) {
 | 
			
		||||
                max-width: 350px;
 | 
			
		||||
              }
 | 
			
		||||
@@ -834,8 +840,15 @@
 | 
			
		||||
              border-radius: 12px;
 | 
			
		||||
              padding: 12px 42px 7px 32px;
 | 
			
		||||
              justify-content: space-between;
 | 
			
		||||
              transition: 0.4s;
 | 
			
		||||
              cursor: pointer;
 | 
			
		||||
 | 
			
		||||
              &:hover {
 | 
			
		||||
                transform: scale(0.99);
 | 
			
		||||
                box-shadow: 4px 4px 8px 0px rgba(34, 60, 80, 0.11);
 | 
			
		||||
                transition: 0.4s;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              &__info {
 | 
			
		||||
                display: flex;
 | 
			
		||||
                flex-direction: column;
 | 
			
		||||
@@ -968,9 +981,12 @@
 | 
			
		||||
            background: #f1f1f1;
 | 
			
		||||
            border-radius: 12px;
 | 
			
		||||
            padding: 12px 42px 7px 32px;
 | 
			
		||||
            transition: 0.4s;
 | 
			
		||||
 | 
			
		||||
            &:hover {
 | 
			
		||||
              background: var(--ds-background-neutral-subtle-hovered, #f4f5f7);
 | 
			
		||||
              transform: scale(0.99);
 | 
			
		||||
              box-shadow: 4px 4px 8px 0px rgba(34, 60, 80, 0.11);
 | 
			
		||||
              transition: 0.4s;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            p {
 | 
			
		||||
@@ -1047,6 +1063,10 @@
 | 
			
		||||
              max-width: 300px;
 | 
			
		||||
              width: 100%;
 | 
			
		||||
 | 
			
		||||
              &:focus-within {
 | 
			
		||||
                border: 1px solid #0000004d;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              @media (max-width: 590px) {
 | 
			
		||||
                max-width: 230px;
 | 
			
		||||
              }
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ const initialState = {
 | 
			
		||||
  boardLoader: false,
 | 
			
		||||
  columnName: "",
 | 
			
		||||
  columnId: 0,
 | 
			
		||||
  columnPriority: 0
 | 
			
		||||
  columnPriority: 0,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const setProjectBoardFetch = createAsyncThunk("userInfo", (id) =>
 | 
			
		||||
@@ -51,13 +51,16 @@ export const projectsTrackerSlice = createSlice({
 | 
			
		||||
    moveProjectTask: (state, action) => {
 | 
			
		||||
      state.projectBoard.columns.forEach((column, index) => {
 | 
			
		||||
        if (column.id === action.payload.columnId) {
 | 
			
		||||
          column.tasks.push({...action.payload.startWrapperIndex.task, column_id: column.id});
 | 
			
		||||
          column.tasks.push({
 | 
			
		||||
            ...action.payload.startWrapperIndex.task,
 | 
			
		||||
            column_id: column.id,
 | 
			
		||||
          });
 | 
			
		||||
          apiRequest(`/task/update-task`, {
 | 
			
		||||
            method: "PUT",
 | 
			
		||||
            data: {
 | 
			
		||||
              task_id: action.payload.startWrapperIndex.task.id,
 | 
			
		||||
              column_id: column.id,
 | 
			
		||||
              priority: column.tasks.length - 1
 | 
			
		||||
              priority: column.tasks.length - 1,
 | 
			
		||||
            },
 | 
			
		||||
          }).then(() => {});
 | 
			
		||||
        }
 | 
			
		||||
@@ -71,10 +74,15 @@ export const projectsTrackerSlice = createSlice({
 | 
			
		||||
    movePositionProjectTask: (state, action) => {
 | 
			
		||||
      state.projectBoard.columns.forEach((column, index) => {
 | 
			
		||||
        if (column.id === action.payload.startTask.column_id) {
 | 
			
		||||
          state.projectBoard.columns[index].tasks = column.tasks.filter((task) => task.id !== action.payload.startTask.id)
 | 
			
		||||
          state.projectBoard.columns[index].tasks = column.tasks.filter(
 | 
			
		||||
            (task) => task.id !== action.payload.startTask.id
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        if (column.id === action.payload.finishTask.column_id) {
 | 
			
		||||
          column.tasks.splice(action.payload.finishIndex, 0, {...action.payload.startTask, column_id: column.id})
 | 
			
		||||
          column.tasks.splice(action.payload.finishIndex, 0, {
 | 
			
		||||
            ...action.payload.startTask,
 | 
			
		||||
            column_id: column.id,
 | 
			
		||||
          });
 | 
			
		||||
          apiRequest(`/task/update-task`, {
 | 
			
		||||
            method: "PUT",
 | 
			
		||||
            data: {
 | 
			
		||||
@@ -82,14 +90,14 @@ export const projectsTrackerSlice = createSlice({
 | 
			
		||||
              column_id: column.id,
 | 
			
		||||
            },
 | 
			
		||||
          }).then(() => {});
 | 
			
		||||
          const priorityTasks = []
 | 
			
		||||
          const priorityTasks = [];
 | 
			
		||||
          column.tasks.forEach((task, index) => {
 | 
			
		||||
            const curTask = {
 | 
			
		||||
              task_id: task.id,
 | 
			
		||||
              priority: index
 | 
			
		||||
            }
 | 
			
		||||
            priorityTasks.push(curTask)
 | 
			
		||||
          })
 | 
			
		||||
              priority: index,
 | 
			
		||||
            };
 | 
			
		||||
            priorityTasks.push(curTask);
 | 
			
		||||
          });
 | 
			
		||||
          apiRequest(`/task/set-priority`, {
 | 
			
		||||
            method: "POST",
 | 
			
		||||
            data: {
 | 
			
		||||
@@ -98,17 +106,21 @@ export const projectsTrackerSlice = createSlice({
 | 
			
		||||
            },
 | 
			
		||||
          }).then(() => {});
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    filterCreatedByMe: (state, action) => {
 | 
			
		||||
      state.projectBoard.columns.forEach((column) => {
 | 
			
		||||
        column.tasks = column.tasks.filter((task) => task.user_id === action.payload)
 | 
			
		||||
      })
 | 
			
		||||
        column.tasks = column.tasks.filter(
 | 
			
		||||
          (task) => task.user_id === action.payload
 | 
			
		||||
        );
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    filteredParticipateTasks: (state, action) => {
 | 
			
		||||
      state.projectBoard.columns.forEach((column) => {
 | 
			
		||||
        column.tasks = column.tasks.filter((task) => task.taskUsers.some((person) => person.user_id === action.payload))
 | 
			
		||||
      })
 | 
			
		||||
        column.tasks = column.tasks.filter((task) =>
 | 
			
		||||
          task.taskUsers.some((person) => person.user_id === action.payload)
 | 
			
		||||
        );
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    setColumnName: (state, action) => {
 | 
			
		||||
      state.columnName = action.payload;
 | 
			
		||||
@@ -117,7 +129,7 @@ export const projectsTrackerSlice = createSlice({
 | 
			
		||||
      state.columnId = action.payload;
 | 
			
		||||
    },
 | 
			
		||||
    setColumnPriority: (state, action) => {
 | 
			
		||||
      state.columnPriority = action.payload
 | 
			
		||||
      state.columnPriority = action.payload;
 | 
			
		||||
    },
 | 
			
		||||
    editProjectName: (state, action) => {
 | 
			
		||||
      state.projects.forEach((project) => {
 | 
			
		||||
@@ -162,7 +174,7 @@ export const {
 | 
			
		||||
  addPersonToProject,
 | 
			
		||||
  filterCreatedByMe,
 | 
			
		||||
  filteredParticipateTasks,
 | 
			
		||||
  movePositionProjectTask
 | 
			
		||||
  movePositionProjectTask,
 | 
			
		||||
} = projectsTrackerSlice.actions;
 | 
			
		||||
 | 
			
		||||
export const getProjects = (state) => state.tracker.projects;
 | 
			
		||||
@@ -172,6 +184,6 @@ export const getValueModalType = (state) => state.tracker.modalType;
 | 
			
		||||
export const getBoarderLoader = (state) => state.tracker.boardLoader;
 | 
			
		||||
export const getColumnName = (state) => state.tracker.columnName;
 | 
			
		||||
export const getColumnId = (state) => state.tracker.columnId;
 | 
			
		||||
export const getColumnPriority = (state) => state.tracker.columnPriority
 | 
			
		||||
export const getColumnPriority = (state) => state.tracker.columnPriority;
 | 
			
		||||
 | 
			
		||||
export default projectsTrackerSlice.reducer;
 | 
			
		||||
 
 | 
			
		||||
@@ -53,12 +53,11 @@ export function scrollToForm() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getCorrectRequestDate(date) {
 | 
			
		||||
  const yyyy = String(date.getUTCFullYear())
 | 
			
		||||
  const yyyy = String(date.getUTCFullYear());
 | 
			
		||||
  const mm = String(date.getUTCMonth() + 1).padStart(2, "0");
 | 
			
		||||
  const dd = String(date.getUTCDate()).padStart(2, "0");
 | 
			
		||||
  const hh = String(date.getUTCHours())
 | 
			
		||||
  const min = String(date.getUTCMinutes())
 | 
			
		||||
  const sec = String(date.getUTCSeconds())
 | 
			
		||||
  return `${yyyy}-${mm}-${dd} ${hh}:${min}:${sec}`
 | 
			
		||||
  const hh = String(date.getUTCHours());
 | 
			
		||||
  const min = String(date.getUTCMinutes());
 | 
			
		||||
  const sec = String(date.getUTCSeconds());
 | 
			
		||||
  return `${yyyy}-${mm}-${dd} ${hh}:${min}:${sec}`;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user