aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-03-15 21:10:51 +0900
committernsfisis <nsfisis@gmail.com>2025-03-15 21:10:51 +0900
commit35d1be206c6be675d92839cfa209fceb5d1b6db9 (patch)
tree31734172b78f11272c5267bf7bae1541411ce553
parent27168df997c298e871d34e58fdc726bf2e8a4954 (diff)
downloadphperkaigi-2025-albatross-35d1be206c6be675d92839cfa209fceb5d1b6db9.tar.gz
phperkaigi-2025-albatross-35d1be206c6be675d92839cfa209fceb5d1b6db9.tar.zst
phperkaigi-2025-albatross-35d1be206c6be675d92839cfa209fceb5d1b6db9.zip
feat(frontend): show sample code in watch page
-rw-r--r--frontend/app/components/BorderedContainerWithCaption.tsx21
-rw-r--r--frontend/app/components/Gaming/Problem.tsx24
-rw-r--r--frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx24
-rw-r--r--frontend/app/components/GolfWatchApp.tsx2
-rw-r--r--frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx19
-rw-r--r--frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx21
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">