|
1 | | -import { BrowserRouter, Outlet, Route, Routes } from "react-router"; |
| 1 | +import { BrowserRouter, Navigate, Outlet, Route, Routes, useParams } from "react-router"; |
2 | 2 | import SubmissionPage from "./pages/eventId/Submission.tsx"; |
3 | 3 | import HomePage from "./pages/Home.tsx"; |
4 | 4 | import LandingPage from "./pages/Landing.tsx"; |
5 | 5 | import NotFoundPage from "./pages/NotFound.tsx"; |
6 | 6 | import ProjectPage from "./pages/Project.tsx"; |
7 | 7 |
|
| 8 | +/** |
| 9 | + * Nano ID 形式の正規表現。 |
| 10 | + * 現在はハイフン・アンダースコアを含まないが、初期は含んでいたため URL の検証時は両方許容する。 |
| 11 | + */ |
| 12 | +const NANOID_REGEX = /^[A-Za-z0-9_-]{21}$/; |
| 13 | + |
| 14 | +/** |
| 15 | + * 旧パス /:eventId から新パス /e/:eventId へのリダイレクト。eventId は Nano ID 形式。 |
| 16 | + */ |
| 17 | +function LegacyEventRedirect() { |
| 18 | + const { eventId } = useParams(); |
| 19 | + if (!eventId || !NANOID_REGEX.test(eventId)) { |
| 20 | + return <NotFoundPage />; |
| 21 | + } |
| 22 | + return <Navigate to={`/e/${eventId}`} replace />; |
| 23 | +} |
| 24 | + |
| 25 | +/** |
| 26 | + * 旧パス /:eventId/edit から新パス /e/:eventId/edit へのリダイレクト。eventId は Nano ID 形式。 |
| 27 | + */ |
| 28 | +function LegacyEventEditRedirect() { |
| 29 | + const { eventId } = useParams(); |
| 30 | + if (!eventId || !NANOID_REGEX.test(eventId)) { |
| 31 | + return <NotFoundPage />; |
| 32 | + } |
| 33 | + return <Navigate to={`/e/${eventId}/edit`} replace />; |
| 34 | +} |
| 35 | + |
8 | 36 | export default function App() { |
9 | 37 | return ( |
10 | 38 | <BrowserRouter> |
11 | 39 | <Routes> |
12 | 40 | <Route index element={<LandingPage />} /> |
13 | 41 | <Route path="home" element={<HomePage />} /> |
14 | 42 | <Route path="new" element={<ProjectPage />} /> |
15 | | - <Route path=":eventId" element={<Outlet />}> |
16 | | - <Route index element={<SubmissionPage />} /> |
17 | | - <Route path="edit" element={<ProjectPage />} /> |
18 | | - <Route path="*" element={<NotFoundPage />} /> |
| 43 | + |
| 44 | + <Route path="e"> |
| 45 | + <Route path=":eventId" element={<Outlet />}> |
| 46 | + <Route index element={<SubmissionPage />} /> |
| 47 | + <Route path="edit" element={<ProjectPage />} /> |
| 48 | + <Route path="*" element={<NotFoundPage />} /> |
| 49 | + </Route> |
19 | 50 | </Route> |
| 51 | + |
| 52 | + {/* /:eventId (旧形式) を /e/:eventId (新形式) にリダイレクト */} |
| 53 | + <Route path=":eventId" element={<LegacyEventRedirect />} /> |
| 54 | + <Route path=":eventId/edit" element={<LegacyEventEditRedirect />} /> |
| 55 | + |
20 | 56 | <Route path="*" element={<NotFoundPage />} /> |
21 | 57 | </Routes> |
22 | 58 | </BrowserRouter> |
|
0 commit comments