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

118 lines
3.8 KiB

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