#57 完了
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
import ReactMarkdown from 'react-markdown'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
|
type Props = { body: string }
|
||||||
|
|
||||||
|
|
||||||
|
export default ({ body }: Props) => (
|
||||||
|
<ReactMarkdown components={{ a: (
|
||||||
|
({ href, children }) => (['/', '.'].some (e => href?.startsWith (e))
|
||||||
|
? <Link to={href!}>{children}</Link>
|
||||||
|
: <a href={href} target="_blank" rel="noopener noreferrer">{children}</a>)) }}>
|
||||||
|
{body}
|
||||||
|
</ReactMarkdown>)
|
||||||
@@ -5,7 +5,7 @@ type TabProps = { name: string
|
|||||||
init?: boolean
|
init?: boolean
|
||||||
children: React.ReactNode }
|
children: React.ReactNode }
|
||||||
|
|
||||||
type Props = { children: React.ReactElement<{ name: string }>[] }
|
type Props = { children: React.ReactElement<TabProps>[] }
|
||||||
|
|
||||||
export const Tab = ({ children }: TabProps) => <>{children}</>
|
export const Tab = ({ children }: TabProps) => <>{children}</>
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import toCamel from 'camelcase-keys'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { Helmet } from 'react-helmet'
|
import { Helmet } from 'react-helmet'
|
||||||
import { Link, useLocation } from 'react-router-dom'
|
import { Link, useLocation } from 'react-router-dom'
|
||||||
|
|
||||||
import TagSidebar from '@/components/TagSidebar'
|
import TagSidebar from '@/components/TagSidebar'
|
||||||
|
import WikiBody from '@/components/WikiBody'
|
||||||
|
import TabGroup, { Tab } from '@/components/common/TabGroup'
|
||||||
import MainArea from '@/components/layout/MainArea'
|
import MainArea from '@/components/layout/MainArea'
|
||||||
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
||||||
|
|
||||||
import type { Post, Tag } from '@/types'
|
import type { Post, Tag, WikiPage } from '@/types'
|
||||||
|
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const [posts, setPosts] = useState<Post[]> ([])
|
const [posts, setPosts] = useState<Post[]> ([])
|
||||||
|
const [wikiPage, setWikiPage] = useState<WikiPage | null> (null)
|
||||||
|
|
||||||
const location = useLocation ()
|
const location = useLocation ()
|
||||||
const query = new URLSearchParams (location.search)
|
const query = new URLSearchParams (location.search)
|
||||||
@@ -21,21 +25,20 @@ export default () => {
|
|||||||
const tags = tagsQuery.split (' ').filter (e => e !== '')
|
const tags = tagsQuery.split (' ').filter (e => e !== '')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchPosts = async () => {
|
void (axios.get (`${ API_BASE_URL }/posts`, {
|
||||||
try
|
|
||||||
{
|
|
||||||
const res = await axios.get (`${ API_BASE_URL }/posts`, {
|
|
||||||
params: { tags: tags.join (','),
|
params: { tags: tags.join (','),
|
||||||
match: (anyFlg ? 'any' : 'all') } })
|
match: (anyFlg ? 'any' : 'all') } })
|
||||||
setPosts (res.data)
|
.then (res => setPosts (res.data))
|
||||||
}
|
.catch (err => {
|
||||||
catch (error)
|
console.error ('Failed to fetch posts:', err)
|
||||||
{
|
|
||||||
console.error ('Failed to fetch posts:', error)
|
|
||||||
setPosts ([])
|
setPosts ([])
|
||||||
}
|
}))
|
||||||
}
|
|
||||||
fetchPosts()
|
if (!(tags.length))
|
||||||
|
return
|
||||||
|
void (axios.get (`${ API_BASE_URL }/wiki/title/${ encodeURIComponent (tags.join (' ')) }`)
|
||||||
|
.then (res => setWikiPage (toCamel (res.data, { deep: true })))
|
||||||
|
.catch (() => setWikiPage (null)))
|
||||||
}, [location.search])
|
}, [location.search])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -49,6 +52,10 @@ export default () => {
|
|||||||
</Helmet>
|
</Helmet>
|
||||||
<TagSidebar posts={posts} />
|
<TagSidebar posts={posts} />
|
||||||
<MainArea>
|
<MainArea>
|
||||||
|
<TabGroup key={wikiPage}>
|
||||||
|
<Tab name="広場">
|
||||||
|
{posts.length
|
||||||
|
? (
|
||||||
<div className="flex flex-wrap gap-4 p-4">
|
<div className="flex flex-wrap gap-4 p-4">
|
||||||
{posts.map (post => (
|
{posts.map (post => (
|
||||||
<Link to={`/posts/${ post.id }`}
|
<Link to={`/posts/${ post.id }`}
|
||||||
@@ -58,7 +65,17 @@ export default () => {
|
|||||||
className="object-none w-full h-full" />
|
className="object-none w-full h-full" />
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
|
</div>)
|
||||||
|
: '広場には何もありませんよ.'}
|
||||||
|
</Tab>
|
||||||
|
{(wikiPage && wikiPage.body) && (
|
||||||
|
<Tab name="Wiki" init={!(posts.length)}>
|
||||||
|
<WikiBody body={wikiPage.body} />
|
||||||
|
<div className="my-2">
|
||||||
|
<Link to={`/wiki/${ wikiPage.title }`}>Wiki を見る</Link>
|
||||||
</div>
|
</div>
|
||||||
|
</Tab>)}
|
||||||
|
</TabGroup>
|
||||||
</MainArea>
|
</MainArea>
|
||||||
</>)
|
</>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import axios from 'axios'
|
|||||||
import toCamel from 'camelcase-keys'
|
import toCamel from 'camelcase-keys'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { Helmet } from 'react-helmet'
|
import { Helmet } from 'react-helmet'
|
||||||
import ReactMarkdown from 'react-markdown'
|
|
||||||
import { Link, useLocation, useParams, useNavigate } from 'react-router-dom'
|
import { Link, useLocation, useParams, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
|
import WikiBody from '@/components/WikiBody'
|
||||||
import PageTitle from '@/components/common/PageTitle'
|
import PageTitle from '@/components/common/PageTitle'
|
||||||
import MainArea from '@/components/layout/MainArea'
|
import MainArea from '@/components/layout/MainArea'
|
||||||
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
||||||
@@ -61,15 +61,9 @@ export default () => {
|
|||||||
</div>)}
|
</div>)}
|
||||||
<PageTitle>{title}</PageTitle>
|
<PageTitle>{title}</PageTitle>
|
||||||
<div className="prose mx-auto p-4">
|
<div className="prose mx-auto p-4">
|
||||||
{wikiPage === undefined ? 'Loading...' : (
|
{wikiPage === undefined
|
||||||
<>
|
? 'Loading...'
|
||||||
<ReactMarkdown components={{ a: (
|
: <WikiBody body={wikiPage?.body || `このページは存在しません。[新規作成してください](/wiki/new?title=${ title })。`} />}
|
||||||
({ href, children }) => (['/', '.'].some (e => href?.startsWith (e))
|
|
||||||
? <Link to={href!}>{children}</Link>
|
|
||||||
: <a href={href} target="_blank" rel="noopener noreferrer">{children}</a>)) }}>
|
|
||||||
{wikiPage?.body || `このページは存在しません。[新規作成してください](/wiki/new?title=${ title })。`}
|
|
||||||
</ReactMarkdown>
|
|
||||||
</>)}
|
|
||||||
</div>
|
</div>
|
||||||
</MainArea>)
|
</MainArea>)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user