From c889a9ad33374eae03cec5b0358d79016d6fd97e Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 8 Mar 2025 10:32:05 +0900 Subject: show ranking --- frontend/app/components/GolfWatchApp.tsx | 66 +++++++---- .../GolfWatchApps/GolfWatchAppGaming.tsx | 128 --------------------- .../GolfWatchApps/GolfWatchAppGaming1v1.tsx | 128 +++++++++++++++++++++ .../GolfWatchAppGamingMultiplayer.tsx | 102 ++++++++++++++++ .../GolfWatchApps/GolfWatchAppWaiting.tsx | 27 ----- .../GolfWatchApps/GolfWatchAppWaiting1v1.tsx | 27 +++++ .../GolfWatchAppWaitingMultiplayer.tsx | 15 +++ 7 files changed, 313 insertions(+), 180 deletions(-) delete mode 100644 frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx create mode 100644 frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx create mode 100644 frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx delete mode 100644 frontend/app/components/GolfWatchApps/GolfWatchAppWaiting.tsx create mode 100644 frontend/app/components/GolfWatchApps/GolfWatchAppWaiting1v1.tsx create mode 100644 frontend/app/components/GolfWatchApps/GolfWatchAppWaitingMultiplayer.tsx (limited to 'frontend/app/components') diff --git a/frontend/app/components/GolfWatchApp.tsx b/frontend/app/components/GolfWatchApp.tsx index fe71932..402884f 100644 --- a/frontend/app/components/GolfWatchApp.tsx +++ b/frontend/app/components/GolfWatchApp.tsx @@ -1,4 +1,4 @@ -import { useAtomValue, useSetAtom } from "jotai"; +import { useAtom, useAtomValue, useSetAtom } from "jotai"; import { useContext, useEffect, useState } from "react"; import { useTimer } from "react-use-precision-timer"; import { @@ -10,14 +10,16 @@ import { import type { components } from "../api/schema"; import { gameStateKindAtom, + rankingAtom, setCurrentTimestampAtom, setGameStartedAtAtom, setLatestGameStatesAtom, - setRankingAtom, } from "../states/watch"; -import GolfWatchAppGaming from "./GolfWatchApps/GolfWatchAppGaming"; +import GolfWatchAppGaming1v1 from "./GolfWatchApps/GolfWatchAppGaming1v1"; +import GolfWatchAppGamingMultiplayer from "./GolfWatchApps/GolfWatchAppGamingMultiplayer"; import GolfWatchAppStarting from "./GolfWatchApps/GolfWatchAppStarting"; -import GolfWatchAppWaiting from "./GolfWatchApps/GolfWatchAppWaiting"; +import GolfWatchAppWaiting1v1 from "./GolfWatchApps/GolfWatchAppWaiting1v1"; +import GolfWatchAppWaitingMultiplayer from "./GolfWatchApps/GolfWatchAppWaitingMultiplayer"; type Game = components["schemas"]["Game"]; @@ -32,23 +34,27 @@ export default function GolfWatchApp({ game }: Props) { const setGameStartedAt = useSetAtom(setGameStartedAtAtom); const setCurrentTimestamp = useSetAtom(setCurrentTimestampAtom); const setLatestGameStates = useSetAtom(setLatestGameStatesAtom); - const setRanking = useSetAtom(setRankingAtom); + const [ranking, setRanking] = useAtom(rankingAtom); useTimer({ delay: 1000, startImmediately: true }, setCurrentTimestamp); - const playerA = game.main_players[0]!; - const playerB = game.main_players[1]!; + 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 playerProfileA = playerA + ? { + id: playerA.user_id, + displayName: playerA.display_name, + iconPath: playerA.icon_path ?? null, + } + : null; + const playerProfileB = playerB + ? { + id: playerB.user_id, + displayName: playerB.display_name, + iconPath: playerB.icon_path ?? null, + } + : null; const [isDataPolling, setIsDataPolling] = useState(false); @@ -101,21 +107,31 @@ export default function GolfWatchApp({ game }: Props) { ]); if (gameStateKind === "waiting") { - return ( - + ) : ( + ); } else if (gameStateKind === "starting") { return ; } else if (gameStateKind === "gaming" || gameStateKind === "finished") { - return ( - + ) : ( + { - const m = Math.floor(leftTimeSeconds / 60); - const s = leftTimeSeconds % 60; - return `${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`; - })(); - - const topBg = gameResult - ? gameResult === "winA" - ? "bg-orange-400" - : gameResult === "winB" - ? "bg-purple-400" - : "bg-pink-500" - : "bg-sky-600"; - - return ( -
-
-
-
- {playerProfileA.iconPath && ( - - )} -
-
Player 1
-
{playerProfileA.displayName}
-
-
-
{scoreA}
-
-
-
{gameDisplayName}
-
- {gameResult - ? gameResult === "winA" - ? `勝者 ${playerProfileA.displayName}` - : gameResult === "winB" - ? `勝者 ${playerProfileB.displayName}` - : "引き分け" - : leftTime} -
-
-
-
{scoreB}
-
-
-
Player 2
-
{playerProfileB.displayName}
-
- {playerProfileB.iconPath && ( - - )} -
-
-
- -
- -
-
- - -
-
-
- {problemTitle} -
- {problemDescription} -
-
- -
-
- ); -} diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx new file mode 100644 index 0000000..033186c --- /dev/null +++ b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx @@ -0,0 +1,128 @@ +import { useAtomValue } from "jotai"; +import { + gamingLeftTimeSecondsAtom, + latestGameStatesAtom, +} from "../../states/watch"; +import type { PlayerProfile } from "../../types/PlayerProfile"; +import BorderedContainer from "../BorderedContainer"; +import CodeBlock from "../Gaming/CodeBlock"; +import ScoreBar from "../Gaming/ScoreBar"; +import SubmitResult from "../Gaming/SubmitResult"; +import UserIcon from "../UserIcon"; + +type Props = { + gameDisplayName: string; + playerProfileA: PlayerProfile; + playerProfileB: PlayerProfile; + problemTitle: string; + problemDescription: string; + gameResult: "winA" | "winB" | "draw" | null; +}; + +export default function GolfWatchAppGaming1v1({ + gameDisplayName, + playerProfileA, + playerProfileB, + problemTitle, + problemDescription, + gameResult, +}: Props) { + const leftTimeSeconds = useAtomValue(gamingLeftTimeSecondsAtom)!; + const latestGameStates = useAtomValue(latestGameStatesAtom); + + const stateA = latestGameStates[playerProfileA.id]; + const codeA = stateA?.code ?? ""; + const scoreA = stateA?.score ?? null; + const statusA = stateA?.status ?? "none"; + const stateB = latestGameStates[playerProfileB.id]; + const codeB = stateB?.code ?? ""; + const scoreB = stateB?.score ?? null; + const statusB = stateB?.status ?? "none"; + + const leftTime = (() => { + const m = Math.floor(leftTimeSeconds / 60); + const s = leftTimeSeconds % 60; + return `${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`; + })(); + + const topBg = gameResult + ? gameResult === "winA" + ? "bg-orange-400" + : gameResult === "winB" + ? "bg-purple-400" + : "bg-pink-500" + : "bg-sky-600"; + + return ( +
+
+
+
+ {playerProfileA.iconPath && ( + + )} +
+
Player 1
+
{playerProfileA.displayName}
+
+
+
{scoreA}
+
+
+
{gameDisplayName}
+
+ {gameResult + ? gameResult === "winA" + ? `勝者 ${playerProfileA.displayName}` + : gameResult === "winB" + ? `勝者 ${playerProfileB.displayName}` + : "引き分け" + : leftTime} +
+
+
+
{scoreB}
+
+
+
Player 2
+
{playerProfileB.displayName}
+
+ {playerProfileB.iconPath && ( + + )} +
+
+
+ +
+ +
+
+ + +
+
+
+ {problemTitle} +
+ {problemDescription} +
+
+ +
+
+ ); +} diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx new file mode 100644 index 0000000..b6d2ac3 --- /dev/null +++ b/frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx @@ -0,0 +1,102 @@ +import { useAtomValue } from "jotai"; +import type { components } from "../../api/schema"; +import { gamingLeftTimeSecondsAtom } from "../../states/watch"; +import BorderedContainer from "../BorderedContainer"; + +type RankingEntry = components["schemas"]["RankingEntry"]; + +type Props = { + gameDisplayName: string; + ranking: RankingEntry[]; + problemTitle: string; + problemDescription: string; + gameResult: "winA" | "winB" | "draw" | null; +}; + +export default function GolfWatchAppGamingMultiplayer({ + gameDisplayName, + ranking, + problemTitle, + problemDescription, + gameResult, +}: Props) { + const leftTimeSeconds = useAtomValue(gamingLeftTimeSecondsAtom)!; + + const leftTime = (() => { + const m = Math.floor(leftTimeSeconds / 60); + const s = leftTimeSeconds % 60; + return `${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`; + })(); + + const topBg = gameResult + ? gameResult === "winA" + ? "bg-orange-400" + : gameResult === "winB" + ? "bg-purple-400" + : "bg-pink-500" + : "bg-sky-600"; + + return ( +
+
+
+
+
{gameDisplayName}
+
{leftTime}
+
+
+
+
+
+
+
+ {problemTitle} +
+ {problemDescription} +
+
+
+ + + + + + + + + + {ranking.map((entry, index) => ( + + + + + + ))} + +
+ 順位 + + 名前 + + スコア +
+ {index + 1} + + {entry.player.display_name} + + {entry.score} +
+
+
+
+ ); +} diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppWaiting.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppWaiting.tsx deleted file mode 100644 index c2a5431..0000000 --- a/frontend/app/components/GolfWatchApps/GolfWatchAppWaiting.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import type { PlayerProfile } from "../../types/PlayerProfile"; -import PlayerNameAndIcon from "../PlayerNameAndIcon"; - -type Props = { - gameDisplayName: string; - playerProfileA: PlayerProfile; - playerProfileB: PlayerProfile; -}; - -export default function GolfWatchAppWaiting({ - gameDisplayName, - playerProfileA, - playerProfileB, -}: Props) { - return ( -
-
-
{gameDisplayName}
-
-
- -
vs.
- -
-
- ); -} diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppWaiting1v1.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppWaiting1v1.tsx new file mode 100644 index 0000000..fb315ff --- /dev/null +++ b/frontend/app/components/GolfWatchApps/GolfWatchAppWaiting1v1.tsx @@ -0,0 +1,27 @@ +import type { PlayerProfile } from "../../types/PlayerProfile"; +import PlayerNameAndIcon from "../PlayerNameAndIcon"; + +type Props = { + gameDisplayName: string; + playerProfileA: PlayerProfile; + playerProfileB: PlayerProfile; +}; + +export default function GolfWatchAppWaiting1v1({ + gameDisplayName, + playerProfileA, + playerProfileB, +}: Props) { + return ( +
+
+
{gameDisplayName}
+
+
+ +
vs.
+ +
+
+ ); +} diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppWaitingMultiplayer.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppWaitingMultiplayer.tsx new file mode 100644 index 0000000..13bcc10 --- /dev/null +++ b/frontend/app/components/GolfWatchApps/GolfWatchAppWaitingMultiplayer.tsx @@ -0,0 +1,15 @@ +type Props = { + gameDisplayName: string; +}; + +export default function GolfWatchAppWaitingMultiplayer({ + gameDisplayName, +}: Props) { + return ( +
+
+
{gameDisplayName}
+
+
+ ); +} -- cgit v1.2.3-70-g09d2