refactor & debug burger-menu, add participant

add column and deploying a task
This commit is contained in:
Никита Губарь 2024-02-29 13:08:41 +03:00
parent 9b01381af1
commit 0df30c74c9
9 changed files with 131 additions and 41 deletions

View File

@ -5,19 +5,25 @@ import "./modalLayout.scss";
export const ModalLayout = ({ export const ModalLayout = ({
active, active,
setActive, setActive,
onClose,
children, children,
styles, styles,
type, type,
...props ...props
}) => { }) => {
const handleClose = (event) => {
if (event.target.className === "modal-layout active") {
setActive(false);
if (onClose) {
onClose(); // Вызов колбэк-функции при закрытии модального окна
}
}
};
return ( return (
<div <div
className={active ? `modal-layout active` : "modal-layout"} className={active ? `modal-layout active` : "modal-layout"}
onClick={(event) => { onClick={handleClose}
if (event.target.className === "modal-layout active") {
setActive(false);
}
}}
{...props} {...props}
> >
<div <div

View File

@ -61,7 +61,7 @@
align-items: center; align-items: center;
row-gap: 5px; row-gap: 5px;
&__input { &__input {
margin: 0; margin: 10px 0 10px 0;
min-width: 240px; min-width: 240px;
height: 42px; height: 42px;
@ -79,6 +79,9 @@
max-width: 190px; max-width: 190px;
width: 100%; width: 100%;
} }
.email-error-message {
color: red;
}
} }
@media (max-width: 805px) { @media (max-width: 805px) {

View File

@ -99,6 +99,18 @@ export const ModalTiсket = ({
const { showNotification } = useNotification(); const { showNotification } = useNotification();
const [commentSendDisable, setCommentSendDisable] = useState(false); const [commentSendDisable, setCommentSendDisable] = useState(false);
const closeModal = () => {
setActive(false);
// Восстанавливаем скролл при закрытии модального окна
document.body.style.overflow = "auto";
};
const [isExpanded, setIsExpanded] = useState(false);
const toggleModalSize = () => {
setIsExpanded((prevState) => !prevState);
};
function deleteTask() { function deleteTask() {
apiRequest("/task/update-task", { apiRequest("/task/update-task", {
method: "PUT", method: "PUT",
@ -107,7 +119,7 @@ export const ModalTiсket = ({
status: 0 status: 0
} }
}).then(() => { }).then(() => {
setActive(false); closeModal();
dispatch(setProjectBoardFetch(projectId)); dispatch(setProjectBoardFetch(projectId));
showNotification({ showNotification({
show: true, show: true,
@ -594,20 +606,20 @@ export const ModalTiсket = ({
<div <div
className={active ? "modal-ticket active" : "modal-ticket"} className={active ? "modal-ticket active" : "modal-ticket"}
onClick={(e) => { onClick={(e) => {
if (e.target.className.includes("modal-ticket")) setActive(false); if (e.target.className.includes("modal-ticket")) closeModal();
}} }}
> >
<div className="modal-ticket__content"> <div className={`modal-ticket__content ${isExpanded ? "expanded" : ""}`}>
<div className="content"> <div className="content">
<h3 className="title-project"> <h3 className="title-project">
<img src={category} className="title-project__category"></img> <img src={category} className="title-project__category"></img>
{projectName} {projectName}
<Link <img
to={`/tracker/task/${task.id}`} src={fullScreen}
alt="Full screen"
onClick={toggleModalSize}
className="title-project__full" className="title-project__full"
> />
<img src={fullScreen}></img>
</Link>
</h3> </h3>
<div className="content__task"> <div className="content__task">
{editOpen ? ( {editOpen ? (
@ -757,7 +769,7 @@ export const ModalTiсket = ({
</div> </div>
<div className="workers"> <div className="workers">
<div className="workers_box task__info"> <div className="workers_box task__info">
<span className="exit" onClick={() => setActive(false)}></span> <span className="exit" onClick={() => closeModal()}></span>
<h5>Создатель: </h5> <h5>Создатель: </h5>
<p className="workers__creator">{task.user?.fio}</p> <p className="workers__creator">{task.user?.fio}</p>
{executor ? ( {executor ? (

View File

@ -15,13 +15,20 @@
display: flex; display: flex;
} }
.modal-ticket__content.expanded {
width: 100vw;
height: 100vh;
max-height: none;
max-width: none;
}
.modal-ticket__content { .modal-ticket__content {
background: #ffffff; background: #ffffff;
border-radius: 8px; border-radius: 8px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
max-height: 700px; max-height: 700px;
// overflow-y: auto; max-width: 915px;
@media (max-width: 990px) { @media (max-width: 990px) {
width: 96%; width: 96%;
@ -52,7 +59,7 @@
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 630px; width: 68%;
margin: 26px 0 0 21px; margin: 26px 0 0 21px;
.title-project { .title-project {
@ -160,7 +167,6 @@
.comments__list { .comments__list {
display: flex; display: flex;
overflow-y: auto;
height: 190px; height: 190px;
flex-direction: column; flex-direction: column;
@ -364,7 +370,6 @@
column-gap: 25px; column-gap: 25px;
row-gap: 20px; row-gap: 20px;
margin-top: 33px; margin-top: 33px;
overflow-y: auto;
.task-file { .task-file {
cursor: pointer; cursor: pointer;
@ -607,6 +612,7 @@
.workers { .workers {
position: relative; position: relative;
border-left: 1px solid #f1f1f1; border-left: 1px solid #f1f1f1;
width: 32%;
.exit { .exit {
cursor: pointer; cursor: pointer;

View File

@ -72,6 +72,7 @@ export const TrackerModal = ({
const [selectWorkersOpen, setSelectWorkersOpen] = useState(false); const [selectWorkersOpen, setSelectWorkersOpen] = useState(false);
const [selectedWorker, setSelectedWorker] = useState(null); const [selectedWorker, setSelectedWorker] = useState(null);
const [emailWorker, setEmailWorker] = useState(""); const [emailWorker, setEmailWorker] = useState("");
const [emailError, setEmailError] = useState("");
const [selectColumnPriority, setSelectColumnPriority] = useState( const [selectColumnPriority, setSelectColumnPriority] = useState(
"Выберите приоритет колонки" "Выберите приоритет колонки"
); );
@ -114,6 +115,19 @@ export const TrackerModal = ({
return; return;
} }
const existingColumn = projectBoard.columns.find(
(column) => column.title === valueColumn
);
if (existingColumn) {
showNotification({
show: true,
text: "Колонка с таким названием уже существует",
type: "error"
});
return;
}
apiRequest("/project-column/create-column", { apiRequest("/project-column/create-column", {
method: "POST", method: "POST",
data: { data: {
@ -325,19 +339,6 @@ export const TrackerModal = ({
setActive(false); setActive(false);
setSelectedWorker(""); setSelectedWorker("");
setSelectWorkersOpen(false); setSelectWorkersOpen(false);
});
}
function inviteUserByEmail() {
apiRequest("/project/add-user-by-email", {
method: "POST",
data: {
email: emailWorker,
project_id: projectBoard.id
}
}).then((el) => {
setActive(false);
setEmailWorker("");
showNotification({ showNotification({
show: true, show: true,
text: "Приглашение отправлено", text: "Приглашение отправлено",
@ -346,6 +347,35 @@ export const TrackerModal = ({
}); });
} }
const validateEmail = (email) => {
// Простая валидация адреса электронной почты
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailPattern.test(email);
};
const inviteUserByEmail = () => {
if (validateEmail(emailWorker)) {
setEmailError("");
apiRequest("/project/add-user-by-email", {
method: "POST",
data: {
email: emailWorker,
project_id: projectBoard.id
}
}).then((el) => {
setActive(false);
setEmailWorker("");
showNotification({
show: true,
text: "Приглашение отправлено",
type: "success"
});
});
} else {
setEmailError("Некорректный e-mail адрес");
}
};
useEffect(() => { useEffect(() => {
modalType === "add-worker" modalType === "add-worker"
? apiRequest("/project/my-employee").then((el) => { ? apiRequest("/project/my-employee").then((el) => {
@ -426,8 +456,18 @@ export const TrackerModal = ({
} }
}; };
const handleModalClose = () => {
setEmailError("");
setEmailWorker("");
};
return ( return (
<ModalLayout active={active} setActive={setActive} type={modalType}> <ModalLayout
active={active}
setActive={setActive}
onClose={handleModalClose}
type={modalType}
>
{modalType === "add-worker" && ( {modalType === "add-worker" && (
<> <>
<div className="select__person"> <div className="select__person">
@ -498,6 +538,7 @@ export const TrackerModal = ({
value={emailWorker} value={emailWorker}
onChange={(e) => setEmailWorker(e.target.value)} onChange={(e) => setEmailWorker(e.target.value)}
/> />
<div className="email-error-message">{emailError}</div>
</div> </div>
<BaseButton <BaseButton
styles={"button-add add-person-btn"} styles={"button-add add-person-btn"}
@ -864,7 +905,14 @@ export const TrackerModal = ({
</div> </div>
)} )}
<span className="exit" onClick={() => setActive(false)}></span> <span
className="exit"
onClick={() => {
setActive(false);
setEmailError("");
setEmailWorker("");
}}
></span>
</ModalLayout> </ModalLayout>
); );
}; };

View File

@ -227,6 +227,7 @@
min-width: 240px; min-width: 240px;
height: 42px; height: 42px;
width: 100%; width: 100%;
margin: 10px 0 10px 0;
p { p {
overflow: hidden; overflow: hidden;

View File

@ -110,6 +110,10 @@ export const ProfileHeader = () => {
} }
}; };
const closeMenu = () => {
setActive(false);
};
return ( return (
<header className="profile-header"> <header className="profile-header">
<div className="auth-title"> <div className="auth-title">
@ -179,6 +183,7 @@ export const ProfileHeader = () => {
</button> </button>
</nav> </nav>
</div> </div>
{active && <div className="backdrop" onClick={closeMenu}></div>}
</header> </header>
); );
}; };

View File

@ -17,7 +17,6 @@
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
height: 100%; height: 100%;
z-index: 9;
max-width: 1160px; max-width: 1160px;
width: 100%; width: 100%;
margin: 0 auto; margin: 0 auto;
@ -36,6 +35,7 @@
@media (max-width: 414px) { @media (max-width: 414px) {
display: block; display: block;
z-index: 9;
} }
&__line { &__line {
@ -64,9 +64,19 @@
background: white; background: white;
} }
.backdrop {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 7;
}
.auth-body { .auth-body {
opacity: 0; opacity: 0;
z-index: 99; z-index: 8;
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
@ -99,7 +109,7 @@
flex-direction: column; flex-direction: column;
a { a {
padding: 10px 0 0 0; padding: 15px 0 0 10px;
} }
a, a,
@ -134,7 +144,7 @@
opacity: 1; opacity: 1;
display: flex; display: flex;
overflow: visible; overflow: visible;
width: calc(100vw / 3); width: calc(100vw / 2.5);
transition: width 0.3s; transition: width 0.3s;
height: 100%; height: 100%;
flex-direction: column; flex-direction: column;
@ -188,6 +198,7 @@
&__logout-burger { &__logout-burger {
background: none; background: none;
border: none; border: none;
padding: 15px 0 0 0;
font-weight: 500; font-weight: 500;
font-size: 16px; font-size: 16px;
line-height: 32px; line-height: 32px;

View File

@ -224,11 +224,9 @@ export const ProjectTracker = () => {
} }
function openTicket(e, task) { function openTicket(e, task) {
if (window.innerWidth < 985) {
return;
}
setSelectedTicket(task); setSelectedTicket(task);
setModalActiveTicket(true); setModalActiveTicket(true);
document.body.style.overflow = "hidden";
} }
function deleteColumn(column) { function deleteColumn(column) {