aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-03-15 23:07:40 +0900
committernsfisis <nsfisis@gmail.com>2025-03-15 23:07:40 +0900
commit172b6d3211d040e8d577afda80debce583c3bf7c (patch)
treee62023aebb0924e8ad63c37e2d22f0a50a299eff
parentc2e23841f446489c4d9b7d2b616f3de249159f5f (diff)
downloadphperkaigi-2025-albatross-172b6d3211d040e8d577afda80debce583c3bf7c.tar.gz
phperkaigi-2025-albatross-172b6d3211d040e8d577afda80debce583c3bf7c.tar.zst
phperkaigi-2025-albatross-172b6d3211d040e8d577afda80debce583c3bf7c.zip
feat(frontend): show loaing screen
-rw-r--r--frontend/app/components/GolfPlayApp.tsx7
-rw-r--r--frontend/app/components/GolfPlayApps/GolfPlayAppLoading.tsx9
-rw-r--r--frontend/app/components/GolfWatchApp.tsx7
-rw-r--r--frontend/app/components/GolfWatchApps/GolfWatchAppLoading.tsx9
-rw-r--r--frontend/app/routes/golf.$gameId.play.tsx2
-rw-r--r--frontend/app/routes/golf.$gameId.watch.tsx2
-rw-r--r--frontend/app/states/play.ts27
-rw-r--r--frontend/app/states/watch.ts20
8 files changed, 63 insertions, 20 deletions
diff --git a/frontend/app/components/GolfPlayApp.tsx b/frontend/app/components/GolfPlayApp.tsx
index e8fafbd..0bb66eb 100644
--- a/frontend/app/components/GolfPlayApp.tsx
+++ b/frontend/app/components/GolfPlayApp.tsx
@@ -20,6 +20,7 @@ import {
} from "../states/play";
import GolfPlayAppFinished from "./GolfPlayApps/GolfPlayAppFinished";
import GolfPlayAppGaming from "./GolfPlayApps/GolfPlayAppGaming";
+import GolfPlayAppLoading from "./GolfPlayApps/GolfPlayAppLoading";
import GolfPlayAppStarting from "./GolfPlayApps/GolfPlayAppStarting";
import GolfPlayAppWaiting from "./GolfPlayApps/GolfPlayAppWaiting";
@@ -111,7 +112,9 @@ export default function GolfPlayApp({ game, player, initialCode }: Props) {
setLatestGameState,
]);
- if (gameStateKind === "waiting") {
+ if (gameStateKind === "loading") {
+ return <GolfPlayAppLoading />;
+ } else if (gameStateKind === "waiting") {
return (
<GolfPlayAppWaiting
gameDisplayName={game.display_name}
@@ -135,7 +138,5 @@ export default function GolfPlayApp({ game, player, initialCode }: Props) {
);
} else if (gameStateKind === "finished") {
return <GolfPlayAppFinished />;
- } else {
- return null;
}
}
diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppLoading.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppLoading.tsx
new file mode 100644
index 0000000..7b424f2
--- /dev/null
+++ b/frontend/app/components/GolfPlayApps/GolfPlayAppLoading.tsx
@@ -0,0 +1,9 @@
+export default function GolfPlayAppLoading() {
+ return (
+ <div className="min-h-screen bg-gray-100 flex items-center justify-center">
+ <div className="text-center">
+ <div className="text-6xl font-bold text-black">読込中</div>
+ </div>
+ </div>
+ );
+}
diff --git a/frontend/app/components/GolfWatchApp.tsx b/frontend/app/components/GolfWatchApp.tsx
index 919fa4f..5cbec3d 100644
--- a/frontend/app/components/GolfWatchApp.tsx
+++ b/frontend/app/components/GolfWatchApp.tsx
@@ -17,6 +17,7 @@ import {
} from "../states/watch";
import GolfWatchAppGaming1v1 from "./GolfWatchApps/GolfWatchAppGaming1v1";
import GolfWatchAppGamingMultiplayer from "./GolfWatchApps/GolfWatchAppGamingMultiplayer";
+import GolfWatchAppLoading from "./GolfWatchApps/GolfWatchAppLoading";
import GolfWatchAppStarting from "./GolfWatchApps/GolfWatchAppStarting";
import GolfWatchAppWaiting1v1 from "./GolfWatchApps/GolfWatchAppWaiting1v1";
import GolfWatchAppWaitingMultiplayer from "./GolfWatchApps/GolfWatchAppWaitingMultiplayer";
@@ -106,7 +107,9 @@ export default function GolfWatchApp({ game }: Props) {
setRanking,
]);
- if (gameStateKind === "waiting") {
+ if (gameStateKind === "loading") {
+ return <GolfWatchAppLoading />;
+ } else if (gameStateKind === "waiting") {
return game.game_type === "1v1" ? (
<GolfWatchAppWaiting1v1
gameDisplayName={game.display_name}
@@ -139,7 +142,5 @@ export default function GolfWatchApp({ game }: Props) {
gameResult={null /* TODO */}
/>
);
- } else {
- return null;
}
}
diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppLoading.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppLoading.tsx
new file mode 100644
index 0000000..7169d24
--- /dev/null
+++ b/frontend/app/components/GolfWatchApps/GolfWatchAppLoading.tsx
@@ -0,0 +1,9 @@
+export default function GolfWatchAppLoading() {
+ return (
+ <div className="min-h-screen bg-gray-100 flex items-center justify-center">
+ <div className="text-center">
+ <div className="text-6xl font-bold text-black">読込中</div>
+ </div>
+ </div>
+ );
+}
diff --git a/frontend/app/routes/golf.$gameId.play.tsx b/frontend/app/routes/golf.$gameId.play.tsx
index dc8eb38..1ffe45e 100644
--- a/frontend/app/routes/golf.$gameId.play.tsx
+++ b/frontend/app/routes/golf.$gameId.play.tsx
@@ -9,7 +9,6 @@ import {
} from "../api/client";
import GolfPlayApp from "../components/GolfPlayApp";
import {
- setCurrentTimestampAtom,
setDurationSecondsAtom,
setGameStartedAtAtom,
setLatestGameStateAtom,
@@ -50,7 +49,6 @@ export default function GolfPlay() {
useLoaderData<typeof loader>();
useHydrateAtoms([
- [setCurrentTimestampAtom, undefined],
[setDurationSecondsAtom, game.duration_seconds],
[setGameStartedAtAtom, game.started_at ?? null],
[setLatestGameStateAtom, gameState],
diff --git a/frontend/app/routes/golf.$gameId.watch.tsx b/frontend/app/routes/golf.$gameId.watch.tsx
index 674abc4..42bde52 100644
--- a/frontend/app/routes/golf.$gameId.watch.tsx
+++ b/frontend/app/routes/golf.$gameId.watch.tsx
@@ -11,7 +11,6 @@ import {
import GolfWatchApp from "../components/GolfWatchApp";
import {
rankingAtom,
- setCurrentTimestampAtom,
setDurationSecondsAtom,
setGameStartedAtAtom,
setLatestGameStatesAtom,
@@ -60,7 +59,6 @@ export default function GolfWatch() {
useHydrateAtoms([
[rankingAtom, ranking],
- [setCurrentTimestampAtom, undefined],
[setDurationSecondsAtom, game.duration_seconds],
[setGameStartedAtAtom, game.started_at ?? null],
[setLatestGameStatesAtom, gameStates],
diff --git a/frontend/app/states/play.ts b/frontend/app/states/play.ts
index e7774cb..3acefbf 100644
--- a/frontend/app/states/play.ts
+++ b/frontend/app/states/play.ts
@@ -6,7 +6,12 @@ export const setGameStartedAtAtom = atom(null, (_, set, value: number | null) =>
set(gameStartedAtAtom, value),
);
-export type GameStateKind = "waiting" | "starting" | "gaming" | "finished";
+export type GameStateKind =
+ | "loading"
+ | "waiting"
+ | "starting"
+ | "gaming"
+ | "finished";
type ExecutionStatus = components["schemas"]["ExecutionStatus"];
type LatestGameState = components["schemas"]["LatestGameState"];
@@ -16,9 +21,12 @@ export const gameStateKindAtom = atom<GameStateKind>((get) => {
return "waiting";
}
+ const now = get(currentTimestampAtom);
+ if (!now) {
+ return "loading";
+ }
const durationSeconds = get(durationSecondsAtom);
const finishedAt = startedAt + durationSeconds;
- const now = get(currentTimestampAtom);
if (now < startedAt) {
return "starting";
} else if (now < finishedAt) {
@@ -28,7 +36,7 @@ export const gameStateKindAtom = atom<GameStateKind>((get) => {
}
});
-const currentTimestampAtom = atom(0);
+const currentTimestampAtom = atom<number | null>(null);
export const setCurrentTimestampAtom = atom(null, (_, set) =>
set(currentTimestampAtom, Math.floor(Date.now() / 1000)),
);
@@ -44,6 +52,9 @@ export const startingLeftTimeSecondsAtom = atom<number | null>((get) => {
return null;
}
const currentTimestamp = get(currentTimestampAtom);
+ if (currentTimestamp === null) {
+ return null;
+ }
return Math.max(0, startedAt - currentTimestamp);
});
@@ -55,6 +66,9 @@ export const gamingLeftTimeSecondsAtom = atom<number | null>((get) => {
const durationSeconds = get(durationSecondsAtom);
const finishedAt = startedAt + durationSeconds;
const currentTimestamp = get(currentTimestampAtom);
+ if (currentTimestamp === null) {
+ return null;
+ }
return Math.min(durationSeconds, Math.max(0, finishedAt - currentTimestamp));
});
@@ -72,13 +86,12 @@ export const scoreAtom = atom<number | null>((get) => {
return get(rawScoreAtom);
});
-const rawIsSubmittingCodeAtom = atom(false);
-export const isSubmittingCodeAtom = atom((get) => get(rawIsSubmittingCodeAtom));
+const isSubmittingCodeAtom = atom(false);
export const handleSubmitCodePreAtom = atom(null, (_, set) => {
- set(rawIsSubmittingCodeAtom, true);
+ set(isSubmittingCodeAtom, true);
});
export const handleSubmitCodePostAtom = atom(null, (_, set) => {
- set(rawIsSubmittingCodeAtom, false);
+ set(isSubmittingCodeAtom, false);
});
export const setLatestGameStateAtom = atom(
diff --git a/frontend/app/states/watch.ts b/frontend/app/states/watch.ts
index d3cc723..463c2cd 100644
--- a/frontend/app/states/watch.ts
+++ b/frontend/app/states/watch.ts
@@ -6,7 +6,12 @@ export const setGameStartedAtAtom = atom(null, (_, set, value: number | null) =>
set(gameStartedAtAtom, value),
);
-export type GameStateKind = "waiting" | "starting" | "gaming" | "finished";
+export type GameStateKind =
+ | "loading"
+ | "waiting"
+ | "starting"
+ | "gaming"
+ | "finished";
type LatestGameState = components["schemas"]["LatestGameState"];
type RankingEntry = components["schemas"]["RankingEntry"];
@@ -16,9 +21,12 @@ export const gameStateKindAtom = atom<GameStateKind>((get) => {
return "waiting";
}
+ const now = get(currentTimestampAtom);
+ if (!now) {
+ return "loading";
+ }
const durationSeconds = get(durationSecondsAtom);
const finishedAt = startedAt + durationSeconds;
- const now = get(currentTimestampAtom);
if (now < startedAt) {
return "starting";
} else if (now < finishedAt) {
@@ -28,7 +36,7 @@ export const gameStateKindAtom = atom<GameStateKind>((get) => {
}
});
-const currentTimestampAtom = atom(0);
+const currentTimestampAtom = atom<number | null>(null);
export const setCurrentTimestampAtom = atom(null, (_, set) =>
set(currentTimestampAtom, Math.floor(Date.now() / 1000)),
);
@@ -44,6 +52,9 @@ export const startingLeftTimeSecondsAtom = atom<number | null>((get) => {
return null;
}
const currentTimestamp = get(currentTimestampAtom);
+ if (currentTimestamp === null) {
+ return null;
+ }
return Math.max(0, startedAt - currentTimestamp);
});
@@ -55,6 +66,9 @@ export const gamingLeftTimeSecondsAtom = atom<number | null>((get) => {
const durationSeconds = get(durationSecondsAtom);
const finishedAt = startedAt + durationSeconds;
const currentTimestamp = get(currentTimestampAtom);
+ if (currentTimestamp === null) {
+ return null;
+ }
return Math.min(durationSeconds, Math.max(0, finishedAt - currentTimestamp));
});