From 7f29d334f26229753e68d20a5aaab33c39de9f06 Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Sun, 1 Mar 2026 12:21:21 +0900
Subject: feat(frontend): show submission history on play screen

Replace the placeholder submission status section with a full submission
history table using the existing getGamePlaySubmissions API. Extract
shared DataTable, DataTableCell, and formatUnixTimestamp from
RankingTable into a reusable Gaming/DataTable component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
 frontend/app/components/GolfPlayApp.tsx | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

(limited to 'frontend/app/components/GolfPlayApp.tsx')

diff --git a/frontend/app/components/GolfPlayApp.tsx b/frontend/app/components/GolfPlayApp.tsx
index 1c1e7ae..5d00239 100644
--- a/frontend/app/components/GolfPlayApp.tsx
+++ b/frontend/app/components/GolfPlayApp.tsx
@@ -1,6 +1,6 @@
 import { useAtomValue, useSetAtom } from "jotai";
 import { useHydrateAtoms } from "jotai/utils";
-import { useContext, useEffect, useState } from "react";
+import { useCallback, useContext, useEffect, useState } from "react";
 import { useTimer } from "react-use-precision-timer";
 import { useDebouncedCallback } from "use-debounce";
 import { ApiClientContext } from "../api/client";
@@ -21,6 +21,7 @@ import GolfPlayAppWaiting from "./GolfPlayApps/GolfPlayAppWaiting";
 
 type Game = components["schemas"]["Game"];
 type User = components["schemas"]["User"];
+type Submission = components["schemas"]["Submission"];
 type LatestGameState = components["schemas"]["LatestGameState"];
 
 type Props = {
@@ -75,8 +76,26 @@ export default function GolfPlayApp({ game, player, initialGameState }: Props) {
 		{ leading: true },
 	);
 
+	const [submissions, setSubmissions] = useState<Submission[]>([]);
 	const [isDataPolling, setIsDataPolling] = useState(false);
 
+	const fetchSubmissions = useCallback(async () => {
+		try {
+			const { submissions } = await apiClient.getGamePlaySubmissions(
+				game.game_id,
+			);
+			setSubmissions(submissions);
+		} catch (error) {
+			console.error(error);
+		}
+	}, [apiClient, game.game_id]);
+
+	useEffect(() => {
+		if (gameStateKind === "finished") {
+			fetchSubmissions();
+		}
+	}, [gameStateKind, fetchSubmissions]);
+
 	useEffect(() => {
 		if (isDataPolling) {
 			return;
@@ -98,6 +117,7 @@ export default function GolfPlayApp({ game, player, initialGameState }: Props) {
 						game.game_id,
 					);
 					setLatestGameState(state);
+					await fetchSubmissions();
 				}
 			} catch (error) {
 				console.error(error);
@@ -116,6 +136,7 @@ export default function GolfPlayApp({ game, player, initialGameState }: Props) {
 		gameStateKind,
 		setGameStartedAt,
 		setLatestGameState,
+		fetchSubmissions,
 	]);
 
 	if (gameStateKind === "loading") {
@@ -134,6 +155,7 @@ export default function GolfPlayApp({ game, player, initialGameState }: Props) {
 					onCodeChange={onCodeChange}
 					onCodeSubmit={onCodeSubmit}
 					isFinished={false}
+					submissions={submissions}
 				/>
 			);
 		}
@@ -158,6 +180,7 @@ export default function GolfPlayApp({ game, player, initialGameState }: Props) {
 				onCodeChange={onCodeChange}
 				onCodeSubmit={onCodeSubmit}
 				isFinished={gameStateKind === "finished"}
+				submissions={submissions}
 			/>
 		);
 	}
-- 
cgit v1.3.1

