ぼざクリタグ広場 https://hub.nizika.monster
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

148 lines
3.8 KiB

  1. import axios from 'axios'
  2. import toCamel from 'camelcase-keys'
  3. import { useEffect, useState } from 'react'
  4. import { Helmet } from 'react-helmet-async'
  5. import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'
  6. import PostList from '@/components/PostList'
  7. import TagLink from '@/components/TagLink'
  8. import WikiBody from '@/components/WikiBody'
  9. import PageTitle from '@/components/common/PageTitle'
  10. import TabGroup, { Tab } from '@/components/common/TabGroup'
  11. import MainArea from '@/components/layout/MainArea'
  12. import { API_BASE_URL, SITE_TITLE } from '@/config'
  13. import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
  14. import type { Post, Tag, WikiPage } from '@/types'
  15. export default () => {
  16. const params = useParams ()
  17. const title = params.title ?? ''
  18. const location = useLocation ()
  19. const navigate = useNavigate ()
  20. const defaultTag = { name: title, category: 'general' } as Tag
  21. const [posts, setPosts] = useState<Post[]> ([])
  22. const [tag, setTag] = useState (defaultTag)
  23. const [wikiPage, setWikiPage] = useState<WikiPage | null | undefined> (undefined)
  24. const query = new URLSearchParams (location.search)
  25. const version = query.get ('version')
  26. useEffect (() => {
  27. if (/^\d+$/.test (title))
  28. {
  29. void (async () => {
  30. try
  31. {
  32. const res = await axios.get (`${ API_BASE_URL }/wiki/${ title }`)
  33. const data = res.data as WikiPage
  34. navigate (`/wiki/${ encodeURIComponent(data.title) }`, { replace: true })
  35. }
  36. catch
  37. {
  38. ;
  39. }
  40. }) ()
  41. return
  42. }
  43. void (async () => {
  44. try
  45. {
  46. const res = await axios.get (
  47. `${ API_BASE_URL }/wiki/title/${ encodeURIComponent (title) }`,
  48. { params: version ? { version } : { } })
  49. const data = toCamel (res.data as any, { deep: true }) as WikiPage
  50. if (data.title !== title)
  51. navigate (`/wiki/${ encodeURIComponent(data.title) }`, { replace: true })
  52. setWikiPage (data)
  53. WikiIdBus.set (data.id)
  54. }
  55. catch
  56. {
  57. setWikiPage (null)
  58. }
  59. }) ()
  60. setPosts ([])
  61. void (async () => {
  62. try
  63. {
  64. const res = await axios.get (
  65. `${ API_BASE_URL }/posts?${ new URLSearchParams ({ tags: title,
  66. limit: '8' }) }`)
  67. const data = toCamel (res.data as any,
  68. { deep: true }) as { posts: Post[]
  69. nextCursor: string }
  70. setPosts (data.posts)
  71. }
  72. catch
  73. {
  74. ;
  75. }
  76. }) ()
  77. void (async () => {
  78. try
  79. {
  80. const res = await axios.get (
  81. `${ API_BASE_URL }/tags/name/${ encodeURIComponent (title) }`)
  82. setTag (toCamel (res.data as any, { deep: true }) as Tag)
  83. }
  84. catch
  85. {
  86. setTag (defaultTag)
  87. }
  88. }) ()
  89. return () => WikiIdBus.set (null)
  90. }, [title, location.search])
  91. return (
  92. <MainArea>
  93. <Helmet>
  94. <title>{`${ title } Wiki | ${ SITE_TITLE }`}</title>
  95. {!(wikiPage?.body) && <meta name="robots" content="noindex"/>}
  96. </Helmet>
  97. {(wikiPage && version) && (
  98. <div className="text-sm flex gap-3 items-center justify-center border border-gray-700 rounded px-2 py-1 mb-4">
  99. {wikiPage.pred ? (
  100. <Link to={`/wiki/${ encodeURIComponent (title) }?version=${ wikiPage.pred }`}>
  101. &lt; 古
  102. </Link>) : '(最古)'}
  103. <span>{wikiPage.updatedAt}</span>
  104. {wikiPage.succ ? (
  105. <Link to={`/wiki/${ encodeURIComponent (title) }?version=${ wikiPage.succ }`}>
  106. 新 &gt;
  107. </Link>) : '(最新)'}
  108. </div>)}
  109. <PageTitle>
  110. <TagLink tag={tag}
  111. withWiki={false}
  112. withCount={false}
  113. {...(version && { to: `/wiki/${ encodeURIComponent (title) }` })}/>
  114. </PageTitle>
  115. <div className="prose mx-auto p-4">
  116. {wikiPage === undefined
  117. ? 'Loading...'
  118. : <WikiBody title={title} body={wikiPage?.body}/>}
  119. </div>
  120. {(!(version) && posts.length > 0) && (
  121. <TabGroup>
  122. <Tab name="広場">
  123. <PostList posts={posts}/>
  124. </Tab>
  125. </TabGroup>)}
  126. </MainArea>)
  127. }