diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-03-15 21:10:51 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-03-15 21:10:51 +0900 |
| commit | 35d1be206c6be675d92839cfa209fceb5d1b6db9 (patch) | |
| tree | 31734172b78f11272c5267bf7bae1541411ce553 | |
| parent | 27168df997c298e871d34e58fdc726bf2e8a4954 (diff) | |
| download | iosdc-japan-2025-albatross-35d1be206c6be675d92839cfa209fceb5d1b6db9.tar.gz iosdc-japan-2025-albatross-35d1be206c6be675d92839cfa209fceb5d1b6db9.tar.zst iosdc-japan-2025-albatross-35d1be206c6be675d92839cfa209fceb5d1b6db9.zip | |
feat(frontend): show sample code in watch page
6 files changed, 69 insertions, 42 deletions
diff --git a/frontend/app/components/BorderedContainerWithCaption.tsx b/frontend/app/components/BorderedContainerWithCaption.tsx new file mode 100644 index 0000000..0fee425 --- /dev/null +++ b/frontend/app/components/BorderedContainerWithCaption.tsx @@ -0,0 +1,21 @@ +import React from "react"; +import BorderedContainer from "./BorderedContainer"; + +type Props = { + caption: string; + children: React.ReactNode; +}; + +export default function BorderedContainerWithCaption({ + caption, + children, +}: Props) { + return ( + <BorderedContainer> + <div className="flex flex-col gap-4"> + <h2 className="text-center text-lg">{caption}</h2> + {children} + </div> + </BorderedContainer> + ); +} diff --git a/frontend/app/components/Gaming/Problem.tsx b/frontend/app/components/Gaming/Problem.tsx new file mode 100644 index 0000000..1584a5a --- /dev/null +++ b/frontend/app/components/Gaming/Problem.tsx @@ -0,0 +1,24 @@ +import BorderedContainerWithCaption from "../BorderedContainerWithCaption"; +import CodeBlock from "./CodeBlock"; + +type Props = { + title: string; + description: string; + sampleCode: string; +}; + +export default function Problem({ title, description, sampleCode }: Props) { + return ( + <div className="p-4 flex flex-col gap-4"> + <div className="text-center text-xl font-bold">{title}</div> + <BorderedContainerWithCaption caption="問題"> + <pre className="text-gray-700 whitespace-pre-wrap break-words"> + {description} + </pre> + </BorderedContainerWithCaption> + <BorderedContainerWithCaption caption="サンプルコード"> + <CodeBlock code={sampleCode} language="php" /> + </BorderedContainerWithCaption> + </div> + ); +} diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx index ec92556..5c5e149 100644 --- a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx +++ b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx @@ -8,8 +8,7 @@ import { statusAtom, } from "../../states/play"; import type { PlayerProfile } from "../../types/PlayerProfile"; -import BorderedContainer from "../BorderedContainer"; -import CodeBlock from "../Gaming/CodeBlock"; +import Problem from "../Gaming/Problem"; import SubmitResult from "../Gaming/SubmitResult"; import UserIcon from "../UserIcon"; @@ -81,22 +80,11 @@ export default function GolfPlayAppGaming({ </Link> </div> <div className="grow grid grid-cols-3 divide-x divide-gray-300"> - <div className="p-4"> - <div className="mb-2 text-xl font-bold">{problemTitle}</div> - <div className="p-2 flex flex-col gap-4"> - <BorderedContainer> - <pre className="text-gray-700 whitespace-pre-wrap break-words"> - {problemDescription} - </pre> - </BorderedContainer> - <BorderedContainer> - <div> - <h2>サンプルコード</h2> - <CodeBlock code={sampleCode} language="php" /> - </div> - </BorderedContainer> - </div> - </div> + <Problem + title={problemTitle} + description={problemDescription} + sampleCode={sampleCode} + /> <div className="p-4"> <textarea ref={textareaRef} diff --git a/frontend/app/components/GolfWatchApp.tsx b/frontend/app/components/GolfWatchApp.tsx index 402884f..919fa4f 100644 --- a/frontend/app/components/GolfWatchApp.tsx +++ b/frontend/app/components/GolfWatchApp.tsx @@ -126,6 +126,7 @@ export default function GolfWatchApp({ game }: Props) { playerProfileB={playerProfileB!} problemTitle={game.problem.title} problemDescription={game.problem.description} + sampleCode={game.problem.sample_code} gameResult={null /* TODO */} /> ) : ( @@ -134,6 +135,7 @@ export default function GolfWatchApp({ game }: Props) { ranking={ranking} problemTitle={game.problem.title} problemDescription={game.problem.description} + sampleCode={game.problem.sample_code} gameResult={null /* TODO */} /> ); diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx index ec18bbc..d9ee800 100644 --- a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx +++ b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx @@ -4,8 +4,8 @@ import { latestGameStatesAtom, } from "../../states/watch"; import type { PlayerProfile } from "../../types/PlayerProfile"; -import BorderedContainer from "../BorderedContainer"; import CodeBlock from "../Gaming/CodeBlock"; +import Problem from "../Gaming/Problem"; import ScoreBar from "../Gaming/ScoreBar"; import SubmitResult from "../Gaming/SubmitResult"; import UserIcon from "../UserIcon"; @@ -16,6 +16,7 @@ type Props = { playerProfileB: PlayerProfile; problemTitle: string; problemDescription: string; + sampleCode: string; gameResult: "winA" | "winB" | "draw" | null; }; @@ -25,6 +26,7 @@ export default function GolfWatchAppGaming1v1({ playerProfileB, problemTitle, problemDescription, + sampleCode, gameResult, }: Props) { const leftTimeSeconds = useAtomValue(gamingLeftTimeSecondsAtom)!; @@ -114,16 +116,11 @@ export default function GolfWatchAppGaming1v1({ <SubmitResult status={statusA} /> <SubmitResult status={statusB} /> </div> - <div> - <div className="mb-2 text-center text-xl font-bold"> - {problemTitle} - </div> - <BorderedContainer> - <pre className="text-gray-700 whitespace-pre-wrap break-words"> - {problemDescription} - </pre> - </BorderedContainer> - </div> + <Problem + title={problemTitle} + description={problemDescription} + sampleCode={sampleCode} + /> </div> <CodeBlock code={codeB} language="php" /> </div> diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx index 758c589..b382850 100644 --- a/frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx +++ b/frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx @@ -1,7 +1,7 @@ import { useAtomValue } from "jotai"; import type { components } from "../../api/schema"; import { gamingLeftTimeSecondsAtom } from "../../states/watch"; -import BorderedContainer from "../BorderedContainer"; +import Problem from "../Gaming/Problem"; import UserLabel from "../UserLabel"; type RankingEntry = components["schemas"]["RankingEntry"]; @@ -11,6 +11,7 @@ type Props = { ranking: RankingEntry[]; problemTitle: string; problemDescription: string; + sampleCode: string; gameResult: "winA" | "winB" | "draw" | null; }; @@ -19,6 +20,7 @@ export default function GolfWatchAppGamingMultiplayer({ ranking, problemTitle, problemDescription, + sampleCode, gameResult, }: Props) { const leftTimeSeconds = useAtomValue(gamingLeftTimeSecondsAtom)!; @@ -48,18 +50,11 @@ export default function GolfWatchAppGamingMultiplayer({ <div className="font-bold flex justify-between my-auto"></div> </div> <div className="grow grid grid-cols-2 p-4 gap-4"> - <div className="flex flex-col gap-4"> - <div> - <div className="mb-2 text-center text-xl font-bold"> - {problemTitle} - </div> - <BorderedContainer> - <pre className="text-gray-700 whitespace-pre-wrap break-words"> - {problemDescription} - </pre> - </BorderedContainer> - </div> - </div> + <Problem + title={problemTitle} + description={problemDescription} + sampleCode={sampleCode} + /> <div> <table className="min-w-full divide-y divide-gray-200"> <thead className="bg-gray-50"> |
