Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev form news #237

Merged
merged 6 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions src/components/ConfirmPopup/ConfirmPopup.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React, { useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import './ConfirmPopup.scss';
import { Button } from '../../ui';
import DeleteIcon from '../../images/DeleteIcon/DeleteIcon';

const ConfirmPopup = ({ isOpen, question, onClose, desc = '', confirmBtnText, rejectBtnText, iconBasket }) => {
const popup = useRef(null);
const navigate = useNavigate();

const handleOverlayClose = (e) => {
const confirmPopup = e.target.classList;
if (confirmPopup.contains('popup_opened') || confirmPopup.contains('popup__button-close')) {
onClose();
}
};

const handleEscClose = (e) => {
if (e.key === 'Escape') {
onClose();
}
};

const handleCloseToNews = () => {
navigate(-1);
onClose();
};

useEffect(() => {
document.addEventListener('keydown', handleEscClose);
document.addEventListener('click', handleOverlayClose);
return () => {
document.removeEventListener('keydown', handleEscClose);
document.removeEventListener('click', handleOverlayClose);
};
}, []);

return (
<div
className={`popup ${isOpen && 'popup_opened'}`}
ref={popup}
>
<div className='popup__content'>
<h3 className='popup__content-question standard-font standard-font_type_h3'>{question}</h3>

{desc !== '' && <p className='popup__content-descr' >{desc}</p>}

<Button
type='button'
className='popup__content-close'
onClick={onClose}
/>
<div className='popup__content-btn-group'>
<Button
className='popup__content-btn-group-confirm'
type='button'
onClick={handleCloseToNews}
>
{iconBasket && <DeleteIcon />} {confirmBtnText}
</Button>
<Button
className='popup__content-btn-group-reject'
type='button'
onClick={onClose}
theme='transparent'
>
{rejectBtnText}
</Button>
</div>
</div>
</div>
);
};

export default ConfirmPopup;
89 changes: 89 additions & 0 deletions src/components/ConfirmPopup/ConfirmPopup.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
$images-path: '../../images';

.popup {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.36);
position: fixed;
left: 0;
top: 0;
visibility: hidden;
opacity: 0;
transition: visibility 0.5s, opacity 0.5s ease-in-out;
z-index: 1;

&_opened {
display: flex;
visibility: visible;
opacity: 1;
z-index: 2;
}

&__content {
width: 100%;
max-width: 576px;
height: fit-content;
background-color: var(--color-background-additional);
border-radius: 30px;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
padding: 80px 106px 60px;

&-question,
&-descr {
text-align: center;
font-family: var(--font-family-title);
color: var(--color-text-base);
}

&-question {
font-weight: 600;
line-height: normal;
font-size: 40px;
}

&-descr {
font-weight: 500;
font-size: 24px;
}

&-close {
background-image: url('#{$images-path}/icons/ic_button_close.svg');
background-size: contain;
border: none;
width: 28px;
height: 28px;
background-color: rgba(0, 0, 0, 0);
padding: 0;
margin: 0;
transition: opacity 0.2s;
position: absolute;
top: 34px;
right: 80px;

&:hover {
opacity: 0.6;
cursor: pointer;
}
}

&-btn-group {
display: flex;
align-items: center;
gap: 20px;
margin-top: 20px;

&-confirm {
display: flex;
align-items: center;
gap: 6px;
}
}
}

}
10 changes: 6 additions & 4 deletions src/modules/ShelterNews/ShelterNews.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { useOutletContext, useParams } from 'react-router-dom';
import { useOutletContext, useParams, Link } from 'react-router-dom';
import './ShelterNews.scss';
import NewsSection from '../NewsSection/NewsSection';
import { Button } from '../../ui';
Expand All @@ -12,10 +12,12 @@ const ShelterNews = () => {
<section className='shelter-section shelter-news'>
<div className='shelter-section-top'>
<h2 className='shelter-section__title shelter-news__title'>Новости приюта</h2>
<Button
<Link
to='/my-shelter/add-news'
className='shelter-section__btn-news'
disabled={!isOwner}
>Предложить новость</Button>
>
<Button disabled={!isOwner}>Предложить новость</Button>
</Link>
</div>
<NewsSection shelterId={id} />
<Button className='shelter-section__btn-more' theme='transparent'>Больше новостей</Button>
Expand Down
3 changes: 0 additions & 3 deletions src/modules/ShelterNews/ShelterNews.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@
}

.shelter-section__btn-news {
padding: 12px 26px;
font-size: 16px;
min-width: 250px;
height: 44px;
}

