diff options
| author | nsfisis <nsfisis@gmail.com> | 2024-08-18 00:38:07 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2024-08-18 01:46:02 +0900 |
| commit | ad42f43d1c3c8f0da0ac31b8016e2f20f1765720 (patch) | |
| tree | 09567462299eed859bb0f2170ee2602825c23ca0 /frontend | |
| parent | 7653eb2b28911a0479b3b673c9b63fd490aedb6b (diff) | |
| download | iosdc-japan-2025-albatross-ad42f43d1c3c8f0da0ac31b8016e2f20f1765720.tar.gz iosdc-japan-2025-albatross-ad42f43d1c3c8f0da0ac31b8016e2f20f1765720.tar.zst iosdc-japan-2025-albatross-ad42f43d1c3c8f0da0ac31b8016e2f20f1765720.zip | |
refactor(frontend): extract components for gaming page
Diffstat (limited to 'frontend')
| -rw-r--r-- | frontend/app/components/Gaming/CodeBlock.tsx | 11 | ||||
| -rw-r--r-- | frontend/app/components/Gaming/ExecStatusIndicatorIcon.tsx (renamed from frontend/app/components/ExecStatusIndicatorIcon.tsx) | 2 | ||||
| -rw-r--r-- | frontend/app/components/Gaming/ScoreBar.tsx | 25 | ||||
| -rw-r--r-- | frontend/app/components/Gaming/SubmitResult.tsx | 56 | ||||
| -rw-r--r-- | frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx | 52 | ||||
| -rw-r--r-- | frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx | 120 |
6 files changed, 118 insertions, 148 deletions
diff --git a/frontend/app/components/Gaming/CodeBlock.tsx b/frontend/app/components/Gaming/CodeBlock.tsx new file mode 100644 index 0000000..20cd425 --- /dev/null +++ b/frontend/app/components/Gaming/CodeBlock.tsx @@ -0,0 +1,11 @@ +type Props = { + code: string; +}; + +export default function CodeBlock({ code }: Props) { + return ( + <pre className="bg-white resize-none h-full w-full rounded-lg border border-gray-300 p-2"> + <code>{code}</code> + </pre> + ); +} diff --git a/frontend/app/components/ExecStatusIndicatorIcon.tsx b/frontend/app/components/Gaming/ExecStatusIndicatorIcon.tsx index 5277bfa..8daf48c 100644 --- a/frontend/app/components/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 "../../models/ExecResult"; type Props = { status: ExecResultStatus; diff --git a/frontend/app/components/Gaming/ScoreBar.tsx b/frontend/app/components/Gaming/ScoreBar.tsx new file mode 100644 index 0000000..4eac3ad --- /dev/null +++ b/frontend/app/components/Gaming/ScoreBar.tsx @@ -0,0 +1,25 @@ +type Props = { + scoreA: number | null; + scoreB: number | null; + bgA: string; + bgB: string; +}; + +export default function ScoreBar({ scoreA, scoreB, bgA, bgB }: Props) { + let scoreRatio; + if (scoreA === null && scoreB === null) { + scoreRatio = 50; + } else if (scoreA === null) { + scoreRatio = 0; + } else if (scoreB === null) { + scoreRatio = 100; + } else { + scoreRatio = (scoreB / (scoreA + scoreB)) * 100; + } + + return ( + <div className={`w-full ${bgB}`}> + <div className={`h-6 ${bgA}`} style={{ width: `${scoreRatio}%` }}></div> + </div> + ); +} diff --git a/frontend/app/components/Gaming/SubmitResult.tsx b/frontend/app/components/Gaming/SubmitResult.tsx new file mode 100644 index 0000000..ae83e92 --- /dev/null +++ b/frontend/app/components/Gaming/SubmitResult.tsx @@ -0,0 +1,56 @@ +import { faArrowDown } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import React from "react"; +import type { SubmitResult } from "../../models/SubmitResult"; +import BorderedContainer from "../BorderedContainer"; +import SubmitStatusLabel from "../SubmitStatusLabel"; +import ExecStatusIndicatorIcon from "./ExecStatusIndicatorIcon"; + +type Props = { + result: SubmitResult; + submitButton?: React.ReactNode; +}; + +export default function SubmitResult({ result, submitButton }: Props) { + return ( + <div className="flex flex-col gap-2"> + <div className="flex"> + {submitButton} + <div className="grow font-bold text-xl text-center"> + <SubmitStatusLabel status={result.status} /> + </div> + </div> + <ul className="flex flex-col gap-2"> + {result.execResults.map((r, idx) => ( + <li key={r.testcase_id ?? -1} className="flex gap-2"> + <div className="flex flex-col gap-2 p-2"> + <div className="w-6"> + <ExecStatusIndicatorIcon status={r.status} /> + </div> + {idx !== result.execResults.length - 1 && ( + <div> + <FontAwesomeIcon + icon={faArrowDown} + fixedWidth + className="text-gray-500" + /> + </div> + )} + </div> + <div className="grow p-2"> + <BorderedContainer> + <div className="font-semibold">{r.label}</div> + <div> + <code> + {r.stdout} + {r.stderr} + </code> + </div> + </BorderedContainer> + </div> + </li> + ))} + </ul> + </div> + ); +} diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx index a6c4550..e9139ba 100644 --- a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx +++ b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx @@ -1,12 +1,9 @@ -import { faArrowDown } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Link } from "@remix-run/react"; import React, { useRef } from "react"; import SubmitButton from "../../components/SubmitButton"; import type { PlayerInfo } from "../../models/PlayerInfo"; import BorderedContainer from "../BorderedContainer"; -import ExecStatusIndicatorIcon from "../ExecStatusIndicatorIcon"; -import SubmitStatusLabel from "../SubmitStatusLabel"; +import SubmitResult from "../Gaming/SubmitResult"; type Props = { gameDisplayName: string; @@ -92,44 +89,15 @@ export default function GolfPlayAppGaming({ className="resize-none h-full w-full rounded-lg border border-gray-300 p-2 focus:outline-none focus:ring-2 focus:ring-gray-400 transition duration-300" ></textarea> </div> - <div className="p-4 flex flex-col gap-4"> - <div className="flex"> - <SubmitButton onClick={handleSubmitButtonClick}>提出</SubmitButton> - <div className="grow font-bold text-xl text-center m-1"> - <SubmitStatusLabel status={playerInfo.submitResult.status} /> - </div> - </div> - <ul className="flex flex-col gap-2"> - {playerInfo.submitResult.execResults.map((r, idx) => ( - <li key={r.testcase_id ?? -1} className="flex gap-2"> - <div className="flex flex-col gap-2 p-2"> - <div className="w-6"> - <ExecStatusIndicatorIcon status={r.status} /> - </div> - {idx !== playerInfo.submitResult.execResults.length - 1 && ( - <div> - <FontAwesomeIcon - icon={faArrowDown} - fixedWidth - className="text-gray-500" - /> - </div> - )} - </div> - <div className="grow p-2 overflow-x-scroll"> - <BorderedContainer> - <div className="font-semibold">{r.label}</div> - <div> - <code> - {r.stdout} - {r.stderr} - </code> - </div> - </BorderedContainer> - </div> - </li> - ))} - </ul> + <div className="p-4"> + <SubmitResult + result={playerInfo.submitResult} + submitButton={ + <SubmitButton onClick={handleSubmitButtonClick}> + 提出 + </SubmitButton> + } + /> </div> </div> </div> diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx index 63c232b..d17c2dc 100644 --- a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx +++ b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx @@ -1,9 +1,7 @@ -import { faArrowDown } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { PlayerInfo } from "../../models/PlayerInfo"; -import BorderedContainer from "../BorderedContainer"; -import ExecStatusIndicatorIcon from "../ExecStatusIndicatorIcon"; -import SubmitStatusLabel from "../SubmitStatusLabel"; +import CodeBlock from "../Gaming/CodeBlock"; +import ScoreBar from "../Gaming/ScoreBar"; +import SubmitResult from "../Gaming/SubmitResult"; type Props = { gameDisplayName: string; @@ -29,20 +27,6 @@ export default function GolfWatchAppGaming({ return `${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`; })(); - const scoreRatio = (() => { - const scoreA = playerInfoA.score; - const scoreB = playerInfoB.score; - if (scoreA === null && scoreB === null) { - return 50; - } else if (scoreA === null) { - return 0; - } else if (scoreB === null) { - return 100; - } else { - return (scoreB / (scoreA + scoreB)) * 100; - } - })(); - return ( <div className="min-h-screen bg-gray-100 flex flex-col"> <div className="text-white bg-iosdc-japan grid grid-cols-3 px-4 py-2"> @@ -91,98 +75,24 @@ export default function GolfWatchAppGaming({ </div> </div> </div> - <div className="w-full bg-purple-400"> - <div - className="h-6 bg-orange-400" - style={{ width: `${scoreRatio}%` }} - ></div> - </div> + <ScoreBar + scoreA={playerInfoA.score} + scoreB={playerInfoB.score} + bgA="bg-orange-400" + bgB="bg-purple-400" + /> <div className="grow grid grid-cols-10 p-4 gap-4"> <div className="col-span-3"> - <pre className="bg-white resize-none h-full w-full rounded-lg border border-gray-300 p-2"> - <code>{playerInfoA.code}</code> - </pre> + <CodeBlock code={playerInfoA.code ?? ""} /> </div> - <div className="col-span-2 flex flex-col gap-4"> - <div className="flex"> - <div className="grow font-bold text-xl text-center"> - <SubmitStatusLabel status={playerInfoA.submitResult.status} /> - </div> - </div> - <ul className="flex flex-col gap-2"> - {playerInfoA.submitResult.execResults.map((r, idx) => ( - <li key={r.testcase_id ?? -1} className="flex gap-2"> - <div className="flex flex-col gap-2 p-2"> - <div className="w-6"> - <ExecStatusIndicatorIcon status={r.status} /> - </div> - {idx !== playerInfoA.submitResult.execResults.length - 1 && ( - <div> - <FontAwesomeIcon - icon={faArrowDown} - fixedWidth - className="text-gray-500" - /> - </div> - )} - </div> - <div className="grow p-2 overflow-x-scroll"> - <BorderedContainer> - <div className="font-semibold">{r.label}</div> - <div> - <code> - {r.stdout} - {r.stderr} - </code> - </div> - </BorderedContainer> - </div> - </li> - ))} - </ul> + <div className="col-span-2"> + <SubmitResult result={playerInfoA.submitResult} /> </div> - <div className="col-span-2 flex flex-col gap-4"> - <div className="flex"> - <div className="grow font-bold text-xl text-center"> - <SubmitStatusLabel status={playerInfoB.submitResult.status} /> - </div> - </div> - <ul className="flex flex-col gap-2"> - {playerInfoB.submitResult.execResults.map((r, idx) => ( - <li key={r.testcase_id ?? -1} className="flex gap-2"> - <div className="flex flex-col gap-2 p-2"> - <div className="w-6"> - <ExecStatusIndicatorIcon status={r.status} /> - </div> - {idx !== playerInfoB.submitResult.execResults.length - 1 && ( - <div> - <FontAwesomeIcon - icon={faArrowDown} - fixedWidth - className="text-gray-500" - /> - </div> - )} - </div> - <div className="grow p-2 overflow-x-scroll"> - <BorderedContainer> - <div className="font-semibold">{r.label}</div> - <div> - <code> - {r.stdout} - {r.stderr} - </code> - </div> - </BorderedContainer> - </div> - </li> - ))} - </ul> + <div className="col-span-2"> + <SubmitResult result={playerInfoB.submitResult} /> </div> <div className="col-span-3"> - <pre className="bg-white resize-none h-full w-full rounded-lg border border-gray-300 p-2"> - <code>{playerInfoB.code}</code> - </pre> + <CodeBlock code={playerInfoB.code ?? ""} /> </div> </div> </div> |
