modal accept with notifications
This commit is contained in:
24
src/components/Modal/AcceptModal/AcceptModal.jsx
Normal file
24
src/components/Modal/AcceptModal/AcceptModal.jsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
|
||||
import close from "assets/icons/closeProjectPersons.svg";
|
||||
|
||||
import './acceptModal.scss'
|
||||
|
||||
export const AcceptModal = ({closeModal, agreeHandler}) => {
|
||||
return (
|
||||
<div className='backDrop'>
|
||||
<div className='acceptModal'>
|
||||
<h3 className='acceptModal__title'>
|
||||
Вы точно хотите переместить задачу в архив?
|
||||
</h3>
|
||||
<div className='acceptModal__buttons'>
|
||||
<button className='agree' onClick={agreeHandler}>Да</button>
|
||||
<button className='cancel' onClick={closeModal}>Нет</button>
|
||||
</div>
|
||||
<img className='acceptModal__close' src={close} alt='close' onClick={closeModal} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AcceptModal
|
61
src/components/Modal/AcceptModal/acceptModal.scss
Normal file
61
src/components/Modal/AcceptModal/acceptModal.scss
Normal file
@ -0,0 +1,61 @@
|
||||
.backDrop {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.11);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
z-index: 11;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.acceptModal {
|
||||
border-radius: 20px;
|
||||
background: linear-gradient(180deg, #FFF 0%, #EBEBEB 100%);
|
||||
padding: 50px 34px 25px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
row-gap: 25px;
|
||||
|
||||
&__title {
|
||||
max-width: 260px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
display: flex;
|
||||
column-gap: 20px;
|
||||
|
||||
button {
|
||||
min-width: 90px;
|
||||
height: 37px;
|
||||
border-radius: 44px;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.agree {
|
||||
background: #52B709;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
background: #B0BABF;
|
||||
}
|
||||
}
|
||||
|
||||
&__close {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 22px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import { Link } from "react-router-dom";
|
||||
|
||||
import { getProfileInfo } from "@redux/outstaffingSlice";
|
||||
import { setProjectBoardFetch } from "@redux/projectsTrackerSlice";
|
||||
import { useNotification } from "@hooks/useNotification";
|
||||
|
||||
import {
|
||||
backendImg,
|
||||
@ -22,6 +23,7 @@ import { apiRequest } from "@api/request";
|
||||
|
||||
import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal";
|
||||
import TrackerTaskComment from "@components/TrackerTaskComment/TrackerTaskComment";
|
||||
import AcceptModal from "@components/Modal/AcceptModal/AcceptModal";
|
||||
|
||||
import archive from "assets/icons/archive.svg";
|
||||
import arrow from "assets/icons/arrows/arrowStart.png";
|
||||
@ -82,6 +84,8 @@ export const ModalTiсket = ({
|
||||
const [correctProjectUsers, setCorrectProjectUsers] = useState(projectUsers);
|
||||
const [executorId, setExecutorId] = useState(task.executor_id);
|
||||
const profileInfo = useSelector(getProfileInfo);
|
||||
const [acceptModalOpen, setAcceptModalOpen] = useState(false)
|
||||
const { showNotification } = useNotification()
|
||||
|
||||
function deleteTask() {
|
||||
apiRequest("/task/update-task", {
|
||||
@ -93,9 +97,14 @@ export const ModalTiсket = ({
|
||||
}).then(() => {
|
||||
setActive(false);
|
||||
dispatch(setProjectBoardFetch(projectId));
|
||||
showNotification({show: true, text: 'Задача успешно была перемещена в архив', type: 'archive'})
|
||||
});
|
||||
}
|
||||
|
||||
function archiveTask () {
|
||||
setAcceptModalOpen(true)
|
||||
}
|
||||
|
||||
function editTask() {
|
||||
apiRequest("/task/update-task", {
|
||||
method: "PUT",
|
||||
@ -416,6 +425,7 @@ export const ModalTiсket = ({
|
||||
navigator.clipboard.writeText(
|
||||
`https://itguild.info/tracker/task/${task.id}`
|
||||
);
|
||||
showNotification({show: true, text: 'Ссылка скопирована в буфер обмена', type: 'copy'})
|
||||
}
|
||||
|
||||
function selectDeadLine(date) {
|
||||
@ -430,6 +440,10 @@ export const ModalTiсket = ({
|
||||
});
|
||||
}
|
||||
|
||||
function closeAcceptModal () {
|
||||
setAcceptModalOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={active ? "modal-tiket active" : "modal-tiket"}
|
||||
@ -809,7 +823,7 @@ export const ModalTiсket = ({
|
||||
<img src={link}></img>
|
||||
<p onClick={copyTicketLink}>ссылка на задачу</p>
|
||||
</div>
|
||||
<div onClick={deleteTask}>
|
||||
<div onClick={archiveTask}>
|
||||
<img src={archive}></img>
|
||||
<p>в архив</p>
|
||||
</div>
|
||||
@ -819,8 +833,13 @@ export const ModalTiсket = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{acceptModalOpen &&
|
||||
<AcceptModal
|
||||
closeModal={closeAcceptModal}
|
||||
agreeHandler={deleteTask}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
|
||||
<TrackerModal
|
||||
active={addSubtask}
|
||||
setActive={setAddSubtask}
|
||||
|
@ -689,6 +689,7 @@
|
||||
.react-datepicker-popper {
|
||||
top: 10px !important;
|
||||
left: -110px !important;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.react-datepicker__current-month {
|
||||
|
@ -31,6 +31,7 @@ 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 AcceptModal from "@components/Modal/AcceptModal/AcceptModal";
|
||||
|
||||
import arrow from "assets/icons/arrows/arrowCalendar.png";
|
||||
import arrowStart from "assets/icons/arrows/arrowStart.png";
|
||||
@ -82,6 +83,7 @@ export const TicketFullScreen = () => {
|
||||
const [startDate, setStartDate] = useState(null);
|
||||
const [uploadedFile, setUploadedFile] = useState(null);
|
||||
const [taskFiles, setTaskFiles] = useState([]);
|
||||
const [acceptModalOpen, setAcceptModalOpen] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
apiRequest(`/task/get-task?task_id=${ticketId.id}`).then((taskInfo) => {
|
||||
@ -161,6 +163,10 @@ export const TicketFullScreen = () => {
|
||||
});
|
||||
}
|
||||
|
||||
function archiveTask () {
|
||||
setAcceptModalOpen(true)
|
||||
}
|
||||
|
||||
function editTask() {
|
||||
apiRequest("/task/update-task", {
|
||||
method: "PUT",
|
||||
@ -450,6 +456,10 @@ export const TicketFullScreen = () => {
|
||||
});
|
||||
}
|
||||
|
||||
function closeAcceptModal () {
|
||||
setAcceptModalOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="ticket-full-screen">
|
||||
<ProfileHeader />
|
||||
@ -976,7 +986,7 @@ export const TicketFullScreen = () => {
|
||||
<img src={link} alt="link"></img>
|
||||
<p onClick={copyTicketLink}>ссылка на задачу</p>
|
||||
</div>
|
||||
<div>
|
||||
<div onClick={archiveTask}>
|
||||
<img src={archive} alt="arch"></img>
|
||||
<p>в архив</p>
|
||||
</div>
|
||||
@ -990,6 +1000,12 @@ export const TicketFullScreen = () => {
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{acceptModalOpen &&
|
||||
<AcceptModal
|
||||
closeModal={closeAcceptModal}
|
||||
agreeHandler={deleteTask}
|
||||
/>
|
||||
}
|
||||
<Footer />
|
||||
</section>
|
||||
);
|
||||
|
@ -30,6 +30,7 @@ import arrowDown from "assets/icons/arrows/selectArrow.png";
|
||||
import avatarMok from "assets/images/avatarMok.png";
|
||||
|
||||
import "./trackerModal.scss";
|
||||
import {useNotification} from "@hooks/useNotification";
|
||||
|
||||
export const TrackerModal = ({
|
||||
active,
|
||||
@ -67,9 +68,11 @@ export const TrackerModal = ({
|
||||
const [correctProjectUsers, setCorrectProjectUsers] = useState([]);
|
||||
const [selectColumnPriorityOpen, setSelectColumnPriorityOpen] =
|
||||
useState(false);
|
||||
const { showNotification } = useNotification()
|
||||
|
||||
function createTab() {
|
||||
if (!valueColumn) {
|
||||
showNotification({show: true, text: 'Введите название', type: 'error'})
|
||||
return;
|
||||
}
|
||||
|
||||
@ -91,6 +94,7 @@ export const TrackerModal = ({
|
||||
|
||||
function createTiket() {
|
||||
if (!valueTiket || !descriptionTicket) {
|
||||
showNotification({show: true, text: 'Введите название и описание', type: 'error'})
|
||||
return;
|
||||
}
|
||||
|
||||
@ -106,25 +110,30 @@ export const TrackerModal = ({
|
||||
priority: priorityTask,
|
||||
},
|
||||
}).then((res) => {
|
||||
if (selectedExecutorTask.user_id) {
|
||||
apiRequest("/task/update-task", {
|
||||
method: "PUT",
|
||||
data: {
|
||||
task_id: res.id,
|
||||
executor_id: selectedExecutorTask.user_id,
|
||||
},
|
||||
}).then(() => {
|
||||
dispatch(setProjectBoardFetch(projectBoard.id));
|
||||
if (res.status === 500) {
|
||||
showNotification({show: true, text: 'Задача с таким именем уже существует', type: 'error'})
|
||||
} else {
|
||||
if (selectedExecutorTask.user_id) {
|
||||
apiRequest("/task/update-task", {
|
||||
method: "PUT",
|
||||
data: {
|
||||
task_id: res.id,
|
||||
executor_id: selectedExecutorTask.user_id,
|
||||
},
|
||||
}).then(() => {
|
||||
dispatch(setProjectBoardFetch(projectBoard.id));
|
||||
setActive(false);
|
||||
setValueTiket("");
|
||||
setDescriptionTicket("Описание задачи");
|
||||
setSelectedExecutorTask("Выберите исполнителя задачи");
|
||||
});
|
||||
} else {
|
||||
setActive(false);
|
||||
setValueTiket("");
|
||||
setDescriptionTicket("Описание задачи");
|
||||
setSelectedExecutorTask("Выберите исполнителя задачи");
|
||||
});
|
||||
} else {
|
||||
setActive(false);
|
||||
setValueTiket("");
|
||||
setDescriptionTicket("Описание задачи");
|
||||
dispatch(setProjectBoardFetch(projectBoard.id));
|
||||
dispatch(setProjectBoardFetch(projectBoard.id));
|
||||
}
|
||||
showNotification({show: true, text: 'Задача создана', type: 'success'})
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -204,10 +213,14 @@ export const TrackerModal = ({
|
||||
status: 19,
|
||||
},
|
||||
}).then((res) => {
|
||||
const result = { ...res, columns: [] };
|
||||
dispatch(setProject(result));
|
||||
setActive(false);
|
||||
setNameProject("");
|
||||
if (!Array.isArray(res.name)) {
|
||||
const result = { ...res, columns: [] };
|
||||
dispatch(setProject(result));
|
||||
setActive(false);
|
||||
setNameProject("");
|
||||
} else {
|
||||
showNotification({show: true, text: 'Проект с таким именем уже существует', type: 'error'})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
36
src/components/Notification/Notification.jsx
Normal file
36
src/components/Notification/Notification.jsx
Normal file
@ -0,0 +1,36 @@
|
||||
import React from "react";
|
||||
import {useDispatch, useSelector} from "react-redux";
|
||||
|
||||
import { closeNotification, getNotification } from "@redux/outstaffingSlice";
|
||||
|
||||
import close from "assets/icons/closeProjectPersons.svg";
|
||||
import copy from "assets/icons/copyNotification.svg";
|
||||
import error from "assets/icons/errorNotification.svg";
|
||||
import archive from "assets/icons/archiveNotification.svg";
|
||||
import success from "assets/icons/successNotification.svg"
|
||||
|
||||
const images = {
|
||||
archive: archive,
|
||||
error: error,
|
||||
copy: copy,
|
||||
success: success
|
||||
}
|
||||
|
||||
import './notification.scss'
|
||||
|
||||
export const Notification = () => {
|
||||
const dispatch = useDispatch();
|
||||
const notificationInfo = useSelector(getNotification)
|
||||
return (
|
||||
<div className='notification'>
|
||||
<div className='notification__info'>
|
||||
<img src={images[notificationInfo.type]} alt='img' />
|
||||
<h2>{notificationInfo.text}</h2>
|
||||
</div>
|
||||
<img onClick={() => dispatch(closeNotification())}
|
||||
className='notification__close' src={close} alt='close' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Notification
|
35
src/components/Notification/notification.scss
Normal file
35
src/components/Notification/notification.scss
Normal file
@ -0,0 +1,35 @@
|
||||
.notification {
|
||||
border-radius: 40px;
|
||||
background: linear-gradient(180deg, #FFF 0%, #EBEBEB 100%);
|
||||
padding: 20px 82px 17px 27px;
|
||||
position: fixed;
|
||||
bottom: 25px;
|
||||
right: 25px;
|
||||
z-index: 20;
|
||||
|
||||
&__info {
|
||||
display: flex;
|
||||
column-gap: 10px;
|
||||
align-items: center;
|
||||
|
||||
h2 {
|
||||
max-width: 194px;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&__close {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 25px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
}
|
@ -3,11 +3,13 @@ import { useDispatch } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
import { deleteProject, modalToggle } from "@redux/projectsTrackerSlice";
|
||||
import {useNotification} from "@hooks/useNotification";
|
||||
|
||||
import { apiRequest } from "@api/request";
|
||||
|
||||
import { ModalSelect } from "@components/Modal/ModalSelect/ModalSelect";
|
||||
import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal";
|
||||
import AcceptModal from "@components/Modal/AcceptModal/AcceptModal"
|
||||
|
||||
import archiveSet from "assets/icons/archive.svg";
|
||||
import del from "assets/icons/delete.svg";
|
||||
@ -19,7 +21,9 @@ import "./projectTiket.scss";
|
||||
export const ProjectTiket = ({ project, index }) => {
|
||||
const [modalSelect, setModalSelect] = useState(false);
|
||||
const [modalAdd, setModalAdd] = useState(false);
|
||||
const [acceptModalOpen, setAcceptModalOpen] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
const { showNotification } = useNotification()
|
||||
|
||||
useEffect(() => {
|
||||
initListeners();
|
||||
@ -49,6 +53,7 @@ export const ProjectTiket = ({ project, index }) => {
|
||||
},
|
||||
}).then(() => {
|
||||
dispatch(deleteProject(project));
|
||||
showNotification({show: true, text: 'Проект успешно была перемещена в архив', type: 'archive'});
|
||||
});
|
||||
}
|
||||
|
||||
@ -58,6 +63,10 @@ export const ProjectTiket = ({ project, index }) => {
|
||||
);
|
||||
}
|
||||
|
||||
function closeAcceptModal () {
|
||||
setAcceptModalOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="project" key={index}>
|
||||
<Link to={`/tracker/project/${project.id}`}>{project.name}</Link>
|
||||
@ -98,7 +107,10 @@ export const ProjectTiket = ({ project, index }) => {
|
||||
<img src={link}></img>
|
||||
<p onClick={copyProjectLink}>ссылка на проект</p>
|
||||
</div>
|
||||
<div>
|
||||
<div onClick={() => {
|
||||
setModalSelect(false)
|
||||
setAcceptModalOpen(true)
|
||||
}}>
|
||||
<img src={archiveSet}></img>
|
||||
<p>в архив</p>
|
||||
</div>
|
||||
@ -108,6 +120,12 @@ export const ProjectTiket = ({ project, index }) => {
|
||||
</div>
|
||||
</div>
|
||||
</ModalSelect>
|
||||
{acceptModalOpen &&
|
||||
<AcceptModal
|
||||
closeModal={closeAcceptModal}
|
||||
agreeHandler={removeProject}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
Reference in New Issue
Block a user