.shelter-section__btn-more {
Expand Down
157 changes: 157 additions & 0 deletions src/pages/AddNewsPage/AddNewsPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import './AddNewsPage.scss';
import MainContainer from '../../components/MainContainer/MainContainer';
import DeclarationInput from '../../ui/DeclarationInput/DeclarationInput';
import useInput from '../../hooks/useInput';
import * as regex from '../../utils/regex';
import * as errorMessage from '../../utils/errorMessage';
import DeclarationTextarea from '../../ui/DeclarationTextarea/DeclarationTextarea';
import PrivacyCheckbox from '../../components/PrivacyCheckbox/PrivacyCheckbox';
import { Button } from '../../ui';
import AddPhotoBlock from '../../ui/AddPhotoBlock/AddPhotoBlock';

import imageSuccess from '../../images/icons/ic_success.svg';
import imageError from '../../images/icons/ic_error.svg';
import addArticleApi from './api';

const AddNewsPage = ({
openInfoPopup,
setInfoPopupImage,
setMessageInfoPopup,
setConfirmPopupOpen,
setQuestion,
setDescription,
setConfirmBtnText,
setRejectBtnText,
setIconBasket,
}) => {
const [isAgreementChecked, setIsAgreementChecked] = useState(false);
const [canSend, setCanSend] = useState(false);
const [newImage, setNewImage] = useState();
const [preImage, setPreImage] = useState();
const [gallery, setGallery] = useState([]);
const [article, setArticle] = useState({});
const sizeLimit = 5 * 1024 * 1024;
const navigate = useNavigate();

const newsTitle = useInput('', {
notEmpty: true, maxLength: 100, regex: regex.TEXT,
}, errorMessage.NEWS_NAME, false);

const newsBody = useInput('', {
notEmpty: true, maxLength: 15000, regex: regex.TEXT,
}, errorMessage.NEWS_TEXT, false);

const handleReject = () => {
setIconBasket(false);
setQuestion('Вы уверены, что хотите вернуться назад?');
setDescription('Внесенные данные не будут сохранены.');
setConfirmBtnText('Вернуться');
setRejectBtnText('Остаться');
setConfirmPopupOpen(true);
};

const handleSubmitForm = (e) => {
e.preventDefault();

const token = localStorage.getItem('access');
addArticleApi
.postArticle(token, { ...article })
.then(() => {
setInfoPopupImage(imageSuccess);
setMessageInfoPopup('Заявка на добавление приюта успешно добавлена! Её состояние можно отслеживать в личном кабинете.');
openInfoPopup(true);
setTimeout(() => {
openInfoPopup(false);
navigate(-1);
}, 3000);
})
.catch((error) => {
setInfoPopupImage(imageError);
setMessageInfoPopup('На запрос получена ошибка. Проверьте, пожалуйста, поля ввода и попробуйте ещё раз или обратитесь в поддержку.');
openInfoPopup(true);
setTimeout(() => {
openInfoPopup(false);
}, 3000);
throw new Error(error);
});
};

useEffect(() => {
if (newImage && newImage !== preImage && gallery.length < 5) {
setGallery([...gallery, { image: newImage }]);
setPreImage(newImage);
}
if (isAgreementChecked && !newsTitle.invalidText && !newsBody.invalidText && preImage) {
setArticle({
profile_image: gallery[0].image,
gallery: [...gallery],
header: newsTitle.value,
text: newsBody.value
});
setCanSend(true);
} else {
setCanSend(false);
}
}, [isAgreementChecked, newsTitle.value, newsBody.value, newImage]);
return (
<MainContainer>
<main className='main'>
<section className='add-news'>
<h2 className='add-news__title'>Предложить новость</h2>
<form className='add-news__form' onSubmit={handleSubmitForm}>
<div className='add-news__form-photo'>
<AddPhotoBlock
photo={newImage}
setPhoto={setNewImage}
labelText='Фото новости'
name='news_photo'
sizeLimit={sizeLimit} />
<span className='add-news__form-photo-count'>{gallery.length}/5</span>
</div>
<div className='add-news__form-heading'>
<DeclarationInput
type='text'
caption='Заголовок*'
name='news_title'
placeholder='В приюте Бирюлево побывали школьники'
required
inputState={newsTitle}
/>
</div>
<div className='add-news__form-body'>
<DeclarationTextarea
caption='Описание новости*'
name='news_text'
placeholder='Предложить текст новости'
required
inputState={newsBody}
textCols={30}
textRows={20}
/>
</div>
<PrivacyCheckbox
type='checkbox'
onChange={() => {
setIsAgreementChecked(!isAgreementChecked);
}} />
<div className='add-news__form-buttons'>
<Button
disabled={!canSend}
submit='submit'
>
Предложить новость
</Button>
<Button theme='transparent' onClick={handleReject}>
Отменить
</Button>
</div>
</form>
</section>
</main>
</MainContainer >
);
};

export default AddNewsPage;
Loading
Loading