aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend/app/routes/golf.$gameId.play.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/app/routes/golf.$gameId.play.tsx')
-rw-r--r--frontend/app/routes/golf.$gameId.play.tsx97
1 files changed, 91 insertions, 6 deletions
diff --git a/frontend/app/routes/golf.$gameId.play.tsx b/frontend/app/routes/golf.$gameId.play.tsx
index ea1b8fd..a2860dd 100644
--- a/frontend/app/routes/golf.$gameId.play.tsx
+++ b/frontend/app/routes/golf.$gameId.play.tsx
@@ -1,10 +1,17 @@
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
-import { useLoaderData } from "@remix-run/react";
-import { ClientOnly } from "remix-utils/client-only";
+import { ClientLoaderFunctionArgs, useLoaderData } from "@remix-run/react";
+import { useHydrateAtoms } from "jotai/utils";
import { apiGetGame, apiGetToken } from "../.server/api/client";
import { ensureUserLoggedIn } from "../.server/auth";
import GolfPlayApp from "../components/GolfPlayApp.client";
import GolfPlayAppConnecting from "../components/GolfPlayApps/GolfPlayAppConnecting";
+import {
+ scoreAtom,
+ setCurrentTimestampAtom,
+ setDurationSecondsAtom,
+ submitResultAtom,
+} from "../states/play";
+import { PlayerState } from "../types/PlayerState";
export const meta: MetaFunction<typeof loader> = ({ data }) => [
{
@@ -25,19 +32,97 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
};
const [game, sockToken] = await Promise.all([fetchGame(), fetchSockToken()]);
+
+ const playerState: PlayerState = {
+ code: "",
+ score: null,
+ submitResult: {
+ status: "waiting_submission",
+ execResults: game.exec_steps.map((r) => ({
+ testcase_id: r.testcase_id,
+ status: "waiting_submission",
+ label: r.label,
+ stdout: "",
+ stderr: "",
+ })),
+ },
+ };
+
return {
game,
player: user,
sockToken,
+ playerState,
};
}
+export async function clientLoader({ serverLoader }: ClientLoaderFunctionArgs) {
+ const data = await serverLoader<typeof loader>();
+ const baseKey = `playerState:${data.game.game_id}:${data.player.user_id}`;
+
+ const localCode = (() => {
+ const rawValue = window.localStorage.getItem(`${baseKey}:code`);
+ if (rawValue === null) {
+ return null;
+ }
+ return rawValue;
+ })();
+
+ const localScore = (() => {
+ const rawValue = window.localStorage.getItem(`${baseKey}:score`);
+ if (rawValue === null || rawValue === "") {
+ return null;
+ }
+ return Number(rawValue);
+ })();
+
+ const localSubmissionResult = (() => {
+ const rawValue = window.localStorage.getItem(`${baseKey}:submissionResult`);
+ if (rawValue === null) {
+ return null;
+ }
+ const parsed = JSON.parse(rawValue);
+ if (typeof parsed !== "object") {
+ return null;
+ }
+ return parsed;
+ })();
+
+ if (localCode !== null) {
+ data.playerState.code = localCode;
+ }
+ if (localScore !== null) {
+ data.playerState.score = localScore;
+ }
+ if (localSubmissionResult !== null) {
+ data.playerState.submitResult = localSubmissionResult;
+ }
+
+ return data;
+}
+clientLoader.hydrate = true;
+
+export function HydrateFallback() {
+ return <GolfPlayAppConnecting />;
+}
+
export default function GolfPlay() {
- const { game, player, sockToken } = useLoaderData<typeof loader>();
+ const { game, player, sockToken, playerState } =
+ useLoaderData<typeof loader>();
+
+ useHydrateAtoms([
+ [setCurrentTimestampAtom, undefined],
+ [setDurationSecondsAtom, game.duration_seconds],
+ [scoreAtom, playerState.score],
+ [submitResultAtom, playerState.submitResult],
+ ]);
return (
- <ClientOnly fallback={<GolfPlayAppConnecting />}>
- {() => <GolfPlayApp game={game} player={player} sockToken={sockToken} />}
- </ClientOnly>
+ <GolfPlayApp
+ game={game}
+ player={player}
+ initialCode={playerState.code}
+ sockToken={sockToken}
+ />
);
}