From e239fe743fc66a8712cf9886d3dfed3cc41fce36 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Fri, 13 Feb 2026 22:40:45 +0900 Subject: refactor(frontend): replace React Router BFF with Wouter SPA Remove React Router 7 SSR/BFF architecture (server-side loaders, actions, sessions, remix-auth) and replace with a client-side SPA using Wouter for routing and cookie-based JWT auth. - Replace reactRouter() Vite plugin with @vitejs/plugin-react - Add index.html + app/main.tsx as SPA entry points - Add Wouter routing with auth guards (ProtectedRoute/PublicOnlyRoute) - Add client-side auth (app/auth.ts) and useAuth hook - Migrate all route files to app/pages/ with client-side data fetching - Update NavigateLink and GolfPlayAppGaming to use Wouter Link - Remove .server/, routes/, root.tsx, react-router.config.ts - Clean up tsconfig.json (remove .react-router references) Co-Authored-By: Claude Opus 4.6 --- frontend/app/routes/tournament.tsx | 440 ------------------------------------- 1 file changed, 440 deletions(-) delete mode 100644 frontend/app/routes/tournament.tsx (limited to 'frontend/app/routes/tournament.tsx') diff --git a/frontend/app/routes/tournament.tsx b/frontend/app/routes/tournament.tsx deleted file mode 100644 index 162bd1a..0000000 --- a/frontend/app/routes/tournament.tsx +++ /dev/null @@ -1,440 +0,0 @@ -import type { LoaderFunctionArgs, MetaFunction } from "react-router"; -import { useLoaderData } from "react-router"; -import { ensureUserLoggedIn } from "../.server/auth"; -import { createApiClient } from "../api/client"; -import type { components } from "../api/schema"; -import BorderedContainer from "../components/BorderedContainer"; -import UserIcon from "../components/UserIcon"; -import { APP_NAME } from "../config"; - -export const meta: MetaFunction = () => [{ title: `Tournament | ${APP_NAME}` }]; - -export async function loader({ request }: LoaderFunctionArgs) { - const { token } = await ensureUserLoggedIn(request); - const apiClient = createApiClient(token); - - const url = new URL(request.url); - const game1Param = url.searchParams.get("game1"); - const game2Param = url.searchParams.get("game2"); - const game3Param = url.searchParams.get("game3"); - const game4Param = url.searchParams.get("game4"); - const game5Param = url.searchParams.get("game5"); - const player1Param = url.searchParams.get("player1"); - const player2Param = url.searchParams.get("player2"); - const player3Param = url.searchParams.get("player3"); - const player4Param = url.searchParams.get("player4"); - const player5Param = url.searchParams.get("player5"); - const player6Param = url.searchParams.get("player6"); - - if (!game1Param || !game2Param || !game3Param || !game4Param || !game5Param) { - throw new Response( - "Missing required query parameters: game1, game2, game3, game4, game5", - { - status: 400, - }, - ); - } - if ( - !player1Param || - !player2Param || - !player3Param || - !player4Param || - !player5Param || - !player6Param - ) { - throw new Response( - "Missing required query parameters: player1, player2, player3, player4, player5, player6", - { - status: 400, - }, - ); - } - - const game1 = Number(game1Param); - const game2 = Number(game2Param); - const game3 = Number(game3Param); - const game4 = Number(game4Param); - const game5 = Number(game5Param); - - if (!game1 || !game2 || !game3 || !game4 || !game5) { - throw new Response("Invalid game IDs: must be positive integers", { - status: 400, - }); - } - - const { tournament } = await apiClient.getTournament( - game1, - game2, - game3, - game4, - game5, - ); - return { - tournament, - playerIDs: [ - Number(player1Param), - Number(player2Param), - Number(player3Param), - Number(player4Param), - Number(player5Param), - Number(player6Param), - ], - }; -} - -type TournamentMatch = components["schemas"]["TournamentMatch"]; -type User = components["schemas"]["User"]; - -function Player({ player, rank }: { player: User | null; rank: number }) { - return ( - -
- 予選 {rank} 位 - {player?.display_name} - {player?.icon_path && ( - - )} -
-
- ); -} - -function BranchVL({ className = "" }: { className?: string }) { - return ( -
-
-
-
- ); -} - -function BranchVR({ className = "" }: { className?: string }) { - return ( -
-
-
-
- ); -} - -function BranchVL2({ - score, - className = "", -}: { score: number | null; className?: string }) { - return ( -
-
-
- {score} -
-
-
- ); -} - -function BranchVR2({ - score, - className = "", -}: { score: number | null; className?: string }) { - return ( -
-
-
- {score} -
-
-
- ); -} - -function BranchV3({ className = "" }: { className?: string }) { - return
; -} - -function BranchH({ - score, - className1, - className2, - className3, -}: { - score?: number | null; - className1: string; - className2: string; - className3: string; -}) { - return ( -
-
-
-
- {score} -
-
- ); -} - -function BranchH2({ - score, - className1, - className2, - className3, -}: { - score?: number | null; - className1: string; - className2: string; - className3: string; -}) { - return ( -
-
- {score} -
-
-
-
- ); -} - -function BranchL({ - score, - className = "", -}: { score: number | null; className?: string }) { - return ( -
-
-
- {score} -
-
- ); -} - -function BranchR({ - score, - className = "", -}: { score: number | null; className?: string }) { - return ( -
-
- {score} -
-
-
- ); -} - -function BranchL2({ className = "" }: { className?: string }) { - return ( -
-
-
-
- ); -} - -function BranchR2({ className = "" }: { className?: string }) { - return ( -
-
-
-
- ); -} - -function getPlayer(match: TournamentMatch, playerID: number): User | null { - if (match.player1?.user_id === playerID) return match.player1; - else if (match.player2?.user_id === playerID) return match.player2; - else return null; -} - -function getScore(match: TournamentMatch, playerIDs: number[]): number | null { - if (match.player1 && playerIDs.includes(match.player1.user_id)) - return match.player1_score ?? null; - if (match.player2 && playerIDs.includes(match.player2.user_id)) - return match.player2_score ?? null; - else return null; -} - -function getBorderColor(match: TournamentMatch, playerIDs: number[]): string { - if (!match.winner) { - return "border-black"; - } else if (playerIDs.includes(match.winner)) { - return "border-pink-700"; - } else { - return "border-gray-400"; - } -} - -export default function Tournament() { - const { tournament, playerIDs } = useLoaderData(); - - const match1 = tournament.matches[0]!; - const match2 = tournament.matches[1]!; - const match3 = tournament.matches[2]!; - const match4 = tournament.matches[3]!; - const match5 = tournament.matches[4]!; - - const playerID1 = playerIDs[0]!; - const playerID2 = playerIDs[1]!; - const playerID3 = playerIDs[2]!; - const playerID4 = playerIDs[3]!; - const playerID5 = playerIDs[4]!; - const playerID6 = playerIDs[5]!; - - const player5 = getPlayer(match1, playerID5); - const player4 = getPlayer(match1, playerID4); - const player3 = getPlayer(match2, playerID3); - const player6 = getPlayer(match2, playerID6); - const player1 = getPlayer(match3, playerID1); - const player2 = getPlayer(match4, playerID2); - - return ( -
-
-

- iOSDC Japan 2025 Swift Code Battle -

- -
-
-
-
- -
-
-
-
-
-
- - - - -
-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
-
- ); -} -- cgit v1.3.1