Files
btrc-hub/frontend/src/pages/posts/PostListPage.tsx
T
みてるぞ e72ec608f4 利用規約(#95) (#311)
#95

#95

#95

#95

#95

Merge remote-tracking branch 'origin/main' into feature/095

#95

#95

#95

Co-authored-by: miteruzo <miteruzo@naver.com>
Reviewed-on: #311
2026-04-14 12:31:48 +09:00

116 lines
3.3 KiB
TypeScript

import { useQuery } from '@tanstack/react-query'
import { useLayoutEffect, useRef, useState } from 'react'
import { Helmet } from 'react-helmet-async'
import { useLocation } from 'react-router-dom'
import PostList from '@/components/PostList'
import PrefetchLink from '@/components/PrefetchLink'
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 { SITE_TITLE } from '@/config'
import { fetchPosts } from '@/lib/posts'
import { postsKeys } from '@/lib/queryKeys'
import { fetchWikiPageByTitle } from '@/lib/wiki'
import type { FC } from 'react'
import type { WikiPage } from '@/types'
export default (() => {
const containerRef = useRef<HTMLDivElement | null> (null)
const [wikiPage, setWikiPage] = useState<WikiPage | null> (null)
const location = useLocation ()
const query = new URLSearchParams (location.search)
const tagsQuery = query.get ('tags') ?? ''
const anyFlg = query.get ('match') === 'any'
const match = anyFlg ? 'any' : 'all'
const tags = tagsQuery.split (' ').filter (e => e !== '')
const tagsKey = tags.join (' ')
const page = Number (query.get ('page') ?? 1)
const limit = Number (query.get ('limit') ?? 20)
const keys = {
tags: tagsKey, match, page, limit,
url: '', title: '', originalCreatedFrom: '', originalCreatedTo: '',
createdFrom: '', createdTo: '', updatedFrom: '', updatedTo: '',
order: 'original_created_at:desc' } as const
const { data, isLoading: loading } = useQuery ({
queryKey: postsKeys.index (keys),
queryFn: () => fetchPosts (keys) })
const posts = data?.posts ?? []
const cursor = ''
const totalPages = data ? Math.ceil (data.count / limit) : 0
useLayoutEffect (() => {
scroll (0, 0)
setWikiPage (null)
if (tags.length !== 1)
return
void (async () => {
try
{
const tagName = tags[0]
setWikiPage (await fetchWikiPageByTitle (tagName, { }))
}
catch
{
;
}
}) ()
}, [location.search])
return (
<div
className="md:flex md:flex-1 overflow-y-auto md:overflow-y-hidden"
ref={containerRef}>
<Helmet>
<title>
{tags.length
? `${ tags.join (anyFlg ? ' or ' : ' and ') } | ${ SITE_TITLE }`
: `${ SITE_TITLE } 〜 ぼざろクリーチャーシリーズ綜合リンク集サイト`}
</title>
</Helmet>
<TagSidebar posts={posts.slice (0, 20)} onClick={() => {
const statesToSave = {
posts, cursor,
scroll: containerRef.current?.scrollTop ?? 0 }
sessionStorage.setItem (`posts:${ tagsQuery }`,
JSON.stringify (statesToSave))
}}/>
<MainArea>
<TabGroup>
<Tab name="広場">
{posts.length > 0
? (
<>
<PostList posts={posts}/>
<Pagination page={page} totalPages={totalPages}/>
</>)
: !(loading) && '広場には何もありませんよ.'}
{loading && 'Loading...'}
</Tab>
{tags.length === 1 && (
<Tab name="Wiki">
<WikiBody title={tags[0]} body={wikiPage?.body}/>
<div className="my-2">
<PrefetchLink to={`/wiki/${ encodeURIComponent (tags[0]) }`}>
Wiki
</PrefetchLink>
</div>
</Tab>)}
</TabGroup>
</MainArea>
</div>)
}) satisfies FC