tracker-tasks

This commit is contained in:
Николай Полтщук 2023-06-29 03:41:18 +03:00
parent 3131fbe1ef
commit 6f534bb82b
3 changed files with 264 additions and 65 deletions

View File

@ -27,6 +27,7 @@ import send from "assets/icons/send.svg";
import watch from "assets/icons/watch.svg"; import watch from "assets/icons/watch.svg";
import "./modalTicket.scss"; import "./modalTicket.scss";
import avatarMok from "assets/images/avatarMok.png";
export const ModalTiсket = ({ export const ModalTiсket = ({
active, active,
@ -469,7 +470,13 @@ export const ModalTiсket = ({
{executor ? ( {executor ? (
<div className="executor"> <div className="executor">
<p>Исполнитель: {executor.fio}</p> <p>Исполнитель: {executor.fio}</p>
<img src={urlForLocal(executor.avatar)} alt="avatar" /> <img
src={
executor?.avatar
? urlForLocal(executor.avatar)
: avatarMok
}
alt="avatar" />
<img <img
src={close} src={close}
className="delete" className="delete"
@ -500,7 +507,14 @@ export const ModalTiсket = ({
onClick={() => taskExecutor(person)} onClick={() => taskExecutor(person)}
> >
<span>{person.user.fio}</span> <span>{person.user.fio}</span>
<img src={urlForLocal(person.user.avatar)} /> <img
src={
person.user?.avatar
? urlForLocal(person.user.avatar)
: avatarMok
}
alt='avatar'
/>
</div> </div>
); );
})} })}
@ -517,7 +531,14 @@ export const ModalTiсket = ({
return ( return (
<div className="worker" key={member.user_id}> <div className="worker" key={member.user_id}>
<p>{member.fio}</p> <p>{member.fio}</p>
<img src={urlForLocal(member.avatar)} /> <img
src={
member?.avatar
? urlForLocal(member.avatar)
: avatarMok
}
alt='avatar'
/>
<img <img
src={close} src={close}
className="delete" className="delete"
@ -554,7 +575,14 @@ export const ModalTiсket = ({
onClick={() => addMember(person)} onClick={() => addMember(person)}
> >
<span>{person.user.fio}</span> <span>{person.user.fio}</span>
<img src={urlForLocal(person.user.avatar)} /> <img
src={
person.user?.avatar
? urlForLocal(person.user.avatar)
: avatarMok
}
alt='avatar'
/>
</div> </div>
); );
}) })

View File

@ -7,10 +7,8 @@ import { Link, useNavigate, useParams } from "react-router-dom";
import { import {
deletePersonOnProject, deletePersonOnProject,
getBoarderLoader, getBoarderLoader,
getProjectBoard, modalToggle, setProjectBoardFetch,
modalToggle, setToggleTab
setProjectBoardFetch,
setToggleTab,
} from "@redux/projectsTrackerSlice"; } from "@redux/projectsTrackerSlice";
import { getCorrectRequestDate, urlForLocal } from "@utils/helper"; import { getCorrectRequestDate, urlForLocal } from "@utils/helper";
@ -35,7 +33,6 @@ import del from "assets/icons/delete.svg";
import edit from "assets/icons/edit.svg"; import edit from "assets/icons/edit.svg";
import file from "assets/icons/fileModal.svg"; import file from "assets/icons/fileModal.svg";
import link from "assets/icons/link.svg"; import link from "assets/icons/link.svg";
import plus from "assets/icons/plus.svg";
import send from "assets/icons/send.svg"; import send from "assets/icons/send.svg";
import project from "assets/icons/trackerProject.svg"; import project from "assets/icons/trackerProject.svg";
import tasks from "assets/icons/trackerTasks.svg"; import tasks from "assets/icons/trackerTasks.svg";
@ -49,8 +46,8 @@ export const TicketFullScreen = () => {
const ticketId = useParams(); const ticketId = useParams();
const dispatch = useDispatch(); const dispatch = useDispatch();
const navigate = useNavigate(); const navigate = useNavigate();
const projectBoard = useSelector(getProjectBoard);
const boardLoader = useSelector(getBoarderLoader); const boardLoader = useSelector(getBoarderLoader);
const [projectInfo, setProjectInfo] = useState({})
const [taskInfo, setTaskInfo] = useState({}); const [taskInfo, setTaskInfo] = useState({});
const [editOpen, setEditOpen] = useState(false); const [editOpen, setEditOpen] = useState(false);
const [inputsValue, setInputsValue] = useState({}); const [inputsValue, setInputsValue] = useState({});
@ -65,6 +62,10 @@ export const TicketFullScreen = () => {
seconds: 0, seconds: 0,
}); });
const [timerId, setTimerId] = useState(null); const [timerId, setTimerId] = useState(null);
const [dropListOpen, setDropListOpen] = useState(false);
const [correctProjectUsers, setCorrectProjectUsers] = useState([]);
const [dropListMembersOpen, setDropListMembersOpen] = useState(false);
const [users, setUsers] = useState([]);
useEffect(() => { useEffect(() => {
apiRequest(`/task/get-task?task_id=${ticketId.id}`).then((taskInfo) => { apiRequest(`/task/get-task?task_id=${ticketId.id}`).then((taskInfo) => {
@ -111,7 +112,10 @@ export const TicketFullScreen = () => {
} }
}); });
}); });
dispatch(setProjectBoardFetch(taskInfo.project_id)); apiRequest(`/project/get-project?project_id=${taskInfo.project_id}&expand=columns`).then((res) => {
setProjectInfo(res)
setCorrectProjectUsers(res.projectUsers)
})
setLoader(boardLoader); setLoader(boardLoader);
}); });
}, []); }, []);
@ -188,7 +192,7 @@ export const TicketFullScreen = () => {
apiRequest("/project/del-user", { apiRequest("/project/del-user", {
method: "DELETE", method: "DELETE",
data: { data: {
project_id: projectBoard.id, project_id: projectInfo.id,
user_id: userId, user_id: userId,
}, },
}).then(() => { }).then(() => {
@ -253,6 +257,18 @@ export const TicketFullScreen = () => {
); );
} }
useEffect(() => {
if (taskInfo.taskUsers && projectInfo.projectUsers) {
let ids = taskInfo.taskUsers.map((user) => user.user_id);
setUsers(
projectInfo.projectUsers.reduce((acc, cur) => {
if (!ids.includes(cur.user_id)) acc.push(cur);
return acc;
}, [])
);
}
}, [taskInfo.taskUsers, projectInfo]);
let updateTimerSec = currentTimerCount.seconds, let updateTimerSec = currentTimerCount.seconds,
updateTimerMinute = currentTimerCount.minute, updateTimerMinute = currentTimerCount.minute,
updateTimerHours = currentTimerCount.hours; updateTimerHours = currentTimerCount.hours;
@ -280,6 +296,70 @@ export const TicketFullScreen = () => {
if (time > 10) return time; if (time > 10) return time;
} }
function deleteTaskExecutor() {
apiRequest("/task/update-task", {
method: "PUT",
data: {
task_id: taskInfo.id,
executor_id: 0,
},
}).then(() => {
setTaskInfo((prevState) => ({
...prevState,
executor_id: null,
executor: null
}))
});
}
function taskExecutor(person) {
apiRequest("/task/update-task", {
method: "PUT",
data: {
task_id: taskInfo.id,
executor_id: person.user_id,
},
}).then((res) => {
setDropListOpen(false);
setTaskInfo((prevState) => ({
...prevState,
executor_id: res.executor_id,
executor: res.executor
}))
});
}
function deleteMember(person) {
apiRequest("/task/del-user", {
method: "DELETE",
data: {
task_id: taskInfo.id,
user_id: person.user_id,
},
}).then(() => {
setTaskInfo((prevState) => ({
...prevState,
taskUsers: taskInfo.taskUsers.filter((item) => item.user_id !== person.user_id)
}))
});
}
function addMember(person) {
apiRequest("/task/add-user-to-task", {
method: "POST",
data: {
task_id: taskInfo.id,
user_id: person.user_id,
},
}).then((res) => {
setDropListMembersOpen(false);
setTaskInfo((prevValue) => ({
...prevValue,
taskUsers: [...prevValue.taskUsers, res]
}));
});
}
return ( return (
<section className="ticket-full-screen"> <section className="ticket-full-screen">
<ProfileHeader /> <ProfileHeader />
@ -329,7 +409,7 @@ export const TicketFullScreen = () => {
<div className="tracker__tabs__content content-tabs"> <div className="tracker__tabs__content content-tabs">
<div className="tasks__head"> <div className="tasks__head">
<div className="tasks__head__wrapper"> <div className="tasks__head__wrapper">
<h5>Проект : {projectBoard.name}</h5> <h5>Проект : {projectInfo.name}</h5>
<TrackerModal <TrackerModal
active={modalAddWorker} active={modalAddWorker}
@ -337,15 +417,15 @@ export const TicketFullScreen = () => {
></TrackerModal> ></TrackerModal>
<div className="tasks__head__persons"> <div className="tasks__head__persons">
{projectBoard.projectUsers?.length > 3 && ( {projectInfo.projectUsers?.length > 3 && (
<span className="countPersons">+1...</span> <span className="countPersons">+1...</span>
)} )}
<div className="projectPersons"> <div className="projectPersons">
{projectBoard.projectUsers?.length && {projectInfo.projectUsers?.length &&
projectBoard.projectUsers projectInfo.projectUsers
.slice( .slice(
0, 0,
projectBoard.length > 3 ? 3 : projectBoard.length 3
) )
.map((person) => { .map((person) => {
return ( return (
@ -379,14 +459,14 @@ export const TicketFullScreen = () => {
onClick={() => setPersonListOpen(false)} onClick={() => setPersonListOpen(false)}
/> />
<div className="persons__list__count"> <div className="persons__list__count">
<span>{projectBoard.projectUsers?.length}</span> <span>{projectInfo.projectUsers?.length}</span>
участник участник
</div> </div>
<div className="persons__list__info"> <div className="persons__list__info">
В проекте - <span>{projectBoard.name}</span> В проекте - <span>{projectInfo.name}</span>
</div> </div>
<div className="persons__list__items"> <div className="persons__list__items">
{projectBoard.projectUsers?.map((person) => { {projectInfo.projectUsers?.map((person) => {
return ( return (
<div <div
className="persons__list__item" className="persons__list__item"
@ -394,7 +474,11 @@ export const TicketFullScreen = () => {
> >
<img <img
className="avatar" className="avatar"
src={urlForLocal(person.user.avatar)} src={
person.user?.avatar
? urlForLocal(person.user.avatar)
: avatarMok
}
alt="avatar" alt="avatar"
/> />
<span>{person.user.fio}</span> <span>{person.user.fio}</span>
@ -484,18 +568,18 @@ export const TicketFullScreen = () => {
)} )}
</div> </div>
<div className="content__communication"> <div className="content__communication">
<p className="tasks"> {/*<p className="tasks">*/}
<BaseButton {/* <BaseButton*/}
onClick={() => { {/* onClick={() => {*/}
dispatch(modalToggle("addSubtask")); {/* dispatch(modalToggle("addSubtask"));*/}
setModalAddWorker(true); {/* setModalAddWorker(true);*/}
}} {/* }}*/}
styles={"button-green-add"} {/* styles={"button-green-add"}*/}
> {/* >*/}
<img src={plus}></img> {/* <img src={plus}></img>*/}
Добавить под задачу {/* Добавить под задачу*/}
</BaseButton> {/* </BaseButton>*/}
</p> {/*</p>*/}
<p className="file"> <p className="file">
<BaseButton styles={"button-add-file"}> <BaseButton styles={"button-add-file"}>
<img src={file}></img> <img src={file}></img>
@ -540,42 +624,129 @@ export const TicketFullScreen = () => {
Создатель : <br /> Создатель : <br />
{taskInfo.user?.fio} {taskInfo.user?.fio}
</p> </p>
<div>
{Boolean(taskInfo.taskUsers?.length) && {taskInfo.executor ? (
taskInfo.taskUsers.map((worker, index) => { <div className="executor">
<p>Исполнитель: {taskInfo.executor.fio}</p>
<img
src={
taskInfo.executor?.avatar
? urlForLocal(taskInfo.executor.avatar)
: avatarMok
}
alt="avatar" />
<img
src={close}
className="delete"
onClick={() => deleteTaskExecutor()}
/>
</div>
) : (
<div className="add-worker moreItems ">
<button
className="button-add-worker"
onClick={() => setDropListOpen(true)}
>
+
</button>
<span>Добавить исполнителя</span>
{dropListOpen && (
<div className="dropdownList">
<img
src={close}
className="dropdownList__close"
onClick={() => setDropListOpen(false)}
/>
{correctProjectUsers.map((person) => {
return ( return (
<div className="worker" key={index}> <div
<img src={worker.avatar} alt="worket"></img> className="dropdownList__person"
<p>{worker.name}</p> key={person.user_id}
onClick={() => taskExecutor(person)}
>
<span>{person.user.fio}</span>
<img
src={
person.user?.avatar
? urlForLocal(person.user.avatar)
: avatarMok
}
alt='avatar'
/>
</div> </div>
); );
})} })}
</div> </div>
)}
<div className="add-worker moreItems">
<BaseButton
onClick={() => {
dispatch(modalToggle("addWorker"));
setModalAddWorker(true);
}}
styles={"button-add-worker"}
>
+
</BaseButton>
<span>Добавить исполнителя</span>
</div> </div>
)}
{Boolean(taskInfo.taskUsers.length) && (
<div className="members">
<p>Участники:</p>
<div className="members__list">
{taskInfo.taskUsers.map((member) => {
return (
<div className="worker" key={member.user_id}>
<p>{member.fio}</p>
<img
src={
member?.avatar
? urlForLocal(member.avatar)
: avatarMok
}
alt='avatar'
/>
<img
src={close}
className="delete"
onClick={() => deleteMember(member)}
/>
</div>
);
})}
</div>
</div>
)}
<div className="add-worker moreItems"> <div className="add-worker moreItems">
<BaseButton <button
onClick={() => { className="button-add-worker"
dispatch(modalToggle("addWorker")); onClick={() => setDropListMembersOpen(true)}
setModalAddWorker(true);
}}
styles={"button-add-worker"}
> >
+ +
</BaseButton> </button>
<span>Добавить участников</span> <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={
person.user?.avatar
? urlForLocal(person.user.avatar)
: avatarMok
}
alt='avatar'
/>
</div>
);
})
) : (
<p className="noUsers">Нет пользователей</p>
)}
</div>
)}
</div> </div>
</div> </div>

View File

@ -330,7 +330,7 @@ export const ProjectTracker = () => {
projectBoard.projectUsers projectBoard.projectUsers
.slice( .slice(
0, 0,
projectBoard.length > 3 ? 3 : projectBoard.length 3
) )
.map((person) => { .map((person) => {
return ( return (