92 lines
2.9 KiB
TypeScript
92 lines
2.9 KiB
TypeScript
import { CSSProperties, useEffect, useState } from 'react'
|
|
import Stories from 'react-insta-stories'
|
|
import { Story } from 'react-insta-stories/dist/interfaces'
|
|
|
|
import { BottomNavBar, AnnouncementDetails, Filters } from '../components'
|
|
import { useStoryDimensions } from '../hooks'
|
|
import { useAnnouncements } from '../hooks/api'
|
|
import { defaultFilters } from '../utils/filters'
|
|
import { Announcement } from '../api/announcement/types'
|
|
import { categoryGraphics } from '../assets/category'
|
|
|
|
import puffSpinner from '../assets/puff.svg'
|
|
import { gotError } from '../hooks/useFetch'
|
|
|
|
function generateStories(announcements: Announcement[]): Story[] {
|
|
return announcements.map(announcement => {
|
|
return ({
|
|
id: announcement.id,
|
|
url: announcement.src || categoryGraphics[announcement.category],
|
|
type: announcement.src?.endsWith('mp4') ? 'video' : undefined,
|
|
seeMore: ({ close }: { close: () => void }) => <AnnouncementDetails close={close} announcement={announcement} />
|
|
})
|
|
})
|
|
}
|
|
|
|
function fallbackGenerateStories(announcementsFetch: ReturnType<typeof useAnnouncements>) {
|
|
if (announcementsFetch.loading)
|
|
return fallbackStory()
|
|
|
|
if (gotError(announcementsFetch))
|
|
return fallbackStory(announcementsFetch.error, true)
|
|
|
|
const stories = generateStories(announcementsFetch.data)
|
|
|
|
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={styles.center} className={isError ? 'text-danger' : ''}>
|
|
{text || <img src={puffSpinner} />}
|
|
</div>
|
|
)
|
|
},
|
|
}]
|
|
|
|
const styles = {
|
|
container: {
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
backgroundColor: 'rgb(17, 17, 17)',
|
|
} as CSSProperties,
|
|
center: {
|
|
margin: 'auto'
|
|
} as CSSProperties,
|
|
}
|
|
|
|
function HomePage() {
|
|
const { height, width } = useStoryDimensions(16 / 9)
|
|
|
|
const [filterShown, setFilterShown] = useState(false)
|
|
const [filter, setFilter] = useState(defaultFilters)
|
|
|
|
const announcementsFetch = useAnnouncements(filter)
|
|
|
|
const stories = fallbackGenerateStories(announcementsFetch)
|
|
|
|
return (<>
|
|
<Filters filter={filter} setFilter={setFilter} filterShown={filterShown} setFilterShown={setFilterShown} />
|
|
<div style={styles.container}>
|
|
<Stories
|
|
stories={stories}
|
|
defaultInterval={11000}
|
|
height={height}
|
|
width={width}
|
|
loop={true}
|
|
keyboardNavigation={true}
|
|
/>
|
|
</div>
|
|
<BottomNavBar toggleFilters={setFilterShown} width={width} />
|
|
</>)
|
|
}
|
|
|
|
export default HomePage
|