|
|
|
@@ -7,6 +7,7 @@ import { Link, useLocation, useNavigationType } from 'react-router-dom' |
|
|
|
import PostList from '@/components/PostList' |
|
|
|
import TagSidebar from '@/components/TagSidebar' |
|
|
|
import WikiBody from '@/components/WikiBody' |
|
|
|
import Pagination from '@/components/common/Pagination' |
|
|
|
import TabGroup, { Tab } from '@/components/common/TabGroup' |
|
|
|
import MainArea from '@/components/layout/MainArea' |
|
|
|
import { API_BASE_URL, SITE_TITLE } from '@/config' |
|
|
|
@@ -23,6 +24,7 @@ export default () => { |
|
|
|
const [cursor, setCursor] = useState ('') |
|
|
|
const [loading, setLoading] = useState (false) |
|
|
|
const [posts, setPosts] = useState<Post[]> ([]) |
|
|
|
const [totalPages, setTotalPages] = useState (0) |
|
|
|
const [wikiPage, setWikiPage] = useState<WikiPage | null> (null) |
|
|
|
|
|
|
|
const loadMore = async (withCursor: boolean) => { |
|
|
|
@@ -31,15 +33,19 @@ export default () => { |
|
|
|
const res = await axios.get (`${ API_BASE_URL }/posts`, { |
|
|
|
params: { tags: tags.join (' '), |
|
|
|
match: anyFlg ? 'any' : 'all', |
|
|
|
limit: '20', |
|
|
|
...(page && { page }), |
|
|
|
...(limit && { limit }), |
|
|
|
...(withCursor && { cursor }) } }) |
|
|
|
const data = toCamel (res.data as any, { deep: true }) as { posts: Post[] |
|
|
|
nextCursor: string } |
|
|
|
const data = toCamel (res.data as any, { deep: true }) as { |
|
|
|
posts: Post[] |
|
|
|
count: number |
|
|
|
nextCursor: string } |
|
|
|
setPosts (posts => ( |
|
|
|
[...((new Map ([...(withCursor ? posts : []), ...data.posts] |
|
|
|
.map (post => [post.id, post]))) |
|
|
|
.values ())])) |
|
|
|
setCursor (data.nextCursor) |
|
|
|
setTotalPages (Math.ceil (data.count / limit)) |
|
|
|
|
|
|
|
setLoading (false) |
|
|
|
} |
|
|
|
@@ -49,6 +55,8 @@ export default () => { |
|
|
|
const tagsQuery = query.get ('tags') ?? '' |
|
|
|
const anyFlg = query.get ('match') === 'any' |
|
|
|
const tags = tagsQuery.split (' ').filter (e => e !== '') |
|
|
|
const page = Number (query.get ('page') ?? 1) |
|
|
|
const limit = Number (query.get ('limit') ?? 20) |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
const observer = new IntersectionObserver (entries => { |
|
|
|
@@ -65,7 +73,8 @@ export default () => { |
|
|
|
}, [loaderRef, loading]) |
|
|
|
|
|
|
|
useLayoutEffect (() => { |
|
|
|
const savedState = sessionStorage.getItem (`posts:${ tagsQuery }`) |
|
|
|
// TODO: 無限ロード用 |
|
|
|
const savedState = /* sessionStorage.getItem (`posts:${ tagsQuery }`) */ null |
|
|
|
if (savedState && navigationType === 'POP') |
|
|
|
{ |
|
|
|
const { posts, cursor, scroll } = JSON.parse (savedState) |
|
|
|
@@ -116,18 +125,23 @@ export default () => { |
|
|
|
<MainArea> |
|
|
|
<TabGroup> |
|
|
|
<Tab name="広場"> |
|
|
|
{posts.length |
|
|
|
{posts.length > 0 |
|
|
|
? ( |
|
|
|
<PostList posts={posts} onClick={() => { |
|
|
|
const statesToSave = { |
|
|
|
posts, cursor, |
|
|
|
scroll: containerRef.current?.scrollTop ?? 0 } |
|
|
|
sessionStorage.setItem (`posts:${ tagsQuery }`, |
|
|
|
JSON.stringify (statesToSave)) |
|
|
|
}}/>) |
|
|
|
<> |
|
|
|
<PostList posts={posts} onClick={() => { |
|
|
|
// TODO: 無限ロード用なので復活時に戻す. |
|
|
|
// const statesToSave = { |
|
|
|
// posts, cursor, |
|
|
|
// scroll: containerRef.current?.scrollTop ?? 0 } |
|
|
|
// sessionStorage.setItem (`posts:${ tagsQuery }`, |
|
|
|
// JSON.stringify (statesToSave)) |
|
|
|
}}/> |
|
|
|
<Pagination page={page} totalPages={totalPages}/> |
|
|
|
</>) |
|
|
|
: !(loading) && '広場には何もありませんよ.'} |
|
|
|
{loading && 'Loading...'} |
|
|
|
<div ref={loaderRef} className="h-12"/> |
|
|
|
{/* TODO: 無限ローディング復活までコメント・アウト */} |
|
|
|
{/* <div ref={loaderRef} className="h-12"/> */} |
|
|
|
</Tab> |
|
|
|
{tags.length === 1 && ( |
|
|
|
<Tab name="Wiki"> |
|
|
|
|