Compare commits
2 Commits
7a044970f0
...
58d1996ce3
Author | SHA1 | Date | |
---|---|---|---|
58d1996ce3 | |||
bc154f8b6b |
@ -1,8 +1,8 @@
|
|||||||
import { initialUser } from '../../api/user'
|
import { initialUser } from '../../api/user'
|
||||||
import { User } from '../../api/user/types'
|
import { User } from '../../api/user/types'
|
||||||
import { UseFetchErrored, UseFetchSucced } from '../useFetch'
|
import { UseFetchReturn } from '../useFetch'
|
||||||
|
|
||||||
const useUser = (): UseFetchSucced<User> | UseFetchErrored => (
|
const useUser = (): UseFetchReturn<User> => (
|
||||||
// useFetch(
|
// useFetch(
|
||||||
// composeUserUrl(getToken()),
|
// composeUserUrl(getToken()),
|
||||||
// 'GET',
|
// 'GET',
|
||||||
@ -16,6 +16,7 @@ const useUser = (): UseFetchSucced<User> | UseFetchErrored => (
|
|||||||
data: initialUser,
|
data: initialUser,
|
||||||
loading: false,
|
loading: false,
|
||||||
error: null,
|
error: null,
|
||||||
|
setData: () => {0}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export { default as useStoryDimensions } from './useStoryDimensions'
|
export { default as useStoryDimensions } from './useStoryDimensions'
|
||||||
export { default as useSend } from './useSend'
|
export { default as useSend } from './useSend'
|
||||||
export { default as useFetch } from './useFetch'
|
export { default as useFetch } from './useFetch'
|
||||||
|
export { default as UseStoryIndex } from './useStoryIndex'
|
||||||
|
@ -3,40 +3,31 @@ import { useEffect, useState } from 'react'
|
|||||||
import { SetState } from '../utils/types'
|
import { SetState } from '../utils/types'
|
||||||
import useSend from './useSend'
|
import useSend from './useSend'
|
||||||
|
|
||||||
type UseFetchShared = {
|
type UseFetchShared<T> = {
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
abort?: () => void,
|
abort?: () => void,
|
||||||
|
setData: SetState<T | undefined>
|
||||||
}
|
}
|
||||||
|
|
||||||
type UseFetchSucced<T> = {
|
type UseFetchSucced<T> = {
|
||||||
error: null,
|
error: null,
|
||||||
data: T,
|
data: T,
|
||||||
} & UseFetchShared
|
} & UseFetchShared<T>
|
||||||
|
|
||||||
type UseFetchErrored = {
|
type UseFetchErrored<T> = {
|
||||||
error: string,
|
error: string,
|
||||||
data: undefined
|
data: undefined
|
||||||
} & UseFetchShared
|
} & UseFetchShared<T>
|
||||||
|
|
||||||
const gotError = <T>(res: UseFetchErrored | UseFetchSucced<T>): res is UseFetchErrored => (
|
const gotError = <T>(res: UseFetchErrored<T> | UseFetchSucced<T>): res is UseFetchErrored<T> => (
|
||||||
typeof res.error === 'string'
|
typeof res.error === 'string'
|
||||||
)
|
)
|
||||||
|
|
||||||
const fallbackError = <T>(res: UseFetchSucced<T> | UseFetchErrored) => (
|
const fallbackError = <T>(res: UseFetchSucced<T> | UseFetchErrored<T>) => (
|
||||||
gotError(res) ? res.error : res.data
|
gotError(res) ? res.error : res.data
|
||||||
)
|
)
|
||||||
|
|
||||||
type UseFetchReturn<T> = ({
|
type UseFetchReturn<T> = UseFetchSucced<T> | UseFetchErrored<T>
|
||||||
error: null,
|
|
||||||
data: T
|
|
||||||
} | {
|
|
||||||
error: string,
|
|
||||||
data: undefined
|
|
||||||
}) & {
|
|
||||||
loading: boolean,
|
|
||||||
setData: SetState<T | undefined>
|
|
||||||
abort?: (() => void)
|
|
||||||
}
|
|
||||||
|
|
||||||
function useFetch<R, T>(
|
function useFetch<R, T>(
|
||||||
url: string,
|
url: string,
|
||||||
@ -70,7 +61,7 @@ function useFetch<R, T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { UseFetchErrored, UseFetchSucced }
|
export type { UseFetchReturn }
|
||||||
|
|
||||||
export default useFetch
|
export default useFetch
|
||||||
|
|
||||||
|
@ -19,7 +19,9 @@ function useStoryDimensions(maxRatio = 16 / 9) {
|
|||||||
return () => window.removeEventListener('resize', handleResize);
|
return () => window.removeEventListener('resize', handleResize);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const height = windowDimensions.height - 56
|
const bottomBarHeight = 56
|
||||||
|
|
||||||
|
const height = windowDimensions.height - bottomBarHeight
|
||||||
|
|
||||||
const ratio = Math.max(maxRatio, height / windowDimensions.width)
|
const ratio = Math.max(maxRatio, height / windowDimensions.width)
|
||||||
|
|
||||||
|
47
front/src/hooks/useStoryIndex.ts
Normal file
47
front/src/hooks/useStoryIndex.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useSearchParams } from 'react-router-dom'
|
||||||
|
import { SetState } from '../utils/types'
|
||||||
|
|
||||||
|
function useStoryIndex(annLength: number | undefined) {
|
||||||
|
const [index, setIndex] = useState(0)
|
||||||
|
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams()
|
||||||
|
|
||||||
|
const withReset = <T>(f: SetState<T>) => (...args: Parameters<SetState<T>>) => {
|
||||||
|
console.log('resetting index')
|
||||||
|
setIndex(0)
|
||||||
|
setSearchParams(prev => ({ ...prev, storyIndex: '0' }), { replace: true })
|
||||||
|
f(...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIndex(annLength ?
|
||||||
|
Number.parseInt(searchParams.get('storyIndex') || '0') :
|
||||||
|
0)
|
||||||
|
// searchParams have actual query string at first render
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [annLength])
|
||||||
|
|
||||||
|
const increment = () => setIndex(prev => {
|
||||||
|
const newIndex = (prev + 1) % (annLength || 1)
|
||||||
|
setSearchParams(prev => ({ ...prev, storyIndex: newIndex.toString() }), { replace: true })
|
||||||
|
|
||||||
|
return newIndex
|
||||||
|
})
|
||||||
|
|
||||||
|
const decrement = () => setIndex(prev => {
|
||||||
|
const newIndex = prev > 0 ? (prev - 1) : 0
|
||||||
|
setSearchParams(prev => ({ ...prev, storyIndex: newIndex.toString() }), { replace: true })
|
||||||
|
|
||||||
|
return newIndex
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
n: index,
|
||||||
|
withReset,
|
||||||
|
increment,
|
||||||
|
decrement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useStoryIndex
|
@ -1,4 +1,4 @@
|
|||||||
import { CSSProperties, useEffect, useState } from 'react'
|
import { CSSProperties, useEffect, useMemo, useState } from 'react'
|
||||||
import Stories from 'react-insta-stories'
|
import Stories from 'react-insta-stories'
|
||||||
import { Story } from 'react-insta-stories/dist/interfaces'
|
import { Story } from 'react-insta-stories/dist/interfaces'
|
||||||
|
|
||||||
@ -10,7 +10,8 @@ import { Announcement } from '../api/announcement/types'
|
|||||||
import { categoryGraphics } from '../assets/category'
|
import { categoryGraphics } from '../assets/category'
|
||||||
|
|
||||||
import puffSpinner from '../assets/puff.svg'
|
import puffSpinner from '../assets/puff.svg'
|
||||||
import { gotError } from '../hooks/useFetch'
|
import { UseFetchReturn, gotError } from '../hooks/useFetch'
|
||||||
|
import useStoryIndex from '../hooks/useStoryIndex'
|
||||||
|
|
||||||
function generateStories(announcements: Announcement[]): Story[] {
|
function generateStories(announcements: Announcement[]): Story[] {
|
||||||
return announcements.map(announcement => {
|
return announcements.map(announcement => {
|
||||||
@ -23,14 +24,14 @@ function generateStories(announcements: Announcement[]): Story[] {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function fallbackGenerateStories(announcementsFetch: ReturnType<typeof useAnnouncements>) {
|
function fallbackGenerateStories(announcements: UseFetchReturn<Announcement[]>) {
|
||||||
if (announcementsFetch.loading)
|
if (announcements.loading)
|
||||||
return fallbackStory()
|
return fallbackStory()
|
||||||
|
|
||||||
if (gotError(announcementsFetch))
|
if (gotError(announcements))
|
||||||
return fallbackStory(announcementsFetch.error, true)
|
return fallbackStory(announcements.error, true)
|
||||||
|
|
||||||
const stories = generateStories(announcementsFetch.data)
|
const stories = generateStories(announcements.data)
|
||||||
|
|
||||||
if (stories.length === 0)
|
if (stories.length === 0)
|
||||||
return fallbackStory('Здесь пока пусто')
|
return fallbackStory('Здесь пока пусто')
|
||||||
@ -68,14 +69,21 @@ function HomePage() {
|
|||||||
const [filterShown, setFilterShown] = useState(false)
|
const [filterShown, setFilterShown] = useState(false)
|
||||||
const [filter, setFilter] = useState(defaultFilters)
|
const [filter, setFilter] = useState(defaultFilters)
|
||||||
|
|
||||||
const announcementsFetch = useAnnouncements(filter)
|
|
||||||
|
|
||||||
const stories = fallbackGenerateStories(announcementsFetch)
|
const announcements = useAnnouncements(filter)
|
||||||
|
|
||||||
|
const stories = useMemo(() => fallbackGenerateStories(announcements), [announcements])
|
||||||
|
|
||||||
|
const index = useStoryIndex(announcements.data?.length)
|
||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
<Filters filter={filter} setFilter={setFilter} filterShown={filterShown} setFilterShown={setFilterShown} />
|
<Filters filter={filter} setFilter={index.withReset(setFilter)} filterShown={filterShown} setFilterShown={setFilterShown} />
|
||||||
<div style={styles.container}>
|
<div style={styles.container}>
|
||||||
<Stories
|
<Stories
|
||||||
|
currentIndex={index.n}
|
||||||
|
onStoryEnd={index.increment}
|
||||||
|
onNext={index.increment}
|
||||||
|
onPrevious={index.decrement}
|
||||||
stories={stories}
|
stories={stories}
|
||||||
defaultInterval={11000}
|
defaultInterval={11000}
|
||||||
height={height}
|
height={height}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user