aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend/app/components/GolfWatchApp.tsx
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-03-04 22:55:01 +0900
committernsfisis <nsfisis@gmail.com>2025-03-08 10:12:44 +0900
commit1e6df136d8202c8adf65948527f4c3e7583b338c (patch)
tree7c82476f6bbbc71d72ab7e71e39559eca197fd95 /frontend/app/components/GolfWatchApp.tsx
parent54316868c3bec1ff9b04643dfe6c13cf56bf3246 (diff)
downloadiosdc-japan-2025-albatross-1e6df136d8202c8adf65948527f4c3e7583b338c.tar.gz
iosdc-japan-2025-albatross-1e6df136d8202c8adf65948527f4c3e7583b338c.tar.zst
iosdc-japan-2025-albatross-1e6df136d8202c8adf65948527f4c3e7583b338c.zip
websocket to polling
Diffstat (limited to 'frontend/app/components/GolfWatchApp.tsx')
-rw-r--r--frontend/app/components/GolfWatchApp.tsx127
1 files changed, 127 insertions, 0 deletions
diff --git a/frontend/app/components/GolfWatchApp.tsx b/frontend/app/components/GolfWatchApp.tsx
new file mode 100644
index 0000000..fe71932
--- /dev/null
+++ b/frontend/app/components/GolfWatchApp.tsx
@@ -0,0 +1,127 @@
+import { useAtomValue, useSetAtom } from "jotai";
+import { useContext, useEffect, useState } from "react";
+import { useTimer } from "react-use-precision-timer";
+import {
+ ApiAuthTokenContext,
+ apiGetGame,
+ apiGetGameWatchLatestStates,
+ apiGetGameWatchRanking,
+} from "../api/client";
+import type { components } from "../api/schema";
+import {
+ gameStateKindAtom,
+ setCurrentTimestampAtom,
+ setGameStartedAtAtom,
+ setLatestGameStatesAtom,
+ setRankingAtom,
+} from "../states/watch";
+import GolfWatchAppGaming from "./GolfWatchApps/GolfWatchAppGaming";
+import GolfWatchAppStarting from "./GolfWatchApps/GolfWatchAppStarting";
+import GolfWatchAppWaiting from "./GolfWatchApps/GolfWatchAppWaiting";
+
+type Game = components["schemas"]["Game"];
+
+export type Props = {
+ game: Game;
+};
+
+export default function GolfWatchApp({ game }: Props) {
+ const apiAuthToken = useContext(ApiAuthTokenContext);
+
+ const gameStateKind = useAtomValue(gameStateKindAtom);
+ const setGameStartedAt = useSetAtom(setGameStartedAtAtom);
+ const setCurrentTimestamp = useSetAtom(setCurrentTimestampAtom);
+ const setLatestGameStates = useSetAtom(setLatestGameStatesAtom);
+ const setRanking = useSetAtom(setRankingAtom);
+
+ useTimer({ delay: 1000, startImmediately: true }, setCurrentTimestamp);
+
+ const playerA = game.main_players[0]!;
+ const playerB = game.main_players[1]!;
+
+ const playerProfileA = {
+ id: playerA.user_id,
+ displayName: playerA.display_name,
+ iconPath: playerA.icon_path ?? null,
+ };
+ const playerProfileB = {
+ id: playerB.user_id,
+ displayName: playerB.display_name,
+ iconPath: playerB.icon_path ?? null,
+ };
+
+ const [isDataPolling, setIsDataPolling] = useState(false);
+
+ useEffect(() => {
+ if (isDataPolling) {
+ return;
+ }
+ const timerId = setInterval(async () => {
+ if (isDataPolling) {
+ return;
+ }
+ setIsDataPolling(true);
+
+ try {
+ if (gameStateKind === "waiting") {
+ const { game: g } = await apiGetGame(apiAuthToken, game.game_id);
+ if (g.started_at != null) {
+ setGameStartedAt(g.started_at);
+ }
+ } else if (gameStateKind === "gaming") {
+ const { states } = await apiGetGameWatchLatestStates(
+ apiAuthToken,
+ game.game_id,
+ );
+ setLatestGameStates(states);
+ const { ranking } = await apiGetGameWatchRanking(
+ apiAuthToken,
+ game.game_id,
+ );
+ setRanking(ranking);
+ }
+ } catch (error) {
+ console.error(error);
+ } finally {
+ setIsDataPolling(false);
+ }
+ }, 1000);
+
+ return () => {
+ clearInterval(timerId);
+ };
+ }, [
+ isDataPolling,
+ apiAuthToken,
+ game.game_id,
+ gameStateKind,
+ setGameStartedAt,
+ setLatestGameStates,
+ setRanking,
+ ]);
+
+ if (gameStateKind === "waiting") {
+ return (
+ <GolfWatchAppWaiting
+ gameDisplayName={game.display_name}
+ playerProfileA={playerProfileA}
+ playerProfileB={playerProfileB}
+ />
+ );
+ } else if (gameStateKind === "starting") {
+ return <GolfWatchAppStarting gameDisplayName={game.display_name} />;
+ } else if (gameStateKind === "gaming" || gameStateKind === "finished") {
+ return (
+ <GolfWatchAppGaming
+ gameDisplayName={game.display_name}
+ playerProfileA={playerProfileA}
+ playerProfileB={playerProfileB}
+ problemTitle={game.problem.title}
+ problemDescription={game.problem.description}
+ gameResult={null /* TODO */}
+ />
+ );
+ } else {
+ return null;
+ }
+}