Skip to content

Commit

Permalink
Merge pull request #237 from Lapkipomoshi/dev-FormNews
Browse files Browse the repository at this point in the history
Dev form news
  • Loading branch information
Notsmartname committed May 20, 2024
2 parents 54b6bf6 + 5c1269f commit 72e6277
Show file tree
Hide file tree
Showing 12 changed files with 541 additions and 9 deletions.
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

0 comments on commit 72e6277

Please sign in to comment.