ぼざクリタグ広場 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.
 
 
 
 
 
 

123 lines
3.7 KiB

  1. import { useQuery } from '@tanstack/react-query'
  2. import { useEffect, useMemo } from 'react'
  3. import { Helmet } from 'react-helmet-async'
  4. import { useLocation, useNavigate, useParams } from 'react-router-dom'
  5. import PostList from '@/components/PostList'
  6. import PrefetchLink from '@/components/PrefetchLink'
  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 { SITE_TITLE } from '@/config'
  13. import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
  14. import { fetchPosts } from '@/lib/posts'
  15. import { postsKeys, tagsKeys, wikiKeys } from '@/lib/queryKeys'
  16. import { fetchTagByName } from '@/lib/tags'
  17. import { fetchWikiPage, fetchWikiPageByTitle } from '@/lib/wiki'
  18. import type { Tag } from '@/types'
  19. export default () => {
  20. const params = useParams ()
  21. const title = params.title ?? ''
  22. const location = useLocation ()
  23. const navigate = useNavigate ()
  24. const defaultTag = useMemo (() => ({ name: title, category: 'general' } as Tag), [title])
  25. const query = new URLSearchParams (location.search)
  26. const version = query.get ('version') || undefined
  27. const { data: wikiPage, isLoading: loading } = useQuery ({
  28. enabled: Boolean (title) && !(/^\d+$/.test (title)),
  29. queryKey: wikiKeys.show (title, { version }),
  30. queryFn: () => fetchWikiPageByTitle (title, { version }) })
  31. const effectiveTitle = wikiPage?.title ?? title
  32. const { data: tag } = useQuery ({
  33. enabled: Boolean (effectiveTitle),
  34. queryKey: tagsKeys.show (effectiveTitle),
  35. queryFn: () => fetchTagByName (effectiveTitle) })
  36. const { data } = useQuery ({
  37. enabled: Boolean (effectiveTitle) && !(version),
  38. queryKey: postsKeys.index ({ tags: effectiveTitle, match: 'all', page: 1, limit: 8 }),
  39. queryFn: () => fetchPosts ({ tags: effectiveTitle, match: 'all', page: 1, limit: 8 }) })
  40. const posts = data?.posts || []
  41. useEffect (() => {
  42. if (!(wikiPage))
  43. return
  44. WikiIdBus.set (wikiPage.id)
  45. if (wikiPage.title !== title)
  46. navigate (`/wiki/${ encodeURIComponent(wikiPage.title) }`, { replace: true })
  47. return () => WikiIdBus.set (null)
  48. }, [wikiPage, title, navigate])
  49. useEffect (() => {
  50. if (!(/^\d+$/.test (title)))
  51. return
  52. void (async () => {
  53. try
  54. {
  55. const data = await fetchWikiPage (title, { })
  56. navigate (`/wiki/${ encodeURIComponent(data.title) }`, { replace: true })
  57. }
  58. catch
  59. {
  60. ;
  61. }
  62. }) ()
  63. }, [title, navigate])
  64. return (
  65. <MainArea>
  66. <Helmet>
  67. <title>{`${ title } Wiki | ${ SITE_TITLE }`}</title>
  68. {!(wikiPage?.body) && <meta name="robots" content="noindex"/>}
  69. </Helmet>
  70. {(wikiPage && version) && (
  71. <div className="text-sm flex gap-3 items-center justify-center
  72. border border-gray-700 rounded px-2 py-1 mb-4">
  73. {wikiPage.pred ? (
  74. <PrefetchLink to={`/wiki/${ encodeURIComponent (title) }?version=${ wikiPage.pred }`}>
  75. &lt; 古
  76. </PrefetchLink>) : '(最古)'}
  77. <span>{wikiPage.updatedAt}</span>
  78. {wikiPage.succ ? (
  79. <PrefetchLink to={`/wiki/${ encodeURIComponent (title) }?version=${ wikiPage.succ }`}>
  80. 新 &gt;
  81. </PrefetchLink>) : '(最新)'}
  82. </div>)}
  83. <PageTitle>
  84. <TagLink tag={tag ?? defaultTag}
  85. withWiki={false}
  86. withCount={false}
  87. {...(version && { to: `/wiki/${ encodeURIComponent (title) }` })}/>
  88. </PageTitle>
  89. <div className="prose mx-auto p-4">
  90. {loading ? 'Loading...' : <WikiBody title={title} body={wikiPage?.body}/>}
  91. </div>
  92. {(!(version) && posts.length > 0) && (
  93. <TabGroup>
  94. <Tab name="広場">
  95. <PostList posts={posts}/>
  96. </Tab>
  97. </TabGroup>)}
  98. </MainArea>)
  99. }