From dc6f8fe8f2e08a7f0680ddbf720a018815d71ce0 Mon Sep 17 00:00:00 2001 From: dm1sh Date: Wed, 17 May 2023 10:46:59 +0300 Subject: [PATCH] moved hooks to separate directories, added stories fallback --- front/src/assets/puff.svg | 13 ++ front/src/hooks/api/index.js | 5 + front/src/hooks/api/useFetch.js | 41 ++++++ .../src/hooks/api/useHomeAnnouncementList.js | 26 ++++ .../{utils => hooks}/useStoryDimensions.js | 0 front/src/pages/HomePage.jsx | 117 ++++++++---------- 6 files changed, 138 insertions(+), 64 deletions(-) create mode 100644 front/src/assets/puff.svg create mode 100644 front/src/hooks/api/index.js create mode 100644 front/src/hooks/api/useFetch.js create mode 100644 front/src/hooks/api/useHomeAnnouncementList.js rename front/src/{utils => hooks}/useStoryDimensions.js (100%) diff --git a/front/src/assets/puff.svg b/front/src/assets/puff.svg new file mode 100644 index 0000000..d598440 --- /dev/null +++ b/front/src/assets/puff.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/front/src/hooks/api/index.js b/front/src/hooks/api/index.js new file mode 100644 index 0000000..69169bc --- /dev/null +++ b/front/src/hooks/api/index.js @@ -0,0 +1,5 @@ +export { default as useHomeAnnouncementList } from './useHomeAnnouncementList' +export { default as useBook } from './useBook' +export { default as useAuth } from './useAuth' +export { default as useTrashboxes } from './useTrashboxes' +export { default as useAddAnnouncement } from './useAddAnnouncement' diff --git a/front/src/hooks/api/useFetch.js b/front/src/hooks/api/useFetch.js new file mode 100644 index 0000000..5422f82 --- /dev/null +++ b/front/src/hooks/api/useFetch.js @@ -0,0 +1,41 @@ +import { useEffect, useState } from "react" + +const useFetch = (url, params, initialData) => { + const [data, setData] = useState(initialData) + const [loading, setLoading] = useState(true) + const [error, setError] = useState("") + + useEffect(() => { + fetch(url, params) + .then(res => { + if (!res.ok) { + switch (res.status) { + case 401: { + throw new Error("Ошибка авторизации") + } + case 404: { + new Error("Объект не найден") + } + break + default: { + throw new Error("Ошибка ответа от сервера") + } + } + } + + return res.json() + }) + .then(data => { + setData(data) + setLoading(false) + }) + .catch(err => { + setError("Ошибка сети") + setLoading(false) + }) + }, [url, params]) + + return { data, loading, error } +} + +export default useFetch diff --git a/front/src/hooks/api/useHomeAnnouncementList.js b/front/src/hooks/api/useHomeAnnouncementList.js new file mode 100644 index 0000000..db1fad0 --- /dev/null +++ b/front/src/hooks/api/useHomeAnnouncementList.js @@ -0,0 +1,26 @@ +import useFetch from './useFetch' +import { API_URL } from '../../config' +import { removeNull } from '../../utils' + +const initialAnnouncements = { list_of_announcements: [], Success: true } + +const useHomeAnnouncementList = (filters) => { + const { data, loading, error } = useFetch( + API_URL + '/announcements?' + new URLSearchParams(removeNull(filters)), + null, + initialAnnouncements + ) + + const annList = data.list_of_announcements + + const res = annList.map(ann => ({ + ...ann, + lat: ann.latitude, + lng: ann.longtitude, + bestBy: ann.best_by + })) + + return { data: error ? [] : res, loading, error } +} + +export default useHomeAnnouncementList diff --git a/front/src/utils/useStoryDimensions.js b/front/src/hooks/useStoryDimensions.js similarity index 100% rename from front/src/utils/useStoryDimensions.js rename to front/src/hooks/useStoryDimensions.js diff --git a/front/src/pages/HomePage.jsx b/front/src/pages/HomePage.jsx index 7579254..63cfe93 100644 --- a/front/src/pages/HomePage.jsx +++ b/front/src/pages/HomePage.jsx @@ -1,18 +1,15 @@ -import Stories from 'react-insta-stories' import { useEffect, useState } from 'react' +import Stories from 'react-insta-stories' import BottomNavBar from '../components/BottomNavBar' -import useStoryDimensions from '../utils/useStoryDimensions' - -import { API_URL } from '../config' - -import "./leafletStyles.css" -import 'leaflet/dist/leaflet.css' - +import useStoryDimensions from '../hooks/useStoryDimensions' import AnnouncementDetails from '../components/AnnouncementDetails' -import { categoryGraphics } from '../assets/category' import Filters from '../components/Filters' -import { removeNull } from '../utils' + +import { useHomeAnnouncementList } from '../hooks/api' + +import puffSpinner from '../assets/puff.svg' +import { categoryGraphics } from '../assets/category' function generateStories(announcements) { return announcements.map(announcement => { @@ -25,76 +22,68 @@ function generateStories(announcements) { }) } -const mock = [ - { - id: 5, - name: "Огурец", - category: "fruits_vegatables", - src: "https://upload.wikimedia.org/wikipedia/commons/thumb/2/24/Marketvegetables.jpg/800px-Marketvegetables.jpg", - bestBy: 10000, - description: "Очень вкусный огурец, прям, закачаешься", - lat: 59.9724, - lng: 30.3227, - address: "ул. Профессора Попова, дом 5 литера Ф", - metro: "Петроградская" +function fallbackGenerateStories(announcementsFetch) { + const stories = generateStories(announcementsFetch.data) + + if (announcementsFetch.loading) + return fallbackStory() + + if (announcementsFetch.error) + return fallbackStory(announcementsFetch.error) + + if (stories.length == 0) + return fallbackStory("Здесь пока пусто") + + return stories +} + +const fallbackStory = (text) => [{ + content: ({ action }) => { + // eslint-disable-next-line react-hooks/rules-of-hooks + useEffect(() => { action('pause') }, [action]) + + return ( +
+ {text || } +
+ ) }, - { - id: 9, - name: "Арбуз", - category: "soup", - src: "/static/watermelon.mp4", - bestBy: 20000, - description: "Очень вкусный арбуз, прям, закачаешься", - lat: 60.9724, - lng: 30.3227, - address: "ул. Профессора Попова, дом 50 литера Ф", - metro: "Горьковская" - } -] + header: { heading: text } +}] const defaultFilters = { userId: null, category: null, metro: null, bookedBy: null } -const PROD = true - function HomePage() { const { height, width } = useStoryDimensions(16 / 10) - const [announcements, setAnnouncements] = useState([]) - const [filterShown, setFilterShown] = useState(false) - const [filter, setFilter] = useState(defaultFilters) - useEffect(() => { - (async () => { - try { - const res = PROD ? await fetch(API_URL + "/announcements?" + new URLSearchParams(removeNull(filter))) : null + const announcementsFetch = useHomeAnnouncementList(filter) - const json = PROD ? (await res.json()).list_of_announcements : mock - - setAnnouncements(json) - } - catch (err) { - console.error(err) - } - })() - }, [filter]) - - const toggleFilters = (toggle) => setFilterShown(toggle) + const stories = fallbackGenerateStories(announcementsFetch) return (<>
- {announcements.length && } + {announcementsFetch.error ? + ( +
+

{announcementsFetch.error}

+
+ ) : ( + + ) + }
- + ) }