diff --git a/front/src/hooks/index.ts b/front/src/hooks/index.ts index e1c5fa4..2e5d398 100644 --- a/front/src/hooks/index.ts +++ b/front/src/hooks/index.ts @@ -1,3 +1,4 @@ export { default as useStoryDimensions } from './useStoryDimensions' export { default as useSend } from './useSend' export { default as useFetch } from './useFetch' +export { default as UseStoryIndex } from './useStoryIndex' diff --git a/front/src/hooks/useStoryIndex.ts b/front/src/hooks/useStoryIndex.ts new file mode 100644 index 0000000..cff4630 --- /dev/null +++ b/front/src/hooks/useStoryIndex.ts @@ -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 = (f: SetState) => (...args: Parameters>) => { + 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 diff --git a/front/src/pages/HomePage.tsx b/front/src/pages/HomePage.tsx index 9ac9435..2c4d36d 100644 --- a/front/src/pages/HomePage.tsx +++ b/front/src/pages/HomePage.tsx @@ -1,4 +1,4 @@ -import { CSSProperties, useEffect, useState } from 'react' +import { CSSProperties, useEffect, useMemo, useState } from 'react' import Stories from 'react-insta-stories' import { Story } from 'react-insta-stories/dist/interfaces' @@ -10,7 +10,8 @@ import { Announcement } from '../api/announcement/types' import { categoryGraphics } from '../assets/category' 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[] { return announcements.map(announcement => { @@ -23,14 +24,14 @@ function generateStories(announcements: Announcement[]): Story[] { }) } -function fallbackGenerateStories(announcementsFetch: ReturnType) { - if (announcementsFetch.loading) +function fallbackGenerateStories(announcements: UseFetchReturn) { + if (announcements.loading) return fallbackStory() - if (gotError(announcementsFetch)) - return fallbackStory(announcementsFetch.error, true) + if (gotError(announcements)) + return fallbackStory(announcements.error, true) - const stories = generateStories(announcementsFetch.data) + const stories = generateStories(announcements.data) if (stories.length === 0) return fallbackStory('Здесь пока пусто') @@ -68,14 +69,21 @@ function HomePage() { const [filterShown, setFilterShown] = useState(false) 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 (<> - +