From 43d40d375c355837de83501c3f1c122b2bf589bb Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Thu, 22 Aug 2024 00:19:58 +0900
Subject: feat(frontend): remove spectrum analyzer in waiting page

---
 .../components/GolfPlayApps/GolfPlayAppWaiting.tsx | 587 +--------------------
 1 file changed, 6 insertions(+), 581 deletions(-)

(limited to 'frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx')

diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx
index bbef43e..a31e5f4 100644
--- a/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx
+++ b/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx
@@ -11,588 +11,13 @@ export default function GolfPlayAppWaiting({
 	playerInfo,
 }: Props) {
 	return (
-		<>
-			<div className="min-h-screen bg-gray-100 flex flex-col font-bold text-center">
-				<div className="text-white bg-iosdc-japan p-10">
-					<div className="text-4xl">{gameDisplayName}</div>
-				</div>
-				<div className="grow grid mx-auto text-black">
-					<PlayerProfile playerInfo={playerInfo} label="You" />
-				</div>
+		<div className="min-h-screen bg-gray-100 flex flex-col font-bold text-center">
+			<div className="text-white bg-iosdc-japan p-10">
+				<div className="text-4xl">{gameDisplayName}</div>
 			</div>
-			<style>
-				{`
-        @keyframes changeHeight {
-          0% { height: 20%; }
-          50% { height: 100%; }
-          100% { height: 20%; }
-        }
-      `}
-			</style>
-			<div
-				style={{
-					position: "fixed",
-					bottom: 0,
-					width: "100%",
-					display: "flex",
-					justifyContent: "center",
-					alignItems: "flex-end",
-					height: "100px",
-					margin: "0 2px",
-				}}
-			>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "2.0s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.9s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.8s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.7s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.6s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.5s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.4s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.3s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.2s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.1s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.0s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.9s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.8s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.7s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.6s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.5s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.4s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.3s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.2s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.1s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.5s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.4s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.3s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.2s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.1s",
-					}}
-				></div>
-
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.1s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.2s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.3s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.4s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.5s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.1s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.2s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.3s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.4s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.5s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.6s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.7s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.8s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "0.9s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.0s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.1s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.2s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.3s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.4s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.5s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.6s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.7s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.8s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "1.9s",
-					}}
-				></div>
-				<div
-					style={{
-						width: "2%",
-						margin: "0 2px",
-						background:
-							"linear-gradient(345deg, rgb(230, 36, 136) 0%, rgb(240, 184, 106) 100%)",
-						display: "inline-block",
-						animation: "changeHeight 1s infinite ease-in-out",
-						animationDelay: "2.0s",
-					}}
-				></div>
+			<div className="grow grid mx-auto text-black">
+				<PlayerProfile playerInfo={playerInfo} label="You" />
 			</div>
-		</>
+		</div>
 	);
 }
-- 
cgit v1.2.3-70-g09d2


From 922bc6a1f52d8f01600e9a61ce31963075ec59a5 Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Thu, 22 Aug 2024 00:46:06 +0900
Subject: refactor(frontend): organize PlayerInfo

---
 .../components/Gaming/ExecStatusIndicatorIcon.tsx  |  2 +-
 frontend/app/components/Gaming/SubmitResult.tsx    |  2 +-
 frontend/app/components/GolfPlayApp.client.tsx     | 20 +++++----
 .../components/GolfPlayApps/GolfPlayAppGaming.tsx  | 16 ++++----
 .../components/GolfPlayApps/GolfPlayAppWaiting.tsx | 10 ++---
 frontend/app/components/GolfWatchApp.client.tsx    | 48 +++++++++++++---------
 .../GolfWatchApps/GolfWatchAppGaming.tsx           | 38 ++++++++---------
 .../GolfWatchApps/GolfWatchAppWaiting.tsx          | 18 ++++----
 frontend/app/components/PlayerNameAndIcon.tsx      | 25 +++++++++++
 frontend/app/components/PlayerProfile.tsx          | 27 ------------
 frontend/app/components/SubmitStatusLabel.tsx      |  2 +-
 frontend/app/models/ExecResult.ts                  | 18 --------
 frontend/app/models/PlayerInfo.ts                  |  9 ----
 frontend/app/models/SubmitResult.ts                | 16 --------
 frontend/app/types/ExecResult.ts                   | 18 ++++++++
 frontend/app/types/PlayerInfo.ts                   |  7 ++++
 frontend/app/types/PlayerProfile.ts                |  4 ++
 frontend/app/types/PlayerState.ts                  |  7 ++++
 frontend/app/types/SubmitResult.ts                 | 16 ++++++++
 19 files changed, 162 insertions(+), 141 deletions(-)
 create mode 100644 frontend/app/components/PlayerNameAndIcon.tsx
 delete mode 100644 frontend/app/components/PlayerProfile.tsx
 delete mode 100644 frontend/app/models/ExecResult.ts
 delete mode 100644 frontend/app/models/PlayerInfo.ts
 delete mode 100644 frontend/app/models/SubmitResult.ts
 create mode 100644 frontend/app/types/ExecResult.ts
 create mode 100644 frontend/app/types/PlayerInfo.ts
 create mode 100644 frontend/app/types/PlayerProfile.ts
 create mode 100644 frontend/app/types/PlayerState.ts
 create mode 100644 frontend/app/types/SubmitResult.ts

(limited to 'frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx')

diff --git a/frontend/app/components/Gaming/ExecStatusIndicatorIcon.tsx b/frontend/app/components/Gaming/ExecStatusIndicatorIcon.tsx
index b611c5d..a717a48 100644
--- a/frontend/app/components/Gaming/ExecStatusIndicatorIcon.tsx
+++ b/frontend/app/components/Gaming/ExecStatusIndicatorIcon.tsx
@@ -6,7 +6,7 @@ import {
 	faRotate,
 } from "@fortawesome/free-solid-svg-icons";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import type { ExecResultStatus } from "../../models/ExecResult";
+import type { ExecResultStatus } from "../../types/ExecResult";
 
 type Props = {
 	status: ExecResultStatus;
diff --git a/frontend/app/components/Gaming/SubmitResult.tsx b/frontend/app/components/Gaming/SubmitResult.tsx
index 93e08a7..c626910 100644
--- a/frontend/app/components/Gaming/SubmitResult.tsx
+++ b/frontend/app/components/Gaming/SubmitResult.tsx
@@ -1,5 +1,5 @@
 import React from "react";
-import type { SubmitResult } from "../../models/SubmitResult";
+import type { SubmitResult } from "../../types/SubmitResult";
 import BorderedContainer from "../BorderedContainer";
 import SubmitStatusLabel from "../SubmitStatusLabel";
 import ExecStatusIndicatorIcon from "./ExecStatusIndicatorIcon";
diff --git a/frontend/app/components/GolfPlayApp.client.tsx b/frontend/app/components/GolfPlayApp.client.tsx
index 42f0250..80cfc40 100644
--- a/frontend/app/components/GolfPlayApp.client.tsx
+++ b/frontend/app/components/GolfPlayApp.client.tsx
@@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
 import { useDebouncedCallback } from "use-debounce";
 import type { components } from "../.server/api/schema";
 import useWebSocket, { ReadyState } from "../hooks/useWebSocket";
-import type { PlayerInfo } from "../models/PlayerInfo";
+import type { PlayerState } from "../types/PlayerState";
 import GolfPlayAppConnecting from "./GolfPlayApps/GolfPlayAppConnecting";
 import GolfPlayAppFinished from "./GolfPlayApps/GolfPlayAppFinished";
 import GolfPlayAppGaming from "./GolfPlayApps/GolfPlayAppGaming";
@@ -72,9 +72,12 @@ export default function GolfPlayApp({
 		}
 	}, [gameState, startedAt, game.duration_seconds]);
 
-	const [playerInfo, setPlayerInfo] = useState<Omit<PlayerInfo, "code">>({
+	const playerProfile = {
 		displayName: player.display_name,
 		iconPath: player.icon_path ?? null,
+	};
+	const [playerState, setPlayerState] = useState<PlayerState>({
+		code: "",
 		score: null,
 		submitResult: {
 			status: "waiting_submission",
@@ -105,7 +108,7 @@ export default function GolfPlayApp({
 			type: "player:c2s:submit",
 			data: { code },
 		});
-		setPlayerInfo((prev) => ({
+		setPlayerState((prev) => ({
 			...prev,
 			submitResult: {
 				status: "running",
@@ -147,7 +150,7 @@ export default function GolfPlayApp({
 					}
 				} else if (lastJsonMessage.type === "player:s2c:execresult") {
 					const { testcase_id, status, stdout, stderr } = lastJsonMessage.data;
-					setPlayerInfo((prev) => {
+					setPlayerState((prev) => {
 						const ret = { ...prev };
 						ret.submitResult = {
 							...prev.submitResult,
@@ -166,7 +169,7 @@ export default function GolfPlayApp({
 					});
 				} else if (lastJsonMessage.type === "player:s2c:submitresult") {
 					const { status, score } = lastJsonMessage.data;
-					setPlayerInfo((prev) => {
+					setPlayerState((prev) => {
 						const ret = { ...prev };
 						ret.submitResult = {
 							...prev.submitResult,
@@ -228,7 +231,7 @@ export default function GolfPlayApp({
 		return (
 			<GolfPlayAppWaiting
 				gameDisplayName={game.display_name}
-				playerInfo={playerInfo}
+				playerProfile={playerProfile}
 			/>
 		);
 	} else if (gameState === "starting") {
@@ -244,7 +247,10 @@ export default function GolfPlayApp({
 				gameDisplayName={game.display_name}
 				gameDurationSeconds={game.duration_seconds}
 				leftTimeSeconds={leftTimeSeconds!}
-				playerInfo={playerInfo}
+				playerInfo={{
+					profile: playerProfile,
+					state: playerState,
+				}}
 				problemTitle={game.problem.title}
 				problemDescription={game.problem.description}
 				onCodeChange={onCodeChange}
diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx
index e6cb7e9..38516bc 100644
--- a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx
+++ b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx
@@ -1,7 +1,7 @@
 import { Link } from "@remix-run/react";
 import React, { useRef } from "react";
 import SubmitButton from "../../components/SubmitButton";
-import type { PlayerInfo } from "../../models/PlayerInfo";
+import type { PlayerInfo } from "../../types/PlayerInfo";
 import BorderedContainer from "../BorderedContainer";
 import SubmitResult from "../Gaming/SubmitResult";
 import UserIcon from "../UserIcon";
@@ -10,7 +10,7 @@ type Props = {
 	gameDisplayName: string;
 	gameDurationSeconds: number;
 	leftTimeSeconds: number;
-	playerInfo: Omit<PlayerInfo, "code">;
+	playerInfo: PlayerInfo;
 	problemTitle: string;
 	problemDescription: string;
 	onCodeChange: (code: string) => void;
@@ -55,15 +55,15 @@ export default function GolfPlayAppGaming({
 				</div>
 				<Link to={"/dashboard"}>
 					<div className="flex gap-4 my-auto font-bold">
-						<div className="text-6xl">{playerInfo.score}</div>
+						<div className="text-6xl">{playerInfo.state.score}</div>
 						<div className="text-end">
 							<div className="text-gray-100">Player 1</div>
-							<div className="text-2xl">{playerInfo.displayName}</div>
+							<div className="text-2xl">{playerInfo.profile.displayName}</div>
 						</div>
-						{playerInfo.iconPath && (
+						{playerInfo.profile.iconPath && (
 							<UserIcon
-								iconPath={playerInfo.iconPath}
-								displayName={playerInfo.displayName!}
+								iconPath={playerInfo.profile.iconPath}
+								displayName={playerInfo.profile.displayName}
 								className="w-12 h-12 my-auto"
 							/>
 						)}
@@ -88,7 +88,7 @@ export default function GolfPlayAppGaming({
 				</div>
 				<div className="p-4">
 					<SubmitResult
-						result={playerInfo.submitResult}
+						result={playerInfo.state.submitResult}
 						submitButton={
 							<SubmitButton onClick={handleSubmitButtonClick}>
 								提出
diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx
index a31e5f4..706dc8f 100644
--- a/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx
+++ b/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx
@@ -1,14 +1,14 @@
-import { PlayerInfo } from "../../models/PlayerInfo";
-import PlayerProfile from "../PlayerProfile";
+import type { PlayerProfile } from "../../types/PlayerProfile";
+import PlayerNameAndIcon from "../PlayerNameAndIcon";
 
 type Props = {
 	gameDisplayName: string;
-	playerInfo: Omit<PlayerInfo, "code">;
+	playerProfile: PlayerProfile;
 };
 
 export default function GolfPlayAppWaiting({
 	gameDisplayName,
-	playerInfo,
+	playerProfile,
 }: Props) {
 	return (
 		<div className="min-h-screen bg-gray-100 flex flex-col font-bold text-center">
@@ -16,7 +16,7 @@ export default function GolfPlayAppWaiting({
 				<div className="text-4xl">{gameDisplayName}</div>
 			</div>
 			<div className="grow grid mx-auto text-black">
-				<PlayerProfile playerInfo={playerInfo} label="You" />
+				<PlayerNameAndIcon label="You" profile={playerProfile} />
 			</div>
 		</div>
 	);
diff --git a/frontend/app/components/GolfWatchApp.client.tsx b/frontend/app/components/GolfWatchApp.client.tsx
index d09a4ae..9eacb2d 100644
--- a/frontend/app/components/GolfWatchApp.client.tsx
+++ b/frontend/app/components/GolfWatchApp.client.tsx
@@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
 import { AudioController } from "../.client/audio/AudioController";
 import type { components } from "../.server/api/schema";
 import useWebSocket, { ReadyState } from "../hooks/useWebSocket";
-import type { PlayerInfo } from "../models/PlayerInfo";
+import type { PlayerState } from "../types/PlayerState";
 import GolfWatchAppConnecting from "./GolfWatchApps/GolfWatchAppConnecting";
 import GolfWatchAppGaming from "./GolfWatchApps/GolfWatchAppGaming";
 import GolfWatchAppStarting from "./GolfWatchApps/GolfWatchAppStarting";
@@ -73,12 +73,14 @@ export default function GolfWatchApp({
 		}
 	}, [gameState, startedAt, game.duration_seconds, audioController]);
 
-	const playerA = game.players[0];
-	const playerB = game.players[1];
+	const playerA = game.players[0]!;
+	const playerB = game.players[1]!;
 
-	const [playerInfoA, setPlayerInfoA] = useState<PlayerInfo>({
-		displayName: playerA?.display_name ?? null,
-		iconPath: playerA?.icon_path ?? null,
+	const playerProfileA = {
+		displayName: playerA.display_name,
+		iconPath: playerA.icon_path ?? null,
+	};
+	const [playerStateA, setPlayerStateA] = useState<PlayerState>({
 		score: null,
 		code: "",
 		submitResult: {
@@ -92,9 +94,11 @@ export default function GolfWatchApp({
 			})),
 		},
 	});
-	const [playerInfoB, setPlayerInfoB] = useState<PlayerInfo>({
-		displayName: playerB?.display_name ?? null,
-		iconPath: playerB?.icon_path ?? null,
+	const playerProfileB = {
+		displayName: playerB.display_name,
+		iconPath: playerB.icon_path ?? null,
+	};
+	const [playerStateB, setPlayerStateB] = useState<PlayerState>({
 		score: null,
 		code: "",
 		submitResult: {
@@ -138,12 +142,12 @@ export default function GolfWatchApp({
 				} else if (lastJsonMessage.type === "watcher:s2c:code") {
 					const { player_id, code } = lastJsonMessage.data;
 					const setter =
-						player_id === playerA?.user_id ? setPlayerInfoA : setPlayerInfoB;
+						player_id === playerA.user_id ? setPlayerStateA : setPlayerStateB;
 					setter((prev) => ({ ...prev, code }));
 				} else if (lastJsonMessage.type === "watcher:s2c:submit") {
 					const { player_id } = lastJsonMessage.data;
 					const setter =
-						player_id === playerA?.user_id ? setPlayerInfoA : setPlayerInfoB;
+						player_id === playerA.user_id ? setPlayerStateA : setPlayerStateB;
 					setter((prev) => ({
 						...prev,
 						submitResult: {
@@ -160,7 +164,7 @@ export default function GolfWatchApp({
 					const { player_id, testcase_id, status, stdout, stderr } =
 						lastJsonMessage.data;
 					const setter =
-						player_id === playerA?.user_id ? setPlayerInfoA : setPlayerInfoB;
+						player_id === playerA.user_id ? setPlayerStateA : setPlayerStateB;
 					setter((prev) => {
 						const ret = { ...prev };
 						ret.submitResult = {
@@ -181,7 +185,7 @@ export default function GolfWatchApp({
 				} else if (lastJsonMessage.type === "watcher:s2c:submitresult") {
 					const { player_id, status, score } = lastJsonMessage.data;
 					const setter =
-						player_id === playerA?.user_id ? setPlayerInfoA : setPlayerInfoB;
+						player_id === playerA.user_id ? setPlayerStateA : setPlayerStateB;
 					setter((prev) => {
 						const ret = { ...prev };
 						ret.submitResult = {
@@ -235,8 +239,8 @@ export default function GolfWatchApp({
 		lastJsonMessage,
 		readyState,
 		gameState,
-		playerA?.user_id,
-		playerB?.user_id,
+		playerA.user_id,
+		playerB.user_id,
 	]);
 
 	if (gameState === "connecting") {
@@ -245,8 +249,8 @@ export default function GolfWatchApp({
 		return (
 			<GolfWatchAppWaiting
 				gameDisplayName={game.display_name}
-				playerInfoA={playerInfoA}
-				playerInfoB={playerInfoB}
+				playerProfileA={playerProfileA}
+				playerProfileB={playerProfileB}
 			/>
 		);
 	} else if (gameState === "starting") {
@@ -262,8 +266,14 @@ export default function GolfWatchApp({
 				gameDisplayName={game.display_name}
 				gameDurationSeconds={game.duration_seconds}
 				leftTimeSeconds={leftTimeSeconds!}
-				playerInfoA={playerInfoA}
-				playerInfoB={playerInfoB}
+				playerInfoA={{
+					profile: playerProfileA,
+					state: playerStateA,
+				}}
+				playerInfoB={{
+					profile: playerProfileB,
+					state: playerStateB,
+				}}
 				problemTitle={game.problem.title}
 				problemDescription={game.problem.description}
 				gameResult={null /* TODO */}
diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx
index 28babff..a23a972 100644
--- a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx
+++ b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx
@@ -1,4 +1,4 @@
-import { PlayerInfo } from "../../models/PlayerInfo";
+import type { PlayerInfo } from "../../types/PlayerInfo";
 import BorderedContainer from "../BorderedContainer";
 import CodeBlock from "../Gaming/CodeBlock";
 import ScoreBar from "../Gaming/ScoreBar";
@@ -49,43 +49,43 @@ export default function GolfWatchAppGaming({
 			<div className={`text-white ${topBg} grid grid-cols-3 px-4 py-2`}>
 				<div className="font-bold flex justify-between my-auto">
 					<div className="flex gap-6">
-						{playerInfoA.iconPath && (
+						{playerInfoA.profile.iconPath && (
 							<UserIcon
-								iconPath={playerInfoA.iconPath}
-								displayName={playerInfoA.displayName!}
+								iconPath={playerInfoA.profile.iconPath}
+								displayName={playerInfoA.profile.displayName}
 								className="w-12 h-12 my-auto"
 							/>
 						)}
 						<div>
 							<div className="text-gray-100">Player 1</div>
-							<div className="text-2xl">{playerInfoA.displayName}</div>
+							<div className="text-2xl">{playerInfoA.profile.displayName}</div>
 						</div>
 					</div>
-					<div className="text-6xl">{playerInfoA.score}</div>
+					<div className="text-6xl">{playerInfoA.state.score}</div>
 				</div>
 				<div className="font-bold text-center">
 					<div className="text-gray-100">{gameDisplayName}</div>
 					<div className="text-3xl">
 						{gameResult
 							? gameResult === "winA"
-								? `勝者 ${playerInfoA.displayName}`
+								? `勝者 ${playerInfoA.profile.displayName}`
 								: gameResult === "winB"
-									? `勝者 ${playerInfoB.displayName}`
+									? `勝者 ${playerInfoB.profile.displayName}`
 									: "引き分け"
 							: leftTime}
 					</div>
 				</div>
 				<div className="font-bold flex justify-between my-auto">
-					<div className="text-6xl">{playerInfoB.score}</div>
+					<div className="text-6xl">{playerInfoB.state.score}</div>
 					<div className="flex gap-6 text-end">
 						<div>
 							<div className="text-gray-100">Player 2</div>
-							<div className="text-2xl">{playerInfoB.displayName}</div>
+							<div className="text-2xl">{playerInfoB.profile.displayName}</div>
 						</div>
-						{playerInfoB.iconPath && (
+						{playerInfoB.profile.iconPath && (
 							<UserIcon
-								iconPath={playerInfoB.iconPath}
-								displayName={playerInfoB.displayName!}
+								iconPath={playerInfoB.profile.iconPath}
+								displayName={playerInfoB.profile.displayName}
 								className="w-12 h-12 my-auto"
 							/>
 						)}
@@ -93,17 +93,17 @@ export default function GolfWatchAppGaming({
 				</div>
 			</div>
 			<ScoreBar
-				scoreA={playerInfoA.score}
-				scoreB={playerInfoB.score}
+				scoreA={playerInfoA.state.score}
+				scoreB={playerInfoB.state.score}
 				bgA="bg-orange-400"
 				bgB="bg-purple-400"
 			/>
 			<div className="grow grid grid-cols-3 p-4 gap-4">
-				<CodeBlock code={playerInfoA.code ?? ""} language="swift" />
+				<CodeBlock code={playerInfoA.state.code ?? ""} language="swift" />
 				<div className="flex flex-col gap-4">
 					<div className="grid grid-cols-2 gap-4">
-						<SubmitResult result={playerInfoA.submitResult} />
-						<SubmitResult result={playerInfoB.submitResult} />
+						<SubmitResult result={playerInfoA.state.submitResult} />
+						<SubmitResult result={playerInfoB.state.submitResult} />
 					</div>
 					<div>
 						<div className="mb-2 text-center text-xl font-bold">
@@ -112,7 +112,7 @@ export default function GolfWatchAppGaming({
 						<BorderedContainer>{problemDescription}</BorderedContainer>
 					</div>
 				</div>
-				<CodeBlock code={playerInfoB.code ?? ""} language="swift" />
+				<CodeBlock code={playerInfoB.state.code ?? ""} language="swift" />
 			</div>
 		</div>
 	);
diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppWaiting.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppWaiting.tsx
index faa9485..0e964e3 100644
--- a/frontend/app/components/GolfWatchApps/GolfWatchAppWaiting.tsx
+++ b/frontend/app/components/GolfWatchApps/GolfWatchAppWaiting.tsx
@@ -1,18 +1,16 @@
-import { PlayerInfo as FullPlayerInfo } from "../../models/PlayerInfo";
-import PlayerProfile from "../PlayerProfile";
-
-type PlayerInfo = Pick<FullPlayerInfo, "displayName" | "iconPath">;
+import type { PlayerProfile } from "../../types/PlayerProfile";
+import PlayerNameAndIcon from "../PlayerNameAndIcon";
 
 type Props = {
 	gameDisplayName: string;
-	playerInfoA: PlayerInfo;
-	playerInfoB: PlayerInfo;
+	playerProfileA: PlayerProfile;
+	playerProfileB: PlayerProfile;
 };
 
 export default function GolfWatchAppWaiting({
 	gameDisplayName,
-	playerInfoA,
-	playerInfoB,
+	playerProfileA,
+	playerProfileB,
 }: Props) {
 	return (
 		<div className="min-h-screen bg-gray-100 flex flex-col font-bold text-center">
@@ -20,9 +18,9 @@ export default function GolfWatchAppWaiting({
 				<div className="text-4xl">{gameDisplayName}</div>
 			</div>
 			<div className="grow grid grid-cols-3 gap-10 mx-auto text-black">
-				<PlayerProfile playerInfo={playerInfoA} label="Player 1" />
+				<PlayerNameAndIcon label="Player 1" profile={playerProfileA} />
 				<div className="text-8xl my-auto">vs.</div>
-				<PlayerProfile playerInfo={playerInfoB} label="Player 2" />
+				<PlayerNameAndIcon label="Player 2" profile={playerProfileB} />
 			</div>
 		</div>
 	);
diff --git a/frontend/app/components/PlayerNameAndIcon.tsx b/frontend/app/components/PlayerNameAndIcon.tsx
new file mode 100644
index 0000000..e9536e3
--- /dev/null
+++ b/frontend/app/components/PlayerNameAndIcon.tsx
@@ -0,0 +1,25 @@
+import { PlayerProfile } from "../types/PlayerProfile";
+import UserIcon from "./UserIcon";
+
+type Props = {
+	label: string;
+	profile: PlayerProfile;
+};
+
+export default function PlayerNameAndIcon({ label, profile }: Props) {
+	return (
+		<div className="flex flex-col gap-6 my-auto">
+			<div className="flex flex-col gap-2">
+				<div className="text-4xl">{label}</div>
+				<div className="text-6xl">{profile.displayName}</div>
+			</div>
+			{profile.iconPath && (
+				<UserIcon
+					iconPath={profile.iconPath}
+					displayName={profile.displayName}
+					className="w-48 h-48"
+				/>
+			)}
+		</div>
+	);
+}
diff --git a/frontend/app/components/PlayerProfile.tsx b/frontend/app/components/PlayerProfile.tsx
deleted file mode 100644
index 675d77b..0000000
--- a/frontend/app/components/PlayerProfile.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import { PlayerInfo as FullPlayerInfo } from "../models/PlayerInfo";
-import UserIcon from "./UserIcon";
-
-type PlayerInfo = Pick<FullPlayerInfo, "displayName" | "iconPath">;
-
-type Props = {
-	playerInfo: PlayerInfo;
-	label: string;
-};
-
-export default function PlayerProfile({ playerInfo, label }: Props) {
-	return (
-		<div className="flex flex-col gap-6 my-auto">
-			<div className="flex flex-col gap-2">
-				<div className="text-4xl">{label}</div>
-				<div className="text-6xl">{playerInfo.displayName}</div>
-			</div>
-			{playerInfo.iconPath && (
-				<UserIcon
-					iconPath={playerInfo.iconPath}
-					displayName={playerInfo.displayName!}
-					className="w-48 h-48"
-				/>
-			)}
-		</div>
-	);
-}
diff --git a/frontend/app/components/SubmitStatusLabel.tsx b/frontend/app/components/SubmitStatusLabel.tsx
index 0e13c1e..d1dc89c 100644
--- a/frontend/app/components/SubmitStatusLabel.tsx
+++ b/frontend/app/components/SubmitStatusLabel.tsx
@@ -1,4 +1,4 @@
-import type { SubmitResultStatus } from "../models/SubmitResult";
+import type { SubmitResultStatus } from "../types/SubmitResult";
 
 type Props = {
 	status: SubmitResultStatus;
diff --git a/frontend/app/models/ExecResult.ts b/frontend/app/models/ExecResult.ts
deleted file mode 100644
index e0b6bb4..0000000
--- a/frontend/app/models/ExecResult.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-export type ExecResultStatus =
-	| "waiting_submission"
-	| "running"
-	| "success"
-	| "wrong_answer"
-	| "timeout"
-	| "compile_error"
-	| "runtime_error"
-	| "internal_error"
-	| "canceled";
-
-export type ExecResult = {
-	testcase_id: number | null;
-	status: ExecResultStatus;
-	label: string;
-	stdout: string;
-	stderr: string;
-};
diff --git a/frontend/app/models/PlayerInfo.ts b/frontend/app/models/PlayerInfo.ts
deleted file mode 100644
index 8092ab3..0000000
--- a/frontend/app/models/PlayerInfo.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { SubmitResult } from "./SubmitResult";
-
-export type PlayerInfo = {
-	displayName: string | null;
-	iconPath: string | null;
-	score: number | null;
-	code: string | null;
-	submitResult: SubmitResult;
-};
diff --git a/frontend/app/models/SubmitResult.ts b/frontend/app/models/SubmitResult.ts
deleted file mode 100644
index 6df00b6..0000000
--- a/frontend/app/models/SubmitResult.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import type { ExecResult } from "./ExecResult";
-
-export type SubmitResultStatus =
-	| "waiting_submission"
-	| "running"
-	| "success"
-	| "wrong_answer"
-	| "timeout"
-	| "compile_error"
-	| "runtime_error"
-	| "internal_error";
-
-export type SubmitResult = {
-	status: SubmitResultStatus;
-	execResults: ExecResult[];
-};
diff --git a/frontend/app/types/ExecResult.ts b/frontend/app/types/ExecResult.ts
new file mode 100644
index 0000000..e0b6bb4
--- /dev/null
+++ b/frontend/app/types/ExecResult.ts
@@ -0,0 +1,18 @@
+export type ExecResultStatus =
+	| "waiting_submission"
+	| "running"
+	| "success"
+	| "wrong_answer"
+	| "timeout"
+	| "compile_error"
+	| "runtime_error"
+	| "internal_error"
+	| "canceled";
+
+export type ExecResult = {
+	testcase_id: number | null;
+	status: ExecResultStatus;
+	label: string;
+	stdout: string;
+	stderr: string;
+};
diff --git a/frontend/app/types/PlayerInfo.ts b/frontend/app/types/PlayerInfo.ts
new file mode 100644
index 0000000..e282ba9
--- /dev/null
+++ b/frontend/app/types/PlayerInfo.ts
@@ -0,0 +1,7 @@
+import type { PlayerProfile } from "./PlayerProfile";
+import type { PlayerState } from "./PlayerState";
+
+export type PlayerInfo = {
+	profile: PlayerProfile;
+	state: PlayerState;
+};
diff --git a/frontend/app/types/PlayerProfile.ts b/frontend/app/types/PlayerProfile.ts
new file mode 100644
index 0000000..42bdcb8
--- /dev/null
+++ b/frontend/app/types/PlayerProfile.ts
@@ -0,0 +1,4 @@
+export type PlayerProfile = {
+	displayName: string;
+	iconPath: string | null;
+};
diff --git a/frontend/app/types/PlayerState.ts b/frontend/app/types/PlayerState.ts
new file mode 100644
index 0000000..e2a2da9
--- /dev/null
+++ b/frontend/app/types/PlayerState.ts
@@ -0,0 +1,7 @@
+import type { SubmitResult } from "./SubmitResult";
+
+export type PlayerState = {
+	score: number | null;
+	code: string;
+	submitResult: SubmitResult;
+};
diff --git a/frontend/app/types/SubmitResult.ts b/frontend/app/types/SubmitResult.ts
new file mode 100644
index 0000000..6df00b6
--- /dev/null
+++ b/frontend/app/types/SubmitResult.ts
@@ -0,0 +1,16 @@
+import type { ExecResult } from "./ExecResult";
+
+export type SubmitResultStatus =
+	| "waiting_submission"
+	| "running"
+	| "success"
+	| "wrong_answer"
+	| "timeout"
+	| "compile_error"
+	| "runtime_error"
+	| "internal_error";
+
+export type SubmitResult = {
+	status: SubmitResultStatus;
+	execResults: ExecResult[];
+};
-- 
cgit v1.2.3-70-g09d2

