diff --git a/src/pages/AddNewsPage/AddNewsPage.jsx b/src/pages/AddNewsPage/AddNewsPage.jsx new file mode 100644 index 00000000..21cdc7c4 --- /dev/null +++ b/src/pages/AddNewsPage/AddNewsPage.jsx @@ -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 ( + +
+
+

Предложить новость

+
+
+ + {gallery.length}/5 +
+
+ +
+
+ +
+ { + setIsAgreementChecked(!isAgreementChecked); + }} /> +
+ + +
+ +
+
+
+ ); +}; + +export default AddNewsPage; diff --git a/src/pages/AddNewsPage/AddNewsPage.scss b/src/pages/AddNewsPage/AddNewsPage.scss new file mode 100644 index 00000000..87ee5dbf --- /dev/null +++ b/src/pages/AddNewsPage/AddNewsPage.scss @@ -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; + } + } +} \ No newline at end of file diff --git a/src/pages/AddNewsPage/api.js b/src/pages/AddNewsPage/api.js new file mode 100644 index 00000000..69eaef78 --- /dev/null +++ b/src/pages/AddNewsPage/api.js @@ -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; diff --git a/src/pages/App/App.jsx b/src/pages/App/App.jsx index c2cdbae8..8a11f1d7 100644 --- a/src/pages/App/App.jsx +++ b/src/pages/App/App.jsx @@ -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(); @@ -49,6 +52,13 @@ 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 = () => { @@ -56,6 +66,16 @@ const App = () => { setInfoTooltipImage(null); }; + const closeConfirmPopup = () => { + setConfirmPopupOpen(false); + setTimeout(() => { + setQuestion(''); + setDescription(''); + setConfirmBtnText(''); + setRejectBtnText(''); + }, 1000); + }; + const handleSignOut = () => { localStorage.clear(); setLoggedIn(false); @@ -163,6 +183,21 @@ const App = () => { /> } /> + } + /> + } /> } /> } /> @@ -198,6 +233,15 @@ const App = () => {