|
- 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 { data, isLoading: loading } = useQuery ({
- queryKey: postsKeys.index ({ tags: tagsKey, match, page, limit }),
- queryFn: () => fetchPosts ({ tags: tagsKey, match, page, limit }) })
- 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" 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
|