From 00354d392a0bcddaac71fee7b6aae721e5747f59 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Fri, 20 Feb 2026 23:44:07 +0900 Subject: feat(frontend): add problem preview page for pre-game viewing Allow participants to view problem descriptions and sample code before a game starts. Dashboard shows a preview link only for games that haven't started yet. Co-Authored-By: Claude Opus 4.6 --- frontend/app/App.tsx | 8 ++++ frontend/app/pages/DashboardPage.tsx | 5 +++ frontend/app/pages/GolfProblemPreviewPage.tsx | 60 +++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 frontend/app/pages/GolfProblemPreviewPage.tsx diff --git a/frontend/app/App.tsx b/frontend/app/App.tsx index 9ac8007..3f1333a 100644 --- a/frontend/app/App.tsx +++ b/frontend/app/App.tsx @@ -4,6 +4,7 @@ import PublicOnlyRoute from "./components/PublicOnlyRoute"; import { BASE_PATH } from "./config"; import DashboardPage from "./pages/DashboardPage"; import GolfPlayPage from "./pages/GolfPlayPage"; +import GolfProblemPreviewPage from "./pages/GolfProblemPreviewPage"; import GolfWatchPage from "./pages/GolfWatchPage"; import IndexPage from "./pages/IndexPage"; import LoginPage from "./pages/LoginPage"; @@ -29,6 +30,13 @@ export default function App() { + + {(params) => ( + + + + )} + {(params) => ( diff --git a/frontend/app/pages/DashboardPage.tsx b/frontend/app/pages/DashboardPage.tsx index 3191f1b..00db3f0 100644 --- a/frontend/app/pages/DashboardPage.tsx +++ b/frontend/app/pages/DashboardPage.tsx @@ -68,6 +68,11 @@ export default function DashboardPage() {
+ {game.started_at == null && ( + + 問題を見る + + )} 対戦 diff --git a/frontend/app/pages/GolfProblemPreviewPage.tsx b/frontend/app/pages/GolfProblemPreviewPage.tsx new file mode 100644 index 0000000..01ac5b2 --- /dev/null +++ b/frontend/app/pages/GolfProblemPreviewPage.tsx @@ -0,0 +1,60 @@ +import { useEffect, useState } from "react"; +import { useLocation } from "wouter"; +import { createApiClient } from "../api/client"; +import type { components } from "../api/schema"; +import ProblemColumnContent from "../components/Gaming/ProblemColumnContent"; +import NavigateLink from "../components/NavigateLink"; +import { APP_NAME } from "../config"; +import { usePageTitle } from "../hooks/usePageTitle"; + +type Game = components["schemas"]["Game"]; + +export default function GolfProblemPreviewPage({ gameId }: { gameId: string }) { + const [, navigate] = useLocation(); + const [game, setGame] = useState(null); + const [loading, setLoading] = useState(true); + + const gameIdNum = Number(gameId); + + usePageTitle( + game + ? `${game.display_name} - 問題プレビュー | ${APP_NAME}` + : `問題プレビュー | ${APP_NAME}`, + ); + + useEffect(() => { + const apiClient = createApiClient(); + apiClient + .getGame(gameIdNum) + .then(({ game }) => setGame(game)) + .catch(() => navigate("/dashboard")) + .finally(() => setLoading(false)); + }, [gameIdNum, navigate]); + + if (loading || !game) { + return ( +
+

Loading...

+
+ ); + } + + return ( +
+

{game.display_name}

+
+ +
+ {game.started_at != null && ( + + 対戦ページへ + + )} + ダッシュボードへ戻る +
+ ); +} -- cgit v1.3.1