From 3840c6d8e4261f182657b11ba55f61da04d70b28 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 31 Jul 2024 21:02:40 +0900 Subject: feat: implement /admin/games and /admin/games/{gameId} --- frontend/app/routes/admin.games_.$gameId.tsx | 127 +++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 frontend/app/routes/admin.games_.$gameId.tsx (limited to 'frontend/app/routes/admin.games_.$gameId.tsx') diff --git a/frontend/app/routes/admin.games_.$gameId.tsx b/frontend/app/routes/admin.games_.$gameId.tsx new file mode 100644 index 0000000..5d83fb4 --- /dev/null +++ b/frontend/app/routes/admin.games_.$gameId.tsx @@ -0,0 +1,127 @@ +import type { + LoaderFunctionArgs, + MetaFunction, + ActionFunctionArgs, +} from "@remix-run/node"; +import { useLoaderData, Form } from "@remix-run/react"; +import { isAuthenticated } from "../.server/auth"; +import { apiClient } from "../.server/api/client"; + +export const meta: MetaFunction = ({ data }) => { + return [ + { + title: data + ? `[Admin] Game Edit ${data.game.display_name} | iOSDC 2024 Albatross.swift` + : "[Admin] Game Edit | iOSDC 2024 Albatross.swift", + }, + ]; +}; + +export async function loader({ request, params }: LoaderFunctionArgs) { + const { user, token } = await isAuthenticated(request, { + failureRedirect: "/login", + }); + if (!user.is_admin) { + throw new Error("Unauthorized"); + } + const { gameId } = params; + const { data, error } = await apiClient.GET("/admin/games/{game_id}", { + params: { + path: { + game_id: Number(gameId), + }, + header: { + Authorization: `Bearer ${token}`, + }, + }, + }); + if (error) { + throw new Error(error.message); + } + return { game: data.game }; +} + +export async function action({ request, params }: ActionFunctionArgs) { + const { user, token } = await isAuthenticated(request, { + failureRedirect: "/login", + }); + if (!user.is_admin) { + throw new Error("Unauthorized"); + } + const { gameId } = params; + + const formData = await request.formData(); + const action = formData.get("action"); + + const nextState = + action === "open" + ? "waiting_entries" + : action === "start" + ? "waiting_start" + : null; + if (!nextState) { + throw new Error("Invalid action"); + } + + const { error } = await apiClient.PUT("/admin/games/{game_id}", { + params: { + path: { + game_id: Number(gameId), + }, + header: { + Authorization: `Bearer ${token}`, + }, + }, + body: { + state: nextState, + }, + }); + if (error) { + throw new Error(error.message); + } +} + +export default function AdminGameEdit() { + const { game } = useLoaderData()!; + + return ( +
+
+

[Admin] Game Edit {game.display_name}

+
    +
  • ID: {game.game_id}
  • +
  • State: {game.state}
  • +
  • Display Name: {game.display_name}
  • +
  • Duration Seconds: {game.duration_seconds}
  • +
  • + Started At:{" "} + {game.started_at + ? new Date(game.started_at * 1000).toString() + : "-"} +
  • +
  • Problem ID: {game.problem ? game.problem.problem_id : "-"}
  • +
+
+
+ + +
+
+
+
+ ); +} -- cgit v1.2.3-70-g09d2