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

125 lines
3.9 KiB

  1. import { AnimatePresence, LayoutGroup } from 'framer-motion'
  2. import { useEffect, useState } from 'react'
  3. import { BrowserRouter,
  4. Navigate,
  5. Route,
  6. Routes,
  7. useLocation } from 'react-router-dom'
  8. import RouteBlockerOverlay from '@/components/RouteBlockerOverlay'
  9. import TopNav from '@/components/TopNav'
  10. import { Toaster } from '@/components/ui/toaster'
  11. import { apiPost, isApiError } from '@/lib/api'
  12. import NicoTagListPage from '@/pages/tags/NicoTagListPage'
  13. import NotFound from '@/pages/NotFound'
  14. import PostDetailPage from '@/pages/posts/PostDetailPage'
  15. import PostHistoryPage from '@/pages/posts/PostHistoryPage'
  16. import PostListPage from '@/pages/posts/PostListPage'
  17. import PostNewPage from '@/pages/posts/PostNewPage'
  18. import ServiceUnavailable from '@/pages/ServiceUnavailable'
  19. import SettingPage from '@/pages/users/SettingPage'
  20. import WikiDetailPage from '@/pages/wiki/WikiDetailPage'
  21. import WikiDiffPage from '@/pages/wiki/WikiDiffPage'
  22. import WikiEditPage from '@/pages/wiki/WikiEditPage'
  23. import WikiHistoryPage from '@/pages/wiki/WikiHistoryPage'
  24. import WikiNewPage from '@/pages/wiki/WikiNewPage'
  25. import WikiSearchPage from '@/pages/wiki/WikiSearchPage'
  26. import type { Dispatch, FC, SetStateAction } from 'react'
  27. import type { User } from '@/types'
  28. const RouteTransitionWrapper = ({ user, setUser }: {
  29. user: User | null
  30. setUser: Dispatch<SetStateAction<User | null>> }) => {
  31. const location = useLocation ()
  32. return (
  33. <LayoutGroup id="gallery-shared">
  34. <AnimatePresence mode="wait">
  35. <Routes location={location} key={location.pathname}>
  36. <Route path="/" element={<Navigate to="/posts" replace/>}/>
  37. <Route path="/posts" element={<PostListPage/>}/>
  38. <Route path="/posts/new" element={<PostNewPage user={user}/>}/>
  39. <Route path="/posts/:id" element={<PostDetailRoute user={user}/>}/>
  40. <Route path="/posts/changes" element={<PostHistoryPage/>}/>
  41. <Route path="/tags/nico" element={<NicoTagListPage user={user}/>}/>
  42. <Route path="/wiki" element={<WikiSearchPage/>}/>
  43. <Route path="/wiki/:title" element={<WikiDetailPage/>}/>
  44. <Route path="/wiki/new" element={<WikiNewPage user={user}/>}/>
  45. <Route path="/wiki/:id/edit" element={<WikiEditPage user={user}/>}/>
  46. <Route path="/wiki/:id/diff" element={<WikiDiffPage/>}/>
  47. <Route path="/wiki/changes" element={<WikiHistoryPage/>}/>
  48. <Route path="/users/settings" element={<SettingPage user={user} setUser={setUser}/>}/>
  49. <Route path="/settings" element={<Navigate to="/users/settings" replace/>}/>
  50. <Route path="*" element={<NotFound/>}/>
  51. </Routes>
  52. </AnimatePresence>
  53. </LayoutGroup>)
  54. }
  55. const PostDetailRoute = ({ user }: { user: User | null }) => {
  56. const location = useLocation ()
  57. const key = location.pathname
  58. return <PostDetailPage key={key} user={user}/>
  59. }
  60. export default (() => {
  61. const [user, setUser] = useState<User | null> (null)
  62. const [status, setStatus] = useState (200)
  63. useEffect (() => {
  64. const createUser = async () => {
  65. const data = await apiPost<{ code: string; user: User }> ('/users')
  66. if (data.code)
  67. {
  68. localStorage.setItem ('user_code', data.code)
  69. setUser (data.user)
  70. }
  71. }
  72. const code = localStorage.getItem ('user_code')
  73. if (code)
  74. {
  75. void (async () => {
  76. try
  77. {
  78. const data = await apiPost<{ valid: boolean; user: User }> ('/users/verify', { code })
  79. if (data.valid)
  80. setUser (data.user)
  81. else
  82. await createUser ()
  83. }
  84. catch (err)
  85. {
  86. if (isApiError (err))
  87. setStatus (err.response?.status ?? 200)
  88. }
  89. }) ()
  90. }
  91. else
  92. createUser ()
  93. }, [])
  94. switch (status)
  95. {
  96. case 503:
  97. return <ServiceUnavailable/>
  98. }
  99. return (
  100. <>
  101. <RouteBlockerOverlay/>
  102. <BrowserRouter>
  103. <div className="flex flex-col h-screen w-screen">
  104. <TopNav user={user}/>
  105. <RouteTransitionWrapper user={user} setUser={setUser}/>
  106. </div>
  107. <Toaster/>
  108. </BrowserRouter>
  109. </>)
  110. }) satisfies FC