139 行
3.7 KiB
TypeScript
139 行
3.7 KiB
TypeScript
import axios from 'axios'
|
|
import toCamel from 'camelcase-keys'
|
|
import { useEffect, useState } from 'react'
|
|
import { Helmet } from 'react-helmet-async'
|
|
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'
|
|
|
|
import PostList from '@/components/PostList'
|
|
import TagLink from '@/components/TagLink'
|
|
import WikiBody from '@/components/WikiBody'
|
|
import PageTitle from '@/components/common/PageTitle'
|
|
import TabGroup, { Tab } from '@/components/common/TabGroup'
|
|
import MainArea from '@/components/layout/MainArea'
|
|
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
|
import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
|
|
|
|
import type { Post, Tag, WikiPage } from '@/types'
|
|
|
|
|
|
export default () => {
|
|
const params = useParams ()
|
|
const title = params.title ?? ''
|
|
|
|
const location = useLocation ()
|
|
const navigate = useNavigate ()
|
|
|
|
const defaultTag = { name: title, category: 'general' } as Tag
|
|
|
|
const [posts, setPosts] = useState<Post[]> ([])
|
|
const [tag, setTag] = useState (defaultTag)
|
|
const [wikiPage, setWikiPage] = useState<WikiPage | null | undefined> (undefined)
|
|
|
|
const query = new URLSearchParams (location.search)
|
|
const version = query.get ('version')
|
|
|
|
useEffect (() => {
|
|
if (/^\d+$/.test (title))
|
|
{
|
|
void (async () => {
|
|
const res = await axios.get (`${ API_BASE_URL }/wiki/${ title }`)
|
|
const data = res.data as WikiPage
|
|
navigate (`/wiki/${ data.title }`, { replace: true })
|
|
}) ()
|
|
|
|
return
|
|
}
|
|
|
|
void (async () => {
|
|
try
|
|
{
|
|
const res = await axios.get (
|
|
`${ API_BASE_URL }/wiki/title/${ encodeURIComponent (title) }`,
|
|
{ params: version ? { version } : { } })
|
|
const data = toCamel (res.data as any, { deep: true }) as WikiPage
|
|
setWikiPage (data)
|
|
WikiIdBus.set (data.id)
|
|
}
|
|
catch
|
|
{
|
|
setWikiPage (null)
|
|
}
|
|
}) ()
|
|
|
|
void (async () => {
|
|
try
|
|
{
|
|
const res = await axios.get (
|
|
`${ API_BASE_URL }/posts?${ new URLSearchParams ({ tags: title,
|
|
limit: '8' }) }`)
|
|
const data = toCamel (res.data as any,
|
|
{ deep: true }) as { posts: Post[]
|
|
nextCursor: string }
|
|
setPosts (data.posts)
|
|
}
|
|
catch
|
|
{
|
|
setPosts ([])
|
|
}
|
|
}) ()
|
|
|
|
void (async () => {
|
|
try
|
|
{
|
|
const res = await axios.get (
|
|
`${ API_BASE_URL }/tags/name/${ encodeURIComponent (title) }`)
|
|
setTag (toCamel (res.data as any, { deep: true }) as Tag)
|
|
}
|
|
catch
|
|
{
|
|
setTag (defaultTag)
|
|
}
|
|
}) ()
|
|
|
|
return () => WikiIdBus.set (null)
|
|
}, [title, location.search])
|
|
|
|
return (
|
|
<MainArea>
|
|
<Helmet>
|
|
<title>{`${ title } Wiki | ${ SITE_TITLE }`}</title>
|
|
</Helmet>
|
|
|
|
{(wikiPage && version) && (
|
|
<div className="text-sm flex gap-3 items-center justify-center border border-gray-700 rounded px-2 py-1 mb-4">
|
|
{wikiPage.pred ? (
|
|
<Link to={`/wiki/${ encodeURIComponent (title) }?version=${ wikiPage.pred }`}>
|
|
< 古
|
|
</Link>) : '(最古)'}
|
|
|
|
<span>{wikiPage.updatedAt}</span>
|
|
|
|
{wikiPage.succ ? (
|
|
<Link to={`/wiki/${ encodeURIComponent (title) }?version=${ wikiPage.succ }`}>
|
|
新 >
|
|
</Link>) : '(最新)'}
|
|
</div>)}
|
|
|
|
<PageTitle>
|
|
<TagLink tag={tag}
|
|
withWiki={false}
|
|
withCount={false}
|
|
to={version
|
|
? `/wiki/${ encodeURIComponent (title) }`
|
|
: undefined} />
|
|
</PageTitle>
|
|
<div className="prose mx-auto p-4">
|
|
{wikiPage === undefined
|
|
? 'Loading...'
|
|
: <WikiBody body={wikiPage?.body || `このページは存在しません。[新規作成してください](/wiki/new?title=${ encodeURIComponent (title) })。`} />}
|
|
</div>
|
|
|
|
{(!(version) && posts.length > 0) && (
|
|
<TabGroup>
|
|
<Tab name="広場">
|
|
<PostList posts={posts} />
|
|
</Tab>
|
|
</TabGroup>)}
|
|
</MainArea>)
|
|
}
|