diff --git a/src/App.js b/src/App.js index e459d6c9..400f14f3 100644 --- a/src/App.js +++ b/src/App.js @@ -35,6 +35,7 @@ import { AuthForCandidate } from "./pages/AuthForCandidate/AuthForCandidate"; import { RegistrationForCandidate } from "./pages/RegistrationForCandidate/RegistrationForCandidate"; import { ProfileCandidate } from "./pages/ProfileCandidate/ProfileCandidate"; import { PassingTests } from "./pages/quiz/PassingTests"; +import { ProjectTracker } from "./pages/ProjectTracker/ProjectTracker"; import "./assets/global.scss"; import "./fonts/stylesheet.css"; @@ -53,6 +54,7 @@ const App = () => { path="/tracker/:id" element={} > + }/> } /> { +export const ProjectTiket = ({ project, index }) => { const [modalSettings, setModalSettings] = useState(false); const dispatch = useDispatch(); @@ -49,13 +50,10 @@ export const ProjectTiket = ({ project, index, setOpenProject }) => { return (
-

{ - setOpenProject(true) - dispatch(setProjectBoardFetch(project.id)) - }}>{project.name}

+ {project.name}

Открытые задачи

- - + {project.columns.reduce((accumulator, currentValue) => accumulator + currentValue.tasks.length, 0)} {/*{project.columns.length ? '+' : ''}*/} setModalSettings(true)}> ... @@ -64,7 +62,7 @@ export const ProjectTiket = ({ project, index, setOpenProject }) => {
-
console.log(project)}> +

редактировать

diff --git a/src/components/ProjectTiket/projectTiket.scss b/src/components/ProjectTiket/projectTiket.scss index e7042099..ed8f08e2 100644 --- a/src/components/ProjectTiket/projectTiket.scss +++ b/src/components/ProjectTiket/projectTiket.scss @@ -19,7 +19,7 @@ padding: 8px 13px 8px; } - h3 { + a { font-weight: 700; font-size: 18px; line-height: 32px; @@ -27,7 +27,12 @@ margin-bottom: 10px; overflow: hidden; white-space: nowrap; + display: flex; text-overflow: ellipsis; + + &:hover { + color: black; + } } &__info { diff --git a/src/components/UI/TicketFullScreen/TicketFullScreen.js b/src/components/UI/TicketFullScreen/TicketFullScreen.js index 37a4b127..38b44a05 100644 --- a/src/components/UI/TicketFullScreen/TicketFullScreen.js +++ b/src/components/UI/TicketFullScreen/TicketFullScreen.js @@ -5,6 +5,8 @@ import { ProfileBreadcrumbs } from "../../ProfileBreadcrumbs/ProfileBreadcrumbs" import { Footer } from "../../Footer/Footer"; import { Link } from "react-router-dom"; import ModalAdd from "../ModalAdd/ModalAdd"; +import { useDispatch } from "react-redux"; +import {setToggleTab} from "../../../redux/projectsTrackerSlice"; import avatarMock1 from "../../../images/avatarMoсk1.png"; import avatarMock2 from "../../../images/avatarMoсk2.png"; @@ -28,10 +30,10 @@ import edit from "../../../images/edit.svg"; import "./ticketFullScreen.scss"; export const TicketFullScreen = ({}) => { - const [toggleTab, setToggleTab] = useState(1); const [addSubtask, setAddSubtask] = useState(false); const [modalAddWorker, setModalAddWorker] = useState(false); const [valueTiket, setValueTiket] = useState(""); + const dispatch = useDispatch(); const [tiket] = useState({ name: "Разработка трекера", @@ -52,7 +54,7 @@ export const TicketFullScreen = ({}) => { ]); const toggleTabs = (index) => { - setToggleTab(index); + dispatch(setToggleTab(index)); }; return ( @@ -71,31 +73,30 @@ export const TicketFullScreen = ({}) => {
-
toggleTabs(1)} > img

Проекты

-
-
+ toggleTabs(2)} > img - -

Все мои задачи

- -
-
Все мои задачи

+ + toggleTabs(3)} > img - -

Архив

- -
+

Архив

+
diff --git a/src/pages/ProjectTracker/ProjectTracker.js b/src/pages/ProjectTracker/ProjectTracker.js new file mode 100644 index 00000000..3af6307f --- /dev/null +++ b/src/pages/ProjectTracker/ProjectTracker.js @@ -0,0 +1,417 @@ +import React, {useEffect, useRef, useState} from "react"; +import {Link} from "react-router-dom"; +import { ProfileHeader } from "../../components/ProfileHeader/ProfileHeader"; +import { ProfileBreadcrumbs } from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs"; +import { Footer } from "../../components/Footer/Footer"; + +import { useDispatch, useSelector } from "react-redux"; +import {getProjectBoard, moveProjectTask, setProjectBoardFetch, setToggleTab} from "../../redux/projectsTrackerSlice"; + +import ModalTicket from "../../components/UI/ModalTicket/ModalTicket"; +import ModalAdd from "../../components/UI/ModalAdd/ModalAdd"; + +import project from "../../images/trackerProject.svg"; +import tasks from "../../images/trackerTasks.svg"; +import archive from "../../images/archiveTracker.svg"; +import avatarTest from "../../images/AvatarTest .png"; +import selectArrow from "../../images/select.svg"; +import commentsBoard from "../../images/commentsBoard.svg"; +import filesBoard from "../../images/filesBoard.svg"; +import arrow from "../../images/arrowCalendar.png"; + +import {apiRequest} from "../../api/request"; +import { Navigation } from "../../components/Navigation/Navigation"; + +export const ProjectTracker = () => { + const dispatch = useDispatch(); + const currentUrl = useState(window.location.pathname) + const projectId = currentUrl[0].split('/').at(-1) + + useEffect(() => { + dispatch(setProjectBoardFetch(projectId)) + }, []) + + // Modal State + const [modalActiveTicket, setModalActiveTicket] = useState(false); + const [selectedTicket, setSelectedTicket] = useState({}); + const [modalAddWorker, setModalAddWorker] = useState(false); + const [modalCreateColl, setModalCreateColl] = useState(false); + const [modalCreateTiket, setModalCreateTiket] = useState(false); + const [valueTiket, setValueTiket] = useState(""); + const [descriptionTicket, setDescriptionTicket] = useState("") + const [valueColl, setValueColl] = useState(""); + // + + const [selectedTab, setSelectedTab] = useState(0); + + const startWrapperIndexTest = useRef({}) + const [wrapperHover, setWrapperHover] = useState([ + false, + false, + false, + false, + ]); + + const projectBoard = useSelector(getProjectBoard); + + // function toggleMoreTasks(columnId) { + // setTabTaskMok((prevArray) => + // prevArray.map((elem, index) => { + // if (columnId === index) { + // return { ...elem, open: !elem.open }; + // } else { + // return elem; + // } + // }) + // ); + // } + + function dragStartHandler(e, task, columnId) { + startWrapperIndexTest.current = { task: task, index: columnId }; + setTimeout(() => { + e.target.classList.add("tasks__board__item__hide"); + }, 0); + } + + function dragEndHandler(e) { + setWrapperHover((prevArray) => + prevArray.map((elem) => { + return false; + }) + ); + e.target.classList.remove("tasks__board__item__hide"); + } + + function dragOverHandler(e) { + e.preventDefault(); + } + + function dragEnterHandler(columnId) { + if (columnId === startWrapperIndexTest.current.index) { + return; + } + setWrapperHover((prevArray) => + prevArray.map((elem, index) => { + if (index === columnId) { + return true; + } else { + return false; + } + }) + ); + } + function dragDropHandler(e, columnId) { + e.preventDefault(); + if (startWrapperIndexTest.current.index === columnId) { + return; + } + setWrapperHover((prevArray) => + prevArray.map((elem) => { + return false; + }) + ); + + if (columnId !== startWrapperIndexTest.current.index) { + dispatch(moveProjectTask({startWrapperIndex: startWrapperIndexTest.current, columnId})) + } + } + + function selectedTabTask(columnId) { + setSelectedTab(columnId); + setModalCreateTiket(true); + } + + function openTicket(e, task) { + setSelectedTicket(task); + setModalActiveTicket(true); + } + + function createTiket() { + if (!valueTiket || !descriptionTicket) { + return + } + + apiRequest('/task/create-task', { + method: 'POST', + data: { + project_id: projectBoard.id, + title: valueTiket, + description: descriptionTicket, + status: 1, + user_id: localStorage.getItem('id'), + column_id: selectedTab + } + }).then((res) => { + dispatch(setProjectBoardFetch(projectBoard.id)) + }) + + setModalCreateTiket(false); + setValueTiket(""); + setDescriptionTicket("") + } + + function createTab() { + if (!valueColl) { + return + } + + apiRequest('/project-column/create-column', { + method: 'POST', + data: { + project_id: projectBoard.id, + title: valueColl + } + }).then((res) => { + dispatch(setProjectBoardFetch(projectBoard.id)) + }) + setValueColl(""); + setModalCreateColl(false); + } + + return ( +
+ + +
+
+ +

Управление проектами с трекером

+
+
+
+
+ dispatch(setToggleTab(1))} + > + img +

Проекты

+ + dispatch(setToggleTab(2))} + > + img +

Все мои задачи

+ + dispatch(setToggleTab(3))} + > + img +

Архив

+ +
+
+
+
+
+

Проект : {projectBoard.name}

+ + +
+

Введите название колонки

+
+ setValueColl(e.target.value)} + > +
+
+ +
+ + +
+

Добавьте участника

+

+ Введите имя или e-mail{" "} +

+
+ setValueTiket(e.target.value)} + > +
+
+ +
+ +
+ setModalCreateColl(true)}>+ +

добавить колонку

+
+
+ avatar + avatar + +9 + + + + +

добавить участника

+
+
+ Участвую + arrow +
+
+ Мои + arrow +
+ +

Вернуться на проекты

+ arrow + +
+
+ + + + +
+

Введите название и описание задачи

+
+ setValueTiket(e.target.value)} + placeholder='Название задачи' + > +
+
+ setDescriptionTicket(e.target.value)} + placeholder='Описание задачи' + > +
+
+ +
+ +
+ {Boolean(projectBoard?.columns) && Boolean(projectBoard.columns.length) && projectBoard.columns.map((column) => { + return ( +
dragOverHandler(e)} + onDragEnter={(e) => dragEnterHandler(column.id)} + onDrop={(e) => dragDropHandler(e, column.id)} + className={`tasks__board ${ + column.tasks.length >= 3 ? "tasks__board__more" : "" + } ${ + wrapperHover[column.id] ? "tasks__board__hover" : "" + }`} + > +
+ {/**/} + + {column.title} + +
+ selectedTabTask(column.id)} + > + + + + ... +
+
+ {column.tasks.map((task, index) => { + if (index > 2) { + if (!column.open) { + return; + } + } + return ( +
+ dragStartHandler(e, task, column.id) + } + onDragEnd={(e) => dragEndHandler(e)} + onClick={(e) => openTicket(e, task)} + > +
+

{task.title}

+
+

+ {task.description} +

+
+
+ commentsImg + {task.comments} коментариев +
+
+ filesImg + {task.files} файлов +
+ {/*
*/} + {/* avatar*/} + {/* avatar*/} + {/*
*/} +
+
+ ); + })} + {column.tasks.length > 3 && ( + toggleMoreTasks(column.id)} + > + {column.open ? "-" : "+"} + + )} +
+ ); + })} +
+
+
+
+
+
+ ); +}; diff --git a/src/pages/Tracker/Tracker.js b/src/pages/Tracker/Tracker.js index d44d98b3..39e89014 100644 --- a/src/pages/Tracker/Tracker.js +++ b/src/pages/Tracker/Tracker.js @@ -1,27 +1,21 @@ -import React, {useEffect, useRef, useState} from "react"; +import React, {useEffect, useState} from "react"; import { ProfileHeader } from "../../components/ProfileHeader/ProfileHeader"; import { ProfileBreadcrumbs } from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs"; import { Footer } from "../../components/Footer/Footer"; import { useDispatch, useSelector } from "react-redux"; -import { setAllProjects, getProjects, getProjectBoard, moveProjectTask, setProjectBoardFetch } from "../../redux/projectsTrackerSlice"; +import { setAllProjects, getProjects, setToggleTab, getToggleTab } from "../../redux/projectsTrackerSlice"; -import ModalTicket from "../../components/UI/ModalTicket/ModalTicket"; import ModalCreate from "../../components/UI/ModalCreate/ModalCreate"; -import ModalAdd from "../../components/UI/ModalAdd/ModalAdd"; import ProjectTiket from "../../components/ProjectTiket/ProjectTiket"; import project from "../../images/trackerProject.svg"; import tasks from "../../images/trackerTasks.svg"; import archive from "../../images/archiveTracker.svg"; import avatarTest from "../../images/AvatarTest .png"; -import selectArrow from "../../images/select.svg"; -import commentsBoard from "../../images/commentsBoard.svg"; -import filesBoard from "../../images/filesBoard.svg"; import search from "../../images/serchIcon.png"; import noProjects from "../../images/noProjects.png"; -import arrow from "../../images/arrowCalendar.png"; import {apiRequest} from "../../api/request"; import { Navigation } from "../../components/Navigation/Navigation"; @@ -30,7 +24,8 @@ import "./tracker.scss"; export const Tracker = () => { const dispatch = useDispatch(); - const [toggleTab, setToggleTab] = useState(1); + const projects = useSelector(getProjects); + const tab = useSelector(getToggleTab) const [allTasks] = useState([ { name: "PR - 2245", @@ -254,28 +249,7 @@ export const Tracker = () => { const [filterCompleteTasks, setFilterCompleteTasks] = useState(completeTasks); // Modal State - const [modalActiveTicket, setModalActiveTicket] = useState(false); - const [selectedTicket, setSelectedTicket] = useState({}); - const [modalAddWorker, setModalAddWorker] = useState(false); const [modalCreateProject, setModalCreateProject] = useState(false); - const [modalCreateColl, setModalCreateColl] = useState(false); - const [modalCreateTiket, setModalCreateTiket] = useState(false); - const [valueTiket, setValueTiket] = useState(""); - const [descriptionTicket, setDescriptionTicket] = useState("") - const [valueColl, setValueColl] = useState(""); - // - - const [projectTasksOpen, setProjectTasksOpen] = useState(false); - - const [selectedTab, setSelectedTab] = useState(0); - - const startWrapperIndexTest = useRef({}) - const [wrapperHover, setWrapperHover] = useState([ - false, - false, - false, - false, - ]); useEffect(() => { apiRequest(`/project/project-list?user_id=${localStorage.getItem('id')}&expand=columns`).then((el) => { @@ -283,78 +257,10 @@ export const Tracker = () => { }) }, []) - const projects = useSelector(getProjects); - const projectBoard = useSelector(getProjectBoard); - const toggleTabs = (index) => { - if (projectTasksOpen) { - setProjectTasksOpen(false); - } - setToggleTab(index); + dispatch(setToggleTab(index)) }; - function toggleMoreTasks(columnId) { - setTabTaskMok((prevArray) => - prevArray.map((elem, index) => { - if (columnId === index) { - return { ...elem, open: !elem.open }; - } else { - return elem; - } - }) - ); - } - - function dragStartHandler(e, task, columnId) { - startWrapperIndexTest.current = { task: task, index: columnId }; - setTimeout(() => { - e.target.classList.add("tasks__board__item__hide"); - }, 0); - } - - function dragEndHandler(e) { - setWrapperHover((prevArray) => - prevArray.map((elem) => { - return false; - }) - ); - e.target.classList.remove("tasks__board__item__hide"); - } - - function dragOverHandler(e) { - e.preventDefault(); - } - - function dragEnterHandler(columnId) { - if (columnId === startWrapperIndexTest.current.index) { - return; - } - setWrapperHover((prevArray) => - prevArray.map((elem, index) => { - if (index === columnId) { - return true; - } else { - return false; - } - }) - ); - } - function dragDropHandler(e, columnId) { - e.preventDefault(); - if (startWrapperIndexTest.current.index === columnId) { - return; - } - setWrapperHover((prevArray) => - prevArray.map((elem) => { - return false; - }) - ); - - if (columnId !== startWrapperIndexTest.current.index) { - dispatch(moveProjectTask({startWrapperIndex: startWrapperIndexTest.current, columnId})) - } - } - function filterArchiveTasks(e) { setFilterCompleteTasks( completeTasks.filter((item) => { @@ -373,58 +279,6 @@ export const Tracker = () => { ); } - function selectedTabTask(columnId) { - setSelectedTab(columnId); - setModalCreateTiket(true); - } - - function openTicket(e, task) { - setSelectedTicket(task); - setModalActiveTicket(true); - } - - function createTiket() { - if (!valueTiket || !descriptionTicket) { - return - } - - apiRequest('/task/create-task', { - method: 'POST', - data: { - project_id: projectBoard.id, - title: valueTiket, - description: descriptionTicket, - status: 1, - user_id: localStorage.getItem('id'), - column_id: selectedTab - } - }).then((res) => { - dispatch(setProjectBoardFetch(projectBoard.id)) - }) - - setModalCreateTiket(false); - setValueTiket(""); - setDescriptionTicket("") - } - - function createTab() { - if (!valueColl) { - return - } - - apiRequest('/project-column/create-column', { - method: 'POST', - data: { - project_id: projectBoard.id, - title: valueColl - } - }).then((res) => { - dispatch(setProjectBoardFetch(projectBoard.id)) - }) - setValueColl(""); - setModalCreateColl(false); - } - return (
@@ -443,21 +297,21 @@ export const Tracker = () => {
toggleTabs(1)} > img

Проекты

toggleTabs(2)} > img

Все мои задачи

toggleTabs(3)} > img @@ -467,7 +321,7 @@ export const Tracker = () => {
{ /> {Boolean(projects.length) && - !projectTasksOpen && projects.map((project, index) => { return ( ); })} - {!Boolean(projects.length) && !projectTasksOpen && ( + {!Boolean(projects.length) && (
@@ -509,7 +361,7 @@ export const Tracker = () => {

)} - {Boolean(projects.length) && !projectTasksOpen && ( + {Boolean(projects.length) && (
-
-
-

Проект : {projectBoard.name}

- - -
-

Введите название колонки

-
- setValueColl(e.target.value)} - > -
-
- -
- - -
-

Добавьте участника

-

- Введите имя или e-mail{" "} -

-
- setValueTiket(e.target.value)} - > -
-
- -
- -
- setModalCreateColl(true)}>+ -

добавить колонку

-
-
- avatar - avatar - +9 - - + - -

добавить участника

-
-
- Участвую - arrow -
-
- Мои - arrow -
-
setProjectTasksOpen(false)} - > -

Вернуться на проекты

- arrow -
-
-
- - - - -
-

Введите название и описание задачи

-
- setValueTiket(e.target.value)} - placeholder='Название задачи' - > -
-
- setDescriptionTicket(e.target.value)} - placeholder='Описание задачи' - > -
-
- -
- -
- {Boolean(projectBoard?.columns) && Boolean(projectBoard.columns.length) && projectBoard.columns.map((column) => { - return ( -
dragOverHandler(e)} - onDragEnter={(e) => dragEnterHandler(column.id)} - onDrop={(e) => dragDropHandler(e, column.id)} - className={`tasks__board ${ - column.tasks.length >= 3 ? "tasks__board__more" : "" - } ${ - wrapperHover[column.id] ? "tasks__board__hover" : "" - }`} - > -
- {/**/} - - {column.title} - -
- selectedTabTask(column.id)} - > - + - - ... -
-
- {column.tasks.map((task, index) => { - if (index > 2) { - if (!column.open) { - return; - } - } - return ( -
- dragStartHandler(e, task, column.id) - } - onDragEnd={(e) => dragEndHandler(e)} - onClick={(e) => openTicket(e, task)} - > -
-

{task.title}

-
-

- {task.description} -

-
-
- commentsImg - {task.comments} коментариев -
-
- filesImg - {task.files} файлов -
- {/*
*/} - {/* avatar*/} - {/* avatar*/} - {/*
*/} -
-
- ); - })} - {column.tasks.length > 3 && ( - toggleMoreTasks(column.id)} - > - {column.open ? "-" : "+"} - - )} -
- ); - })} -
-
-
{
{ state.projects.push(action.payload); }, + setToggleTab: (state, action) => { + state.toggleTab = action.payload + }, deleteProject: (state, action) => { - console.log(action.payload) state.projects = state.projects.filter((project) => project.id !== action.payload.id) }, moveProjectTask: (state, action) => { @@ -52,9 +55,10 @@ export const projectsTrackerSlice = createSlice({ } }); -export const { setProject, deleteProject, setAllProjects, moveProjectTask } = projectsTrackerSlice.actions; +export const { setProject, deleteProject, setAllProjects, moveProjectTask, setToggleTab } = projectsTrackerSlice.actions; export const getProjects = (state) => state.tracker.projects; export const getProjectBoard = (state) => state.tracker.projectBoard; +export const getToggleTab = (state) => state.tracker.toggleTab export default projectsTrackerSlice.reducer;