Added type definitions for components, functions, data Added guards for network responses fixes #8
80 lines
2.7 KiB
TypeScript
80 lines
2.7 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import Stories from 'react-insta-stories'
|
|
|
|
import { BottomNavBar, AnnouncementDetails, Filters } from '../components'
|
|
import { useStoryDimensions } from '../hooks'
|
|
import { useHomeAnnouncementList } from '../hooks/api'
|
|
import { defaultFilters } from '../utils/filters'
|
|
|
|
import puffSpinner from '../assets/puff.svg'
|
|
import { categoryGraphics } from '../assets/category'
|
|
import { Announcement } from '../hooks/api/useHomeAnnouncementList'
|
|
import { Story } from 'react-insta-stories/dist/interfaces'
|
|
|
|
function generateStories(announcements: Announcement[]): Story[] {
|
|
return announcements.map(announcement => {
|
|
return ({
|
|
id: announcement.id,
|
|
url: announcement.src || categoryGraphics.get(announcement.category),
|
|
type: announcement.src?.endsWith("mp4") ? "video" : undefined,
|
|
seeMore: ({ close }: { close: () => void }) => <AnnouncementDetails close={close} announcement={announcement} />
|
|
})
|
|
})
|
|
}
|
|
|
|
function fallbackGenerateStories(announcementsFetch: ReturnType<typeof useHomeAnnouncementList>) {
|
|
const stories = generateStories(announcementsFetch.data)
|
|
|
|
if (announcementsFetch.loading)
|
|
return fallbackStory()
|
|
|
|
if (announcementsFetch.error)
|
|
return fallbackStory(announcementsFetch.error, true)
|
|
|
|
if (stories.length === 0)
|
|
return fallbackStory("Здесь пока пусто")
|
|
|
|
return stories
|
|
}
|
|
|
|
const fallbackStory = (text = '', isError = false): Story[] => [{
|
|
content: ({ action }) => {
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
useEffect(() => { action('pause') }, [action])
|
|
|
|
return (
|
|
<div style={{ margin: 'auto' }} className={isError ? "text-danger" : ''}>
|
|
{text || <img src={puffSpinner} />}
|
|
</div>
|
|
)
|
|
},
|
|
}]
|
|
|
|
function HomePage() {
|
|
const { height, width } = useStoryDimensions(16 / 10)
|
|
|
|
const [filterShown, setFilterShown] = useState(false)
|
|
const [filter, setFilter] = useState(defaultFilters)
|
|
|
|
const announcementsFetch = useHomeAnnouncementList(filter)
|
|
|
|
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)" }}>
|
|
<Stories
|
|
stories={stories}
|
|
defaultInterval={11000}
|
|
height={height}
|
|
width={width}
|
|
loop={true}
|
|
keyboardNavigation={true}
|
|
/>
|
|
</div>
|
|
<BottomNavBar toggleFilters={setFilterShown} width={width} />
|
|
</>)
|
|
}
|
|
|
|
export default HomePage
|