diff --git a/src/components/UI/ModalTicket/ModalTicket.jsx b/src/components/UI/ModalTicket/ModalTicket.jsx index cee567d2..290ff0bd 100644 --- a/src/components/UI/ModalTicket/ModalTicket.jsx +++ b/src/components/UI/ModalTicket/ModalTicket.jsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, {useEffect, useState} from "react"; import { Link } from "react-router-dom"; import TrackerModal from "../TrackerModal/TrackerModal"; import { apiRequest } from "../../../api/request"; @@ -32,6 +32,8 @@ export const ModalTiсket = ({ }) => { const dispatch = useDispatch(); const [addSubtask, setAddSubtask] = useState(false); + const [editOpen, setEditOpen] = useState(false); + const [inputsValue, setInputsValue] = useState({title: task.title, description: task.description}) function deleteTask() { apiRequest("/task/update-task", { @@ -46,6 +48,19 @@ export const ModalTiсket = ({ }); } + function editTask() { + apiRequest("/task/update-task", { + method: "PUT", + data: { + task_id: task.id, + title: inputsValue.title, + description: inputsValue.description + }, + }).then((res) => { + dispatch(setProjectBoardFetch(projectId)); + }); + } + return (
Задача -
{task.title}
+ {editOpen ? { + setInputsValue((prevValue) => ({...prevValue, title: e.target.value})) + }} /> :
{inputsValue.title}
}
-

{task.description}

+ {editOpen ? { + setInputsValue((prevValue) => ({...prevValue, description: e.target.value})) + }}/> :

{inputsValue.description}

} -

{task.description}

@@ -138,15 +156,22 @@ export const ModalTiсket = ({

-
+
{ + if(editOpen) { + setEditOpen(!editOpen) + editTask() + } else { + setEditOpen(!editOpen) + } + }}> -

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

+

{editOpen ? 'сохранить' : 'редактировать'}

ссылка на проект

-
+

в архив

diff --git a/src/components/UI/ModalTicket/ModalTicket.scss b/src/components/UI/ModalTicket/ModalTicket.scss index 727f8f5b..fdd19c48 100644 --- a/src/components/UI/ModalTicket/ModalTicket.scss +++ b/src/components/UI/ModalTicket/ModalTicket.scss @@ -6,14 +6,13 @@ position: fixed; top: 0; left: 0; - display: flex; + display: none; align-items: center; justify-content: center; - transform: scale(0); } .modal-tiket.active { - transform: scale(1); + display: flex; } .modal-tiket__content { @@ -50,6 +49,16 @@ &__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 { @@ -64,10 +73,14 @@ font-size: 16px; line-height: 24px; color: #1a1919; + margin-bottom: 0; } } &__description { + display: flex; + flex-direction: column; + margin-top: 10px; p { font-weight: 400; font-size: 14px; @@ -77,7 +90,8 @@ } .image-task { - margin: 0 0 20px 0; + margin: 10px 0 20px 0; + max-width: 330px; } } @@ -313,11 +327,21 @@ 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; + } + } } } } diff --git a/src/components/UI/TicketFullScreen/TicketFullScreen.jsx b/src/components/UI/TicketFullScreen/TicketFullScreen.jsx index 008b16a9..46f1c769 100644 --- a/src/components/UI/TicketFullScreen/TicketFullScreen.jsx +++ b/src/components/UI/TicketFullScreen/TicketFullScreen.jsx @@ -6,9 +6,10 @@ import { Footer } from "../../Footer/Footer"; import { Link, useParams, useNavigate } from "react-router-dom"; import TrackerModal from "../TrackerModal/TrackerModal"; import { Navigation } from "../../Navigation/Navigation"; +import {Loader} from "../../Loader/Loader"; import { useDispatch } from "react-redux"; -import { modalToggle, setToggleTab } from "../../../redux/projectsTrackerSlice"; +import {modalToggle, setToggleTab} from "../../../redux/projectsTrackerSlice"; import { apiRequest } from "../../../api/request"; import project from "../../../images/trackerProject.svg"; @@ -37,13 +38,18 @@ export const TicketFullScreen = ({}) => { const navigate = useNavigate(); const [projectInfo, setProjectInfo] = useState({}); const [taskInfo, setTaskInfo] = useState({}); + const [editOpen, setEditOpen] = useState(false); + const [inputsValue, setInputsValue] = useState({}) + const [loader, setLoader] = useState(true) useEffect(() => { apiRequest(`/task/get-task?task_id=${ticketId.id}`).then((taskInfo) => { setTaskInfo(taskInfo); + setInputsValue({title: taskInfo.title, description: taskInfo.description}) apiRequest(`/project/get-project?project_id=${taskInfo.project_id}`).then( (project) => { setProjectInfo(project); + setLoader(false) } ); }); @@ -61,6 +67,18 @@ export const TicketFullScreen = ({}) => { }); } + function editTask() { + apiRequest("/task/update-task", { + method: "PUT", + data: { + task_id: taskInfo.id, + title: inputsValue.title, + description: inputsValue.description + }, + }).then((res) => { + }); + } + const toggleTabs = (index) => { dispatch(setToggleTab(index)); }; @@ -107,6 +125,8 @@ export const TicketFullScreen = ({}) => {

Архив

+ {loader ? : + <>
@@ -153,11 +173,14 @@ export const TicketFullScreen = ({}) => {
Задача -
{taskInfo.title}
+ {editOpen ? { + setInputsValue((prevValue) => ({...prevValue, title: e.target.value})) + }} /> :
{inputsValue.title}
}
-

{taskInfo.description}

+ {editOpen ? { + setInputsValue((prevValue) => ({...prevValue, description: e.target.value})) + }}/> :

{inputsValue.description}

} -

{taskInfo.description}

@@ -229,9 +252,16 @@ export const TicketFullScreen = ({}) => {

-
+
{ + if(editOpen) { + setEditOpen(!editOpen) + editTask() + } else { + setEditOpen(!editOpen) + } + }}> -

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

+

{editOpen ? 'сохранить' : 'редактировать'}

@@ -248,6 +278,8 @@ export const TicketFullScreen = ({}) => {
+ + }
diff --git a/src/components/UI/TrackerModal/TrackerModal.jsx b/src/components/UI/TrackerModal/TrackerModal.jsx index 9951b10b..d8361f34 100644 --- a/src/components/UI/TrackerModal/TrackerModal.jsx +++ b/src/components/UI/TrackerModal/TrackerModal.jsx @@ -1,16 +1,22 @@ -import React, { useState } from "react"; +import React, {useEffect, useState} from "react"; import { useDispatch, useSelector } from "react-redux"; import { apiRequest } from "../../../api/request"; +import { urlForLocal } from '../../../helper' import { + setColumnName, getProjectBoard, getValueModalType, setProject, setProjectBoardFetch, editProjectName, - getColumnTitle, + editColumnName, + getColumnName, + getColumnId } from "../../../redux/projectsTrackerSlice"; +import arrowDown from "../../../images/selectArrow.png" + import "./trackerModal.scss"; export const TrackerModal = ({ @@ -20,22 +26,22 @@ export const TrackerModal = ({ defautlInput, titleProject, projectId, - titleColumn + priorityTask }) => { const dispatch = useDispatch(); const projectBoard = useSelector(getProjectBoard); + const columnName = useSelector(getColumnName); + const columnId = useSelector(getColumnId) const modalType = useSelector(getValueModalType); - - const [emailWorker, setEmailWorker] = useState(""); const [projectName, setProjectName] = useState(defautlInput); - const [editTitleColumn, setEditTitleColumn] = useState(titleColumn); - const [valueColumn, setValueColumn] = useState(""); 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) function createTab() { if (!valueColumn) { @@ -69,6 +75,7 @@ export const TrackerModal = ({ status: 1, user_id: localStorage.getItem("id"), column_id: selectedTab, + priority: priorityTask }, }).then((res) => { dispatch(setProjectBoardFetch(projectBoard.id)); @@ -92,6 +99,19 @@ export const TrackerModal = ({ }); } + function changeColumnName() { + apiRequest("/project-column/update-column", { + method: "PUT", + data: { + column_id: columnId, + title: columnName + } + }).then((res) => { + setActive(false); + dispatch(editColumnName({id: columnId, title: columnName})) + }) + } + function createProject() { if (nameProject === "") { return; @@ -112,6 +132,23 @@ export const TrackerModal = ({ } } + function addUserToProject() { + apiRequest("/project/add-user", { + method: "POST", + data: { + user_id: selectedWorker.id, + project_id: projectBoard.id + } + }).then((el) => { + setActive(false); + selectedWorker(null) + }) + } + + useEffect(() => { + modalType === "addWorker" ? apiRequest('/project/my-employee').then((el) => setWorkers(el.managerEmployees)) : '' + }, [modalType]) + return (

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

-

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

-
- setEmailWorker(e.target.value)} - /> + {/*
*/} + {/* setEmailWorker(e.target.value)}*/} + {/* />*/} + {/*
*/} +
setSelectWorkersOpen(!selectWorkersOpen)}> +

{selectedWorker ? selectedWorker.employee.fio : 'Выберите пользователя'}

+ arrow + {Boolean(selectWorkersOpen) && +
+ {workers.map((worker) => { + if (worker === selectedWorker) { + return + } + return
setSelectedWorker(worker)}> +

{worker.employee.fio}

+ avatar +
+ }) + } +
+ }
@@ -243,12 +294,12 @@ export const TrackerModal = ({
setEditTitleColumn(e.target.value)} + value={columnName} + onChange={(e) => dispatch(setColumnName(e.target.value))} />
-
diff --git a/src/components/UI/TrackerModal/trackerModal.scss b/src/components/UI/TrackerModal/trackerModal.scss index ca46330b..ab934e11 100644 --- a/src/components/UI/TrackerModal/trackerModal.scss +++ b/src/components/UI/TrackerModal/trackerModal.scss @@ -61,6 +61,56 @@ 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 { diff --git a/src/pages/ProjectTracker/ProjectTracker.js b/src/pages/ProjectTracker/ProjectTracker.js index 842f85a0..854e5ced 100644 --- a/src/pages/ProjectTracker/ProjectTracker.js +++ b/src/pages/ProjectTracker/ProjectTracker.js @@ -16,7 +16,8 @@ import { setProjectBoardFetch, setToggleTab, activeLoader, - setColumnTitle, + setColumnName, + setColumnId, } from "../../redux/projectsTrackerSlice"; import ModalTicket from "../../components/UI/ModalTicket/ModalTicket"; @@ -25,7 +26,6 @@ import TrackerModal from "../../components/UI/TrackerModal/TrackerModal"; 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"; @@ -39,6 +39,7 @@ export const ProjectTracker = () => { const [openColumnSelect, setOpenColumnSelect] = useState({}); const [selectedTab, setSelectedTab] = useState(0); + const [priorityTask, setPriorityTask] = useState(0); const [wrapperHover, setWrapperHover] = useState({}); const [modalAdd, setModalAdd] = useState(false); const [modalActiveTicket, setModalActiveTicket] = useState(false); @@ -125,10 +126,11 @@ export const ProjectTracker = () => { } } - function selectedTabTask(columnId) { + function selectedTabTask(columnId, length) { setSelectedTab(columnId); dispatch(modalToggle("createTiketProject")); setModalAdd(true); + setPriorityTask(length + 1) } function openTicket(e, task) { @@ -196,6 +198,7 @@ export const ProjectTracker = () => { active={modalAdd} setActive={setModalAdd} selectedTab={selectedTab} + priorityTask={priorityTask} /> {loader && } @@ -217,9 +220,9 @@ export const ProjectTracker = () => {

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

- avatar - avatar - +9 + {/*avatar*/} + {/*avatar*/} + {projectBoard.projectUsers?.length} { @@ -246,13 +249,13 @@ export const ProjectTracker = () => {
- + {Boolean(modalActiveTicket) && }
{Boolean(projectBoard?.columns) && @@ -270,19 +273,13 @@ export const ProjectTracker = () => { wrapperHover[column.id] ? "tasks__board__hover" : "" }`} > -
{/**/} {column.title}
selectedTabTask(column.id)} + onClick={() => selectedTabTask(column.id, column.tasks.length)} > + @@ -309,6 +306,8 @@ export const ProjectTracker = () => { [column.id]: false, })); dispatch(modalToggle("editColumn")); + dispatch(setColumnName(column.title)) + dispatch(setColumnId(column.id)) setModalAdd(true); }} > @@ -325,11 +324,11 @@ export const ProjectTracker = () => {
)} {column.tasks.map((task, index) => { - if (index > 2) { - if (!column.open) { - return; - } - } + // if (index > 2) { + // if (!column.open) { + // return; + // } + // } return (
{
commentsImg - {task.comments} коментариев + {task.comment_count} коментариев
filesImg @@ -364,18 +363,18 @@ export const ProjectTracker = () => {
); })} - {column.tasks.length > 3 && ( - toggleMoreTasks(column.id)} - > - {column.open ? "-" : "+"} - - )} + {/*{column.tasks.length > 3 && (*/} + {/* toggleMoreTasks(column.id)}*/} + {/* >*/} + {/* {column.open ? "-" : "+"}*/} + {/* */} + {/*)}*/}
); })} diff --git a/src/pages/Tracker/Tracker.js b/src/pages/Tracker/Tracker.js index bbd14e32..f6291b7b 100644 --- a/src/pages/Tracker/Tracker.js +++ b/src/pages/Tracker/Tracker.js @@ -39,7 +39,7 @@ export const Tracker = () => { const [filteredAllTasks, setFilteredAllTasks] = useState([]); const [loader, setLoader] = useState(false); const [filterCompleteTasks, setFilterCompleteTasks] = useState([]); - // const [allCompletedTasks, setAllCompletedTasks] = useState([]) + const [allCompletedTasks, setAllCompletedTasks] = useState([]) const [modalCreateProject, setModalCreateProject] = useState(false); @@ -56,13 +56,22 @@ export const Tracker = () => { // if (project.status === 10 && project.columns.length) { // return project // } - // }).map((project) => { return project.columns})) + // }).map((project) => { return project.columns}).reduce((acu, curr) => { + // curr.forEach((item) => { + // acu.push(...item.tasks) + // }) + // return acu + // }, [])) }); apiRequest( `/task/get-user-tasks?user_id=${localStorage.getItem("id")}` ).then((el) => { - setAllTasks(el); - setFilteredAllTasks(el); + const allTasks = el.filter((item) => item.status !== 0) + const completedTasks = el.filter((item) => item.status === 0) + setAllTasks(allTasks); + setFilteredAllTasks(allTasks); + setAllCompletedTasks(completedTasks) + setFilterCompleteTasks(completedTasks) }); }, []); @@ -89,21 +98,21 @@ export const Tracker = () => { } function filterArchiveTasks(e) { - // setFilterCompleteTasks( - // completeTasks.filter((item) => { - // if (!e.target.value) { - // return item; - // } - // if ( - // item.name.toLowerCase().startsWith(e.target.value.toLowerCase()) || - // item.description - // .toLowerCase() - // .startsWith(e.target.value.toLowerCase()) - // ) { - // return item; - // } - // }) - // ); + setFilterCompleteTasks( + allCompletedTasks.filter((item) => { + if (!e.target.value) { + return item; + } + if ( + item.title.toLowerCase().startsWith(e.target.value.toLowerCase()) || + item.description + .toLowerCase() + .startsWith(e.target.value.toLowerCase()) + ) { + return item; + } + }) + ); } return ( @@ -281,19 +290,21 @@ export const Tracker = () => {
+ {loader && } + {!loader && <> {Boolean(filterCompleteTasks.length) ? ( filterCompleteTasks.map((task, index) => { return (
-

{task.description}

-

{task.dateComplete}

+

{task.title}

+

{task.description}

- avatar + avatar
- Проект -

{task.project}

+ {/*Проект*/} +

{getCorrectDate(task.updated_at)}

@@ -304,6 +315,8 @@ export const Tracker = () => {

В архиве задач нет

)} + + }
diff --git a/src/pages/Tracker/tracker.scss b/src/pages/Tracker/tracker.scss index 34a51fd0..f7452790 100644 --- a/src/pages/Tracker/tracker.scss +++ b/src/pages/Tracker/tracker.scss @@ -289,7 +289,7 @@ color: #252c32; border: 1px solid #dde2e4; background: white; - left: -25px; + left: -18px; z-index: 2; } @@ -298,7 +298,7 @@ color: white; font-size: 14px; left: -30px; - z-index: 1; + z-index: 2; } p { @@ -453,6 +453,8 @@ &__more { cursor: pointer; + display: flex; + align-items: center; span { font-weight: 500; font-size: 12px; diff --git a/src/redux/projectsTrackerSlice.js b/src/redux/projectsTrackerSlice.js index 9efb3268..3e7333aa 100644 --- a/src/redux/projectsTrackerSlice.js +++ b/src/redux/projectsTrackerSlice.js @@ -7,6 +7,8 @@ const initialState = { toggleTab: 1, modalType: "", boardLoader: false, + columnName: "", + columnId: 0 }; export const setProjectBoardFetch = createAsyncThunk("userInfo", (id) => @@ -55,6 +57,12 @@ export const projectsTrackerSlice = createSlice({ } }); }, + setColumnName: (state, action) => { + state.columnName = action.payload + }, + setColumnId: (state, action) => { + state.columnId = action.payload + }, editProjectName: (state, action) => { state.projects.forEach((project) => { if (project.id === action.payload.id) { @@ -62,6 +70,13 @@ export const projectsTrackerSlice = createSlice({ } }); }, + editColumnName: (state, action) => { + state.projectBoard.columns.forEach((column) => { + if (column.id === action.payload.id) { + column.title = action.payload.title + } + }) + }, modalToggle: (state, action) => { state.modalType = action.payload; }, @@ -76,6 +91,7 @@ export const projectsTrackerSlice = createSlice({ export const { setProject, + setColumnName, deleteProject, setAllProjects, moveProjectTask, @@ -83,7 +99,8 @@ export const { modalToggle, activeLoader, editProjectName, - setColumnTitle, + editColumnName, + setColumnId } = projectsTrackerSlice.actions; export const getProjects = (state) => state.tracker.projects; @@ -91,5 +108,7 @@ export const getProjectBoard = (state) => state.tracker.projectBoard; export const getToggleTab = (state) => state.tracker.toggleTab; 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 default projectsTrackerSlice.reducer;