Skip to content

Commit

Permalink
Added component AddNewsPage
Browse files Browse the repository at this point in the history
  • Loading branch information
Notsmartname committed May 19, 2024
1 parent 99be3d2 commit 5c1269f
Show file tree
Hide file tree
Showing 4 changed files with 284 additions and 0 deletions.
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;
47 changes: 47 additions & 0 deletions src/pages/AddNewsPage/AddNewsPage.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
.add-news {
display: flex;
flex-direction: column;
padding: 44px 0 167px 15px;

&__title {
margin: 0;
padding-bottom: 24px;
font-size: 40px;
line-height: 49px;
font-weight: 600;
font-family: 'Montserrat Alternates';
text-align: left;
}

&__form {
&-photo {
position: relative;

&-count {
position: absolute;
left: 115px;
top: 50px;
font-family: var(--second-family);
font-weight: 500;
font-size: 16px;
text-align: center;
color: #ff712c;
cursor: pointer;
pointer-events: none;
}

}

&-heading {
width: 944px;
}


&-buttons {
margin-top: 40px;
display: flex;
align-items: center;
gap: 32px;
}
}
}
36 changes: 36 additions & 0 deletions src/pages/AddNewsPage/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { baseUrl } from '../../utils/constants';

class AddArticleApi {
constructor(options) {
this._baseUrl = options._baseUrl;
}

_processTheResponse(res) {
if (res.ok) {
return res.json();
}
return Promise.reject(`Ошибка: ${res.status}`);
}

postArticle(token, article) {
return fetch(`${this._baseUrl}/v1/my-shelter/news/`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
authorization: `Bearer ${token}`,
},
body: JSON.stringify(article),
})
.then((res) => {
return this._processTheResponse(res);
});

}
}

const addArticleApi = new AddArticleApi({
_baseUrl: baseUrl,
});

export default addArticleApi;
44 changes: 44 additions & 0 deletions src/pages/App/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ import getUserInfo from './api/userApi';
import AppContext from '../../contexts/App';
import MyShelterPage from '../MyShelterPage/MyShelterPage';
import MyShelterEdit from '../../modules/MySheelterEdit/MyShelterEdit';
import AddNewsPage from '../AddNewsPage/AddNewsPage';
import ConfirmPopup from '../../components/ConfirmPopup/ConfirmPopup';


const App = () => {
const navigate = useNavigate();
Expand All @@ -49,13 +52,30 @@ const App = () => {
const [infoTooltipImage, setInfoTooltipImage] = useState(null);
const [message, setMessage] = useState('');

const [confirmPopupOpen, setConfirmPopupOpen] = useState(false);
const [question, setQuestion] = useState('');
const [description, setDescription] = useState('');
const [confirmBtnText, setConfirmBtnText] = useState('');
const [rejectBtnText, setRejectBtnText] = useState('');
const [iconBasket, setIconBasket] = useState(false);

const [success, setSuccess] = useState(false);

const closeInfoTooltip = () => {
setInfoTooltipOpen(false);
setInfoTooltipImage(null);
};

const closeConfirmPopup = () => {
setConfirmPopupOpen(false);
setTimeout(() => {
setQuestion('');
setDescription('');
setConfirmBtnText('');
setRejectBtnText('');
}, 1000);
};

const handleSignOut = () => {
localStorage.clear();
setLoggedIn(false);
Expand Down Expand Up @@ -163,6 +183,21 @@ const App = () => {
/>
}
/>
<Route
path='/my-shelter/add-news'
element={<ProtectedRoute condition={loggedIn} component={AddNewsPage}
openInfoPopup={setInfoTooltipOpen}
setInfoPopupImage={setInfoTooltipImage}
setMessageInfoPopup={setMessage}
setConfirmPopupOpen={setConfirmPopupOpen}
setQuestion={setQuestion}
setDescription={setDescription}
setConfirmBtnText={setConfirmBtnText}
setRejectBtnText={setRejectBtnText}
setIconBasket={setIconBasket}
/>}
/>

<Route path='/papers' element={<PapersPage />} />
<Route path='/papers/:id' element={<PaperPage />} />
<Route path='/news' element={<NewsPage />} />
Expand Down Expand Up @@ -198,6 +233,15 @@ const App = () => {
<Footer />

<InfoTooltip isOpen={infoTooltipOpen} image={infoTooltipImage} message={message} onClose={closeInfoTooltip} />
<ConfirmPopup
isOpen={confirmPopupOpen}
question={question}
desc={description}
confirmBtnText={confirmBtnText}
rejectBtnText={rejectBtnText}
onClose={closeConfirmPopup}
iconBasket={iconBasket}
/>
</div>
</AppContext.Provider>
</CurrentUserContext.Provider>
Expand Down

0 comments on commit 5c1269f

Please sign in to comment.