moved hooks to separate directories, added stories fallback
This commit is contained in:
parent
e9b7a9e32a
commit
dc6f8fe8f2
13
front/src/assets/puff.svg
Normal file
13
front/src/assets/puff.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
|
||||
<svg width="44" height="44" viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" stroke="#fff">
|
||||
<g fill="none" fill-rule="evenodd" stroke-width="2">
|
||||
<circle cx="22" cy="22" r="1">
|
||||
<animate attributeName="r" begin="0s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite"/>
|
||||
<animate attributeName="stroke-opacity" begin="0s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
<circle cx="22" cy="22" r="1">
|
||||
<animate attributeName="r" begin="-0.9s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite"/>
|
||||
<animate attributeName="stroke-opacity" begin="-0.9s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
5
front/src/hooks/api/index.js
Normal file
5
front/src/hooks/api/index.js
Normal file
@ -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'
|
41
front/src/hooks/api/useFetch.js
Normal file
41
front/src/hooks/api/useFetch.js
Normal file
@ -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
|
26
front/src/hooks/api/useHomeAnnouncementList.js
Normal file
26
front/src/hooks/api/useHomeAnnouncementList.js
Normal file
@ -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
|
@ -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: "Петроградская"
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: "Арбуз",
|
||||
category: "soup",
|
||||
src: "/static/watermelon.mp4",
|
||||
bestBy: 20000,
|
||||
description: "Очень вкусный арбуз, прям, закачаешься",
|
||||
lat: 60.9724,
|
||||
lng: 30.3227,
|
||||
address: "ул. Профессора Попова, дом 50 литера Ф",
|
||||
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 (
|
||||
<div style={{ margin: 'auto' }}>
|
||||
{text || <img src={puffSpinner} />}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
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 (<>
|
||||
<Filters filter={filter} setFilter={setFilter} filterShown={filterShown} setFilterShown={setFilterShown} />
|
||||
<div style={{ display: "flex", justifyContent: "center", backgroundColor: "rgb(17, 17, 17)" }}>
|
||||
{announcements.length && <Stories
|
||||
stories={generateStories(announcements)}
|
||||
{announcementsFetch.error ?
|
||||
(
|
||||
<div style={{ width, height, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<p className='text-danger'>{announcementsFetch.error}</p>
|
||||
</div>
|
||||
) : (
|
||||
<Stories
|
||||
stories={stories}
|
||||
defaultInterval={11000}
|
||||
height={height}
|
||||
width={width}
|
||||
loop={true}
|
||||
keyboardNavigation={true}
|
||||
/>}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<BottomNavBar toggleFilters={toggleFilters} width={width} />
|
||||
<BottomNavBar toggleFilters={setFilterShown} width={width} />
|
||||
</>)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user