modal accept with notifications

This commit is contained in:
Николай Полтщук 2023-07-14 03:03:49 +03:00
parent 001920a840
commit 7c7ea86c8c
9 changed files with 155 additions and 112 deletions

View File

@ -2,23 +2,32 @@ import React from "react";
import close from "assets/icons/closeProjectPersons.svg"; import close from "assets/icons/closeProjectPersons.svg";
import './acceptModal.scss' import "./acceptModal.scss";
export const AcceptModal = ({closeModal, agreeHandler}) => { export const AcceptModal = ({ closeModal, agreeHandler }) => {
return ( return (
<div className='backDrop'> <div className="backDrop">
<div className='acceptModal'> <div className="acceptModal">
<h3 className='acceptModal__title'> <h3 className="acceptModal__title">
Вы точно хотите переместить задачу в архив? Вы точно хотите переместить задачу в архив?
</h3> </h3>
<div className='acceptModal__buttons'> <div className="acceptModal__buttons">
<button className='agree' onClick={agreeHandler}>Да</button> <button className="agree" onClick={agreeHandler}>
<button className='cancel' onClick={closeModal}>Нет</button> Да
</div> </button>
<img className='acceptModal__close' src={close} alt='close' onClick={closeModal} /> <button className="cancel" onClick={closeModal}>
</div> Нет
</button>
</div> </div>
) <img
} className="acceptModal__close"
src={close}
alt="close"
onClick={closeModal}
/>
</div>
</div>
);
};
export default AcceptModal export default AcceptModal;

View File

@ -9,7 +9,6 @@ import { Link } from "react-router-dom";
import { getProfileInfo } from "@redux/outstaffingSlice"; import { getProfileInfo } from "@redux/outstaffingSlice";
import { setProjectBoardFetch } from "@redux/projectsTrackerSlice"; import { setProjectBoardFetch } from "@redux/projectsTrackerSlice";
import { useNotification } from "@hooks/useNotification";
import { import {
backendImg, backendImg,
@ -21,9 +20,11 @@ import {
import { apiRequest } from "@api/request"; import { apiRequest } from "@api/request";
import { useNotification } from "@hooks/useNotification";
import AcceptModal from "@components/Modal/AcceptModal/AcceptModal";
import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal"; import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal";
import TrackerTaskComment from "@components/TrackerTaskComment/TrackerTaskComment"; import TrackerTaskComment from "@components/TrackerTaskComment/TrackerTaskComment";
import AcceptModal from "@components/Modal/AcceptModal/AcceptModal";
import archive from "assets/icons/archive.svg"; import archive from "assets/icons/archive.svg";
import arrow from "assets/icons/arrows/arrowStart.png"; import arrow from "assets/icons/arrows/arrowStart.png";
@ -84,8 +85,8 @@ export const ModalTiсket = ({
const [correctProjectUsers, setCorrectProjectUsers] = useState(projectUsers); const [correctProjectUsers, setCorrectProjectUsers] = useState(projectUsers);
const [executorId, setExecutorId] = useState(task.executor_id); const [executorId, setExecutorId] = useState(task.executor_id);
const profileInfo = useSelector(getProfileInfo); const profileInfo = useSelector(getProfileInfo);
const [acceptModalOpen, setAcceptModalOpen] = useState(false) const [acceptModalOpen, setAcceptModalOpen] = useState(false);
const { showNotification } = useNotification() const { showNotification } = useNotification();
function deleteTask() { function deleteTask() {
apiRequest("/task/update-task", { apiRequest("/task/update-task", {
@ -97,12 +98,16 @@ export const ModalTiсket = ({
}).then(() => { }).then(() => {
setActive(false); setActive(false);
dispatch(setProjectBoardFetch(projectId)); dispatch(setProjectBoardFetch(projectId));
showNotification({show: true, text: 'Задача успешно была перемещена в архив', type: 'archive'}) showNotification({
show: true,
text: "Задача успешно была перемещена в архив",
type: "archive",
});
}); });
} }
function archiveTask () { function archiveTask() {
setAcceptModalOpen(true) setAcceptModalOpen(true);
} }
function editTask() { function editTask() {
@ -425,7 +430,11 @@ export const ModalTiсket = ({
navigator.clipboard.writeText( navigator.clipboard.writeText(
`https://itguild.info/tracker/task/${task.id}` `https://itguild.info/tracker/task/${task.id}`
); );
showNotification({show: true, text: 'Ссылка скопирована в буфер обмена', type: 'copy'}) showNotification({
show: true,
text: "Ссылка скопирована в буфер обмена",
type: "copy",
});
} }
function selectDeadLine(date) { function selectDeadLine(date) {
@ -440,8 +449,8 @@ export const ModalTiсket = ({
}); });
} }
function closeAcceptModal () { function closeAcceptModal() {
setAcceptModalOpen(false) setAcceptModalOpen(false);
} }
return ( return (
@ -833,12 +842,12 @@ export const ModalTiсket = ({
</div> </div>
</div> </div>
</div> </div>
{acceptModalOpen && {acceptModalOpen && (
<AcceptModal <AcceptModal
closeModal={closeAcceptModal} closeModal={closeAcceptModal}
agreeHandler={deleteTask} agreeHandler={deleteTask}
/> />
} )}
</div> </div>
<TrackerModal <TrackerModal
active={addSubtask} active={addSubtask}

View File

@ -26,12 +26,12 @@ import { apiRequest } from "@api/request";
import { getCorrectDate } from "@components/Calendar/calendarHelper"; import { getCorrectDate } from "@components/Calendar/calendarHelper";
import { Footer } from "@components/Common/Footer/Footer"; import { Footer } from "@components/Common/Footer/Footer";
import { Loader } from "@components/Common/Loader/Loader"; import { Loader } from "@components/Common/Loader/Loader";
import AcceptModal from "@components/Modal/AcceptModal/AcceptModal";
import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal"; import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal";
import { Navigation } from "@components/Navigation/Navigation"; import { Navigation } from "@components/Navigation/Navigation";
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs"; import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader"; import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
import TrackerTaskComment from "@components/TrackerTaskComment/TrackerTaskComment"; import TrackerTaskComment from "@components/TrackerTaskComment/TrackerTaskComment";
import AcceptModal from "@components/Modal/AcceptModal/AcceptModal";
import arrow from "assets/icons/arrows/arrowCalendar.png"; import arrow from "assets/icons/arrows/arrowCalendar.png";
import arrowStart from "assets/icons/arrows/arrowStart.png"; import arrowStart from "assets/icons/arrows/arrowStart.png";
@ -83,7 +83,7 @@ export const TicketFullScreen = () => {
const [startDate, setStartDate] = useState(null); const [startDate, setStartDate] = useState(null);
const [uploadedFile, setUploadedFile] = useState(null); const [uploadedFile, setUploadedFile] = useState(null);
const [taskFiles, setTaskFiles] = useState([]); const [taskFiles, setTaskFiles] = useState([]);
const [acceptModalOpen, setAcceptModalOpen] = useState(false) const [acceptModalOpen, setAcceptModalOpen] = useState(false);
useEffect(() => { useEffect(() => {
apiRequest(`/task/get-task?task_id=${ticketId.id}`).then((taskInfo) => { apiRequest(`/task/get-task?task_id=${ticketId.id}`).then((taskInfo) => {
@ -163,8 +163,8 @@ export const TicketFullScreen = () => {
}); });
} }
function archiveTask () { function archiveTask() {
setAcceptModalOpen(true) setAcceptModalOpen(true);
} }
function editTask() { function editTask() {
@ -456,8 +456,8 @@ export const TicketFullScreen = () => {
}); });
} }
function closeAcceptModal () { function closeAcceptModal() {
setAcceptModalOpen(false) setAcceptModalOpen(false);
} }
return ( return (
@ -1000,12 +1000,9 @@ export const TicketFullScreen = () => {
</> </>
)} )}
</div> </div>
{acceptModalOpen && {acceptModalOpen && (
<AcceptModal <AcceptModal closeModal={closeAcceptModal} agreeHandler={deleteTask} />
closeModal={closeAcceptModal} )}
agreeHandler={deleteTask}
/>
}
<Footer /> <Footer />
</section> </section>
); );

View File

@ -23,6 +23,8 @@ import { urlForLocal } from "@utils/helper";
import { apiRequest } from "@api/request"; import { apiRequest } from "@api/request";
import { useNotification } from "@hooks/useNotification";
import BaseButton from "@components/Common/BaseButton/BaseButton"; import BaseButton from "@components/Common/BaseButton/BaseButton";
import ModalLayout from "@components/Common/ModalLayout/ModalLayout"; import ModalLayout from "@components/Common/ModalLayout/ModalLayout";
@ -30,7 +32,6 @@ import arrowDown from "assets/icons/arrows/selectArrow.png";
import avatarMok from "assets/images/avatarMok.png"; import avatarMok from "assets/images/avatarMok.png";
import "./trackerModal.scss"; import "./trackerModal.scss";
import {useNotification} from "@hooks/useNotification";
export const TrackerModal = ({ export const TrackerModal = ({
active, active,
@ -68,11 +69,11 @@ export const TrackerModal = ({
const [correctProjectUsers, setCorrectProjectUsers] = useState([]); const [correctProjectUsers, setCorrectProjectUsers] = useState([]);
const [selectColumnPriorityOpen, setSelectColumnPriorityOpen] = const [selectColumnPriorityOpen, setSelectColumnPriorityOpen] =
useState(false); useState(false);
const { showNotification } = useNotification() const { showNotification } = useNotification();
function createTab() { function createTab() {
if (!valueColumn) { if (!valueColumn) {
showNotification({show: true, text: 'Введите название', type: 'error'}) showNotification({ show: true, text: "Введите название", type: "error" });
return; return;
} }
@ -94,7 +95,11 @@ export const TrackerModal = ({
function createTiket() { function createTiket() {
if (!valueTiket || !descriptionTicket) { if (!valueTiket || !descriptionTicket) {
showNotification({show: true, text: 'Введите название и описание', type: 'error'}) showNotification({
show: true,
text: "Введите название и описание",
type: "error",
});
return; return;
} }
@ -111,7 +116,11 @@ export const TrackerModal = ({
}, },
}).then((res) => { }).then((res) => {
if (res.status === 500) { if (res.status === 500) {
showNotification({show: true, text: 'Задача с таким именем уже существует', type: 'error'}) showNotification({
show: true,
text: "Задача с таким именем уже существует",
type: "error",
});
} else { } else {
if (selectedExecutorTask.user_id) { if (selectedExecutorTask.user_id) {
apiRequest("/task/update-task", { apiRequest("/task/update-task", {
@ -133,7 +142,11 @@ export const TrackerModal = ({
setDescriptionTicket("Описание задачи"); setDescriptionTicket("Описание задачи");
dispatch(setProjectBoardFetch(projectBoard.id)); dispatch(setProjectBoardFetch(projectBoard.id));
} }
showNotification({show: true, text: 'Задача создана', type: 'success'}) showNotification({
show: true,
text: "Задача создана",
type: "success",
});
} }
}); });
} }
@ -219,7 +232,11 @@ export const TrackerModal = ({
setActive(false); setActive(false);
setNameProject(""); setNameProject("");
} else { } else {
showNotification({show: true, text: 'Проект с таким именем уже существует', type: 'error'}) showNotification({
show: true,
text: "Проект с таким именем уже существует",
type: "error",
});
} }
}); });
} }

View File

@ -1,36 +1,40 @@
import React from "react"; import React from "react";
import {useDispatch, useSelector} from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { closeNotification, getNotification } from "@redux/outstaffingSlice"; import { closeNotification, getNotification } from "@redux/outstaffingSlice";
import archive from "assets/icons/archiveNotification.svg";
import close from "assets/icons/closeProjectPersons.svg"; import close from "assets/icons/closeProjectPersons.svg";
import copy from "assets/icons/copyNotification.svg"; import copy from "assets/icons/copyNotification.svg";
import error from "assets/icons/errorNotification.svg"; import error from "assets/icons/errorNotification.svg";
import archive from "assets/icons/archiveNotification.svg"; import success from "assets/icons/successNotification.svg";
import success from "assets/icons/successNotification.svg"
import "./notification.scss";
const images = { const images = {
archive: archive, archive: archive,
error: error, error: error,
copy: copy, copy: copy,
success: success success: success,
} };
import './notification.scss'
export const Notification = () => { export const Notification = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const notificationInfo = useSelector(getNotification) const notificationInfo = useSelector(getNotification);
return ( return (
<div className='notification'> <div className="notification">
<div className='notification__info'> <div className="notification__info">
<img src={images[notificationInfo.type]} alt='img' /> <img src={images[notificationInfo.type]} alt="img" />
<h2>{notificationInfo.text}</h2> <h2>{notificationInfo.text}</h2>
</div> </div>
<img onClick={() => dispatch(closeNotification())} <img
className='notification__close' src={close} alt='close' /> onClick={() => dispatch(closeNotification())}
</div> className="notification__close"
) src={close}
} alt="close"
/>
</div>
);
};
export default Notification export default Notification;

View File

@ -3,13 +3,14 @@ import { useDispatch } from "react-redux";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { deleteProject, modalToggle } from "@redux/projectsTrackerSlice"; import { deleteProject, modalToggle } from "@redux/projectsTrackerSlice";
import {useNotification} from "@hooks/useNotification";
import { apiRequest } from "@api/request"; import { apiRequest } from "@api/request";
import { useNotification } from "@hooks/useNotification";
import AcceptModal from "@components/Modal/AcceptModal/AcceptModal";
import { ModalSelect } from "@components/Modal/ModalSelect/ModalSelect"; import { ModalSelect } from "@components/Modal/ModalSelect/ModalSelect";
import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal"; import TrackerModal from "@components/Modal/Tracker/TrackerModal/TrackerModal";
import AcceptModal from "@components/Modal/AcceptModal/AcceptModal"
import archiveSet from "assets/icons/archive.svg"; import archiveSet from "assets/icons/archive.svg";
import del from "assets/icons/delete.svg"; import del from "assets/icons/delete.svg";
@ -23,7 +24,7 @@ export const ProjectTiket = ({ project, index }) => {
const [modalAdd, setModalAdd] = useState(false); const [modalAdd, setModalAdd] = useState(false);
const [acceptModalOpen, setAcceptModalOpen] = useState(false); const [acceptModalOpen, setAcceptModalOpen] = useState(false);
const dispatch = useDispatch(); const dispatch = useDispatch();
const { showNotification } = useNotification() const { showNotification } = useNotification();
useEffect(() => { useEffect(() => {
initListeners(); initListeners();
@ -53,7 +54,11 @@ export const ProjectTiket = ({ project, index }) => {
}, },
}).then(() => { }).then(() => {
dispatch(deleteProject(project)); dispatch(deleteProject(project));
showNotification({show: true, text: 'Проект успешно была перемещена в архив', type: 'archive'}); showNotification({
show: true,
text: "Проект успешно была перемещена в архив",
type: "archive",
});
}); });
} }
@ -63,8 +68,8 @@ export const ProjectTiket = ({ project, index }) => {
); );
} }
function closeAcceptModal () { function closeAcceptModal() {
setAcceptModalOpen(false) setAcceptModalOpen(false);
} }
return ( return (
@ -107,10 +112,12 @@ export const ProjectTiket = ({ project, index }) => {
<img src={link}></img> <img src={link}></img>
<p onClick={copyProjectLink}>ссылка на проект</p> <p onClick={copyProjectLink}>ссылка на проект</p>
</div> </div>
<div onClick={() => { <div
setModalSelect(false) onClick={() => {
setAcceptModalOpen(true) setModalSelect(false);
}}> setAcceptModalOpen(true);
}}
>
<img src={archiveSet}></img> <img src={archiveSet}></img>
<p>в архив</p> <p>в архив</p>
</div> </div>
@ -120,12 +127,12 @@ export const ProjectTiket = ({ project, index }) => {
</div> </div>
</div> </div>
</ModalSelect> </ModalSelect>
{acceptModalOpen && {acceptModalOpen && (
<AcceptModal <AcceptModal
closeModal={closeAcceptModal} closeModal={closeAcceptModal}
agreeHandler={removeProject} agreeHandler={removeProject}
/> />
} )}
</div> </div>
); );
}; };

View File

@ -1,15 +1,15 @@
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { setNotification, closeNotification } from "../redux/outstaffingSlice"; import { closeNotification, setNotification } from "../redux/outstaffingSlice";
export const useNotification = () => { export const useNotification = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const showNotification = (notification) => { const showNotification = (notification) => {
dispatch(setNotification(notification)) dispatch(setNotification(notification));
setTimeout(() => { setTimeout(() => {
dispatch(closeNotification()) dispatch(closeNotification());
}, 2500) }, 2500);
} };
return { showNotification } return { showNotification };
}; };

View File

@ -25,6 +25,8 @@ import { caseOfNum } from "@utils/helper";
import { apiRequest } from "@api/request"; import { apiRequest } from "@api/request";
import { useNotification } from "@hooks/useNotification";
import BaseButton from "@components/Common/BaseButton/BaseButton"; import BaseButton from "@components/Common/BaseButton/BaseButton";
import { Footer } from "@components/Common/Footer/Footer"; import { Footer } from "@components/Common/Footer/Footer";
import { Loader } from "@components/Common/Loader/Loader"; import { Loader } from "@components/Common/Loader/Loader";
@ -49,7 +51,6 @@ import archive from "assets/images/archiveIcon.png";
import avatarMok from "assets/images/avatarMok.png"; import avatarMok from "assets/images/avatarMok.png";
import { getCorrectDate } from "../../components/Calendar/calendarHelper"; import { getCorrectDate } from "../../components/Calendar/calendarHelper";
import {useNotification} from "@hooks/useNotification";
export const ProjectTracker = () => { export const ProjectTracker = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -73,7 +74,7 @@ export const ProjectTracker = () => {
const startWrapperIndexTest = useRef({}); const startWrapperIndexTest = useRef({});
const projectBoard = useSelector(getProjectBoard); const projectBoard = useSelector(getProjectBoard);
const loader = useSelector(getBoarderLoader); const loader = useSelector(getBoarderLoader);
const { showNotification } = useNotification() const { showNotification } = useNotification();
useEffect(() => { useEffect(() => {
dispatch(activeLoader()); dispatch(activeLoader());
@ -226,7 +227,7 @@ export const ProjectTracker = () => {
} else { } else {
dispatch(setProjectBoardFetch(projectBoard.id)); dispatch(setProjectBoardFetch(projectBoard.id));
} }
showNotification({show: true, text: 'Колонка удалена', type: 'error'}) showNotification({ show: true, text: "Колонка удалена", type: "error" });
}); });
} }

View File

@ -1,4 +1,4 @@
import {createAsyncThunk, createSlice} from "@reduxjs/toolkit"; import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
const initialState = { const initialState = {
tags: [], tags: [],
@ -16,9 +16,9 @@ const initialState = {
partnerRequestInfo: {}, partnerRequestInfo: {},
notification: { notification: {
show: false, show: false,
text: '', text: "",
type: '' type: "",
} },
}; };
export const outstaffingSlice = createSlice({ export const outstaffingSlice = createSlice({
@ -68,11 +68,11 @@ export const outstaffingSlice = createSlice({
state.partnerRequestInfo = action.payload; state.partnerRequestInfo = action.payload;
}, },
setNotification: (state, action) => { setNotification: (state, action) => {
state.notification = action.payload state.notification = action.payload;
}, },
closeNotification: (state) => { closeNotification: (state) => {
state.notification.show = false state.notification.show = false;
} },
}, },
}); });
@ -92,15 +92,14 @@ export const {
setPartnerRequests, setPartnerRequests,
setPartnerRequestInfo, setPartnerRequestInfo,
setNotification, setNotification,
closeNotification closeNotification,
} = outstaffingSlice.actions; } = outstaffingSlice.actions;
export const selectProfiles = (state) => state.outstaffing.profiles; export const selectProfiles = (state) => state.outstaffing.profiles;
export const selectTags = (state) => state.outstaffing.tags; export const selectTags = (state) => state.outstaffing.tags;
export const selectFilteredCandidates = (state) => export const selectFilteredCandidates = (state) =>
state.outstaffing.filteredCandidates; state.outstaffing.filteredCandidates;
export const getNotification = (state) => export const getNotification = (state) => state.outstaffing.notification;
state.outstaffing.notification
export const selectItems = (state) => state.outstaffing.selectedItems; export const selectItems = (state) => state.outstaffing.selectedItems;
export const selectCurrentCandidate = (state) => export const selectCurrentCandidate = (state) =>
state.outstaffing.currentCandidate; state.outstaffing.currentCandidate;