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

128 lines
3.9 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 keys = {
  37. tags: effectiveTitle, match: 'all', page: 1, limit: 8, url: '', title: '',
  38. originalCreatedFrom: '', originalCreatedTo: '',
  39. createdFrom: '', createdTo: '', updatedFrom: '', updatedTo: '',
  40. order: 'original_created_at:desc' } as const
  41. const { data } = useQuery ({
  42. enabled: Boolean (effectiveTitle) && !(version),
  43. queryKey: postsKeys.index (keys),
  44. queryFn: () => fetchPosts (keys) })
  45. const posts = data?.posts || []
  46. useEffect (() => {
  47. if (!(wikiPage))
  48. return
  49. WikiIdBus.set (wikiPage.id)
  50. if (wikiPage.title !== title)
  51. navigate (`/wiki/${ encodeURIComponent(wikiPage.title) }`, { replace: true })
  52. return () => WikiIdBus.set (null)
  53. }, [wikiPage, title, navigate])
  54. useEffect (() => {
  55. if (!(/^\d+$/.test (title)))
  56. return
  57. void (async () => {
  58. try
  59. {
  60. const data = await fetchWikiPage (title, { })
  61. navigate (`/wiki/${ encodeURIComponent(data.title) }`, { replace: true })
  62. }
  63. catch
  64. {
  65. ;
  66. }
  67. }) ()
  68. }, [title, navigate])
  69. return (
  70. <MainArea>
  71. <Helmet>
  72. <title>{`${ title } Wiki | ${ SITE_TITLE }`}</title>
  73. {!(wikiPage?.body) && <meta name="robots" content="noindex"/>}
  74. </Helmet>
  75. {(wikiPage && version) && (
  76. <div className="text-sm flex gap-3 items-center justify-center
  77. border border-gray-700 rounded px-2 py-1 mb-4">
  78. {wikiPage.pred ? (
  79. <PrefetchLink to={`/wiki/${ encodeURIComponent (title) }?version=${ wikiPage.pred }`}>
  80. &lt; 古
  81. </PrefetchLink>) : '(最古)'}
  82. <span>{wikiPage.updatedAt}</span>
  83. {wikiPage.succ ? (
  84. <PrefetchLink to={`/wiki/${ encodeURIComponent (title) }?version=${ wikiPage.succ }`}>
  85. 新 &gt;
  86. </PrefetchLink>) : '(最新)'}
  87. </div>)}
  88. <PageTitle>
  89. <TagLink tag={tag ?? defaultTag}
  90. withWiki={false}
  91. withCount={false}
  92. {...(version && { to: `/wiki/${ encodeURIComponent (title) }` })}/>
  93. </PageTitle>
  94. <div className="prose mx-auto p-4">
  95. {loading ? 'Loading...' : <WikiBody title={title} body={wikiPage?.body}/>}
  96. </div>
  97. {(!(version) && posts.length > 0) && (
  98. <TabGroup>
  99. <Tab name="広場">
  100. <PostList posts={posts}/>
  101. </Tab>
  102. </TabGroup>)}
  103. </MainArea>)
  104. }