aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend/app/components/GolfPlayApps
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-03-06 02:18:40 +0900
committernsfisis <nsfisis@gmail.com>2026-03-06 02:18:40 +0900
commit46f9ba5d8c295454381655e6ec02ad3cf8bd79db (patch)
treec54719cb129ee05f96c4898219588062f71daa36 /frontend/app/components/GolfPlayApps
parent27f509ccf4fbfeaa1bc2580ae2251461dc44ebfa (diff)
downloadphperkaigi-2026-albatross-46f9ba5d8c295454381655e6ec02ad3cf8bd79db.tar.gz
phperkaigi-2026-albatross-46f9ba5d8c295454381655e6ec02ad3cf8bd79db.tar.zst
phperkaigi-2026-albatross-46f9ba5d8c295454381655e6ec02ad3cf8bd79db.zip
style: switch from tab to space indentation in frontend and worker/php
Update biome.json indentStyle from "tab" to "space" and reformat all files in both workspaces. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'frontend/app/components/GolfPlayApps')
-rw-r--r--frontend/app/components/GolfPlayApps/GolfPlayAppGaming.test.tsx168
-rw-r--r--frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx272
-rw-r--r--frontend/app/components/GolfPlayApps/GolfPlayAppLoading.tsx14
-rw-r--r--frontend/app/components/GolfPlayApps/GolfPlayAppStarting.tsx24
-rw-r--r--frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx28
5 files changed, 253 insertions, 253 deletions
diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.test.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.test.tsx
index 2d51d66..ae5381b 100644
--- a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.test.tsx
+++ b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.test.tsx
@@ -5,103 +5,103 @@ import { cleanup, render, screen } from "@testing-library/react";
import { createStore, Provider } from "jotai";
import { afterEach, describe, expect, test } from "vitest";
import {
- setCurrentTimestampAtom,
- setDurationSecondsAtom,
- setGameStartedAtAtom,
- setLatestGameStateAtom,
+ setCurrentTimestampAtom,
+ setDurationSecondsAtom,
+ setGameStartedAtAtom,
+ setLatestGameStateAtom,
} from "../../states/play";
import GolfPlayAppGaming from "./GolfPlayAppGaming";
afterEach(() => {
- cleanup();
+ cleanup();
});
function createTestStore() {
- const store = createStore();
- const now = Math.floor(Date.now() / 1000);
- store.set(setCurrentTimestampAtom);
- store.set(setDurationSecondsAtom, 600);
- store.set(setGameStartedAtAtom, now - 60);
- store.set(setLatestGameStateAtom, {
- status: "none",
- code: "",
- score: null,
- best_score_submitted_at: null,
- });
- return store;
+ const store = createStore();
+ const now = Math.floor(Date.now() / 1000);
+ store.set(setCurrentTimestampAtom);
+ store.set(setDurationSecondsAtom, 600);
+ store.set(setGameStartedAtAtom, now - 60);
+ store.set(setLatestGameStateAtom, {
+ status: "none",
+ code: "",
+ score: null,
+ best_score_submitted_at: null,
+ });
+ return store;
}
const defaultProps = {
- gameDisplayName: "Test Game",
- playerProfile: {
- id: 1,
- displayName: "Test Player",
- iconPath: null,
- },
- problemTitle: "Test Problem",
- problemDescription: "Description",
- problemLanguage: "php" as const,
- sampleCode: "<?php echo 1;",
- initialCode: "",
- onCodeChange: () => {},
- onCodeSubmit: () => {},
- isFinished: false,
+ gameDisplayName: "Test Game",
+ playerProfile: {
+ id: 1,
+ displayName: "Test Player",
+ iconPath: null,
+ },
+ problemTitle: "Test Problem",
+ problemDescription: "Description",
+ problemLanguage: "php" as const,
+ sampleCode: "<?php echo 1;",
+ initialCode: "",
+ onCodeChange: () => {},
+ onCodeSubmit: () => {},
+ isFinished: false,
};
describe("GolfPlayAppGaming submission history", () => {
- test("shows placeholder row when no submissions", () => {
- const store = createTestStore();
- render(
- <Provider store={store}>
- <GolfPlayAppGaming {...defaultProps} submissions={[]} />
- </Provider>,
- );
- expect(screen.getByText("提出待ち")).toBeDefined();
- const dashes = screen.getAllByText("-");
- expect(dashes.length).toBe(3);
- });
+ test("shows placeholder row when no submissions", () => {
+ const store = createTestStore();
+ render(
+ <Provider store={store}>
+ <GolfPlayAppGaming {...defaultProps} submissions={[]} />
+ </Provider>,
+ );
+ expect(screen.getByText("提出待ち")).toBeDefined();
+ const dashes = screen.getAllByText("-");
+ expect(dashes.length).toBe(3);
+ });
- test("renders submission rows with status and code size", () => {
- const store = createTestStore();
- const submissions = [
- {
- submission_id: 1,
- game_id: 1,
- status: "success" as const,
- code: "<?php echo 1;",
- code_size: 7,
- created_at: 1740000000,
- },
- {
- submission_id: 2,
- game_id: 1,
- status: "wrong_answer" as const,
- code: "<?php echo 2;",
- code_size: 10,
- created_at: 1740000060,
- },
- ];
- render(
- <Provider store={store}>
- <GolfPlayAppGaming {...defaultProps} submissions={submissions} />
- </Provider>,
- );
- expect(screen.getByText("成功")).toBeDefined();
- expect(screen.getByText("テスト失敗")).toBeDefined();
- expect(screen.getByText("7")).toBeDefined();
- expect(screen.getByText("10")).toBeDefined();
- });
+ test("renders submission rows with status and code size", () => {
+ const store = createTestStore();
+ const submissions = [
+ {
+ submission_id: 1,
+ game_id: 1,
+ status: "success" as const,
+ code: "<?php echo 1;",
+ code_size: 7,
+ created_at: 1740000000,
+ },
+ {
+ submission_id: 2,
+ game_id: 1,
+ status: "wrong_answer" as const,
+ code: "<?php echo 2;",
+ code_size: 10,
+ created_at: 1740000060,
+ },
+ ];
+ render(
+ <Provider store={store}>
+ <GolfPlayAppGaming {...defaultProps} submissions={submissions} />
+ </Provider>,
+ );
+ expect(screen.getByText("成功")).toBeDefined();
+ expect(screen.getByText("テスト失敗")).toBeDefined();
+ expect(screen.getByText("7")).toBeDefined();
+ expect(screen.getByText("10")).toBeDefined();
+ });
- test("renders table headers", () => {
- const store = createTestStore();
- render(
- <Provider store={store}>
- <GolfPlayAppGaming {...defaultProps} submissions={[]} />
- </Provider>,
- );
- expect(screen.getByText("ステータス")).toBeDefined();
- expect(screen.getByText("スコア")).toBeDefined();
- expect(screen.getByText("提出時刻")).toBeDefined();
- expect(screen.getByText("コード")).toBeDefined();
- });
+ test("renders table headers", () => {
+ const store = createTestStore();
+ render(
+ <Provider store={store}>
+ <GolfPlayAppGaming {...defaultProps} submissions={[]} />
+ </Provider>,
+ );
+ expect(screen.getByText("ステータス")).toBeDefined();
+ expect(screen.getByText("スコア")).toBeDefined();
+ expect(screen.getByText("提出時刻")).toBeDefined();
+ expect(screen.getByText("コード")).toBeDefined();
+ });
});
diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx
index e590df0..3e1ab67 100644
--- a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx
+++ b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx
@@ -3,18 +3,18 @@ import React, { useRef, useState } from "react";
import { Link } from "wouter";
import type { components } from "../../api/schema";
import {
- calcCodeSize,
- gamingLeftTimeSecondsAtom,
- scoreAtom,
- statusAtom,
+ calcCodeSize,
+ gamingLeftTimeSecondsAtom,
+ scoreAtom,
+ statusAtom,
} from "../../states/play";
import type { PlayerProfile } from "../../types/PlayerProfile";
import type { SupportedLanguage } from "../../types/SupportedLanguage";
import BorderedContainer from "../BorderedContainer";
import CodePopover from "../Gaming/CodePopover";
import DataTable, {
- DataTableCell,
- formatUnixTimestamp,
+ DataTableCell,
+ formatUnixTimestamp,
} from "../Gaming/DataTable";
import LeftTime from "../Gaming/LeftTime";
import ProblemColumn from "../Gaming/ProblemColumn";
@@ -27,142 +27,142 @@ import UserIcon from "../UserIcon";
type Submission = components["schemas"]["Submission"];
type Props = {
- gameDisplayName: string;
- playerProfile: PlayerProfile;
- problemTitle: string;
- problemDescription: string;
- problemLanguage: SupportedLanguage;
- sampleCode: string;
- initialCode: string;
- onCodeChange: (code: string) => void;
- onCodeSubmit: (code: string) => void;
- isFinished: boolean;
- submissions: Submission[];
+ gameDisplayName: string;
+ playerProfile: PlayerProfile;
+ problemTitle: string;
+ problemDescription: string;
+ problemLanguage: SupportedLanguage;
+ sampleCode: string;
+ initialCode: string;
+ onCodeChange: (code: string) => void;
+ onCodeSubmit: (code: string) => void;
+ isFinished: boolean;
+ submissions: Submission[];
};
export default function GolfPlayAppGaming({
- gameDisplayName,
- playerProfile,
- problemTitle,
- problemDescription,
- problemLanguage,
- sampleCode,
- initialCode,
- onCodeChange,
- onCodeSubmit,
- isFinished,
- submissions,
+ gameDisplayName,
+ playerProfile,
+ problemTitle,
+ problemDescription,
+ problemLanguage,
+ sampleCode,
+ initialCode,
+ onCodeChange,
+ onCodeSubmit,
+ isFinished,
+ submissions,
}: Props) {
- const leftTimeSeconds = useAtomValue(gamingLeftTimeSecondsAtom);
- const score = useAtomValue(scoreAtom);
- const status = useAtomValue(statusAtom);
+ const leftTimeSeconds = useAtomValue(gamingLeftTimeSecondsAtom);
+ const score = useAtomValue(scoreAtom);
+ const status = useAtomValue(statusAtom);
- const [codeSize, setCodeSize] = useState(
- calcCodeSize(initialCode, problemLanguage),
- );
- const textareaRef = useRef<HTMLTextAreaElement>(null);
+ const [codeSize, setCodeSize] = useState(
+ calcCodeSize(initialCode, problemLanguage),
+ );
+ const textareaRef = useRef<HTMLTextAreaElement>(null);
- const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
- setCodeSize(calcCodeSize(e.target.value, problemLanguage));
- if (!isFinished) {
- onCodeChange(e.target.value);
- }
- };
+ const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
+ setCodeSize(calcCodeSize(e.target.value, problemLanguage));
+ if (!isFinished) {
+ onCodeChange(e.target.value);
+ }
+ };
- const handleSubmitButtonClick = () => {
- if (textareaRef.current && !isFinished) {
- onCodeSubmit(textareaRef.current.value);
- }
- };
+ const handleSubmitButtonClick = () => {
+ if (textareaRef.current && !isFinished) {
+ onCodeSubmit(textareaRef.current.value);
+ }
+ };
- return (
- <div className="min-h-screen bg-gray-100 flex flex-col">
- <div className="text-white bg-brand-600 flex flex-row justify-between px-4 py-2">
- <div className="font-bold">
- <div className="text-gray-100">{gameDisplayName}</div>
- {isFinished ? (
- <div className="text-2xl md:text-3xl">終了</div>
- ) : leftTimeSeconds === null ? (
- <div className="text-2xl md:text-3xl">未開始</div>
- ) : (
- <LeftTime sec={leftTimeSeconds} />
- )}
- </div>
- <Link to={"/dashboard"}>
- <div className="flex gap-6 items-center font-bold">
- <div className="text-2xl md:text-6xl">{score}</div>
- <div className="hidden md:block text-4xl">
- {playerProfile.displayName}
- </div>
- {playerProfile.iconPath && (
- <UserIcon
- iconPath={playerProfile.iconPath}
- displayName={playerProfile.displayName}
- className="w-12 h-12 my-auto"
- />
- )}
- </div>
- </Link>
- </div>
- <ThreeColumnLayout>
- <ProblemColumn
- title={problemTitle}
- description={problemDescription}
- language={problemLanguage}
- sampleCode={sampleCode}
- />
- <TitledColumn title="ソースコード">
- <BorderedContainer className="grow flex flex-col gap-4">
- <div className="flex flex-row gap-2 items-center">
- <div className="grow font-semibold text-lg">
- コードサイズ: {codeSize}
- </div>
- <SubmitButton
- onClick={handleSubmitButtonClick}
- disabled={isFinished}
- >
- 提出
- </SubmitButton>
- </div>
- <textarea
- ref={textareaRef}
- defaultValue={initialCode}
- onChange={handleTextChange}
- className="grow resize-none h-full w-full p-2 bg-gray-50 rounded-lg border border-gray-300 focus:outline-hidden focus:ring-2 focus:ring-gray-400 transition duration-300"
- rows={10}
- />
- </BorderedContainer>
- </TitledColumn>
- <TitledColumn title="提出結果">
- <DataTable headers={["ステータス", "スコア", "提出時刻", "コード"]}>
- {submissions.length === 0 ? (
- <tr>
- <DataTableCell>
- <SubmitStatusLabel status={status} />
- </DataTableCell>
- <DataTableCell>-</DataTableCell>
- <DataTableCell>-</DataTableCell>
- <DataTableCell>-</DataTableCell>
- </tr>
- ) : (
- submissions.map((s) => (
- <tr key={s.submission_id}>
- <DataTableCell>
- <SubmitStatusLabel status={s.status} />
- </DataTableCell>
- <DataTableCell>{s.code_size}</DataTableCell>
- <DataTableCell>
- {formatUnixTimestamp(s.created_at)}
- </DataTableCell>
- <DataTableCell>
- <CodePopover code={s.code} language={problemLanguage} />
- </DataTableCell>
- </tr>
- ))
- )}
- </DataTable>
- </TitledColumn>
- </ThreeColumnLayout>
- </div>
- );
+ return (
+ <div className="min-h-screen bg-gray-100 flex flex-col">
+ <div className="text-white bg-brand-600 flex flex-row justify-between px-4 py-2">
+ <div className="font-bold">
+ <div className="text-gray-100">{gameDisplayName}</div>
+ {isFinished ? (
+ <div className="text-2xl md:text-3xl">終了</div>
+ ) : leftTimeSeconds === null ? (
+ <div className="text-2xl md:text-3xl">未開始</div>
+ ) : (
+ <LeftTime sec={leftTimeSeconds} />
+ )}
+ </div>
+ <Link to={"/dashboard"}>
+ <div className="flex gap-6 items-center font-bold">
+ <div className="text-2xl md:text-6xl">{score}</div>
+ <div className="hidden md:block text-4xl">
+ {playerProfile.displayName}
+ </div>
+ {playerProfile.iconPath && (
+ <UserIcon
+ iconPath={playerProfile.iconPath}
+ displayName={playerProfile.displayName}
+ className="w-12 h-12 my-auto"
+ />
+ )}
+ </div>
+ </Link>
+ </div>
+ <ThreeColumnLayout>
+ <ProblemColumn
+ title={problemTitle}
+ description={problemDescription}
+ language={problemLanguage}
+ sampleCode={sampleCode}
+ />
+ <TitledColumn title="ソースコード">
+ <BorderedContainer className="grow flex flex-col gap-4">
+ <div className="flex flex-row gap-2 items-center">
+ <div className="grow font-semibold text-lg">
+ コードサイズ: {codeSize}
+ </div>
+ <SubmitButton
+ onClick={handleSubmitButtonClick}
+ disabled={isFinished}
+ >
+ 提出
+ </SubmitButton>
+ </div>
+ <textarea
+ ref={textareaRef}
+ defaultValue={initialCode}
+ onChange={handleTextChange}
+ className="grow resize-none h-full w-full p-2 bg-gray-50 rounded-lg border border-gray-300 focus:outline-hidden focus:ring-2 focus:ring-gray-400 transition duration-300"
+ rows={10}
+ />
+ </BorderedContainer>
+ </TitledColumn>
+ <TitledColumn title="提出結果">
+ <DataTable headers={["ステータス", "スコア", "提出時刻", "コード"]}>
+ {submissions.length === 0 ? (
+ <tr>
+ <DataTableCell>
+ <SubmitStatusLabel status={status} />
+ </DataTableCell>
+ <DataTableCell>-</DataTableCell>
+ <DataTableCell>-</DataTableCell>
+ <DataTableCell>-</DataTableCell>
+ </tr>
+ ) : (
+ submissions.map((s) => (
+ <tr key={s.submission_id}>
+ <DataTableCell>
+ <SubmitStatusLabel status={s.status} />
+ </DataTableCell>
+ <DataTableCell>{s.code_size}</DataTableCell>
+ <DataTableCell>
+ {formatUnixTimestamp(s.created_at)}
+ </DataTableCell>
+ <DataTableCell>
+ <CodePopover code={s.code} language={problemLanguage} />
+ </DataTableCell>
+ </tr>
+ ))
+ )}
+ </DataTable>
+ </TitledColumn>
+ </ThreeColumnLayout>
+ </div>
+ );
}
diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppLoading.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppLoading.tsx
index 7b424f2..ccb716f 100644
--- a/frontend/app/components/GolfPlayApps/GolfPlayAppLoading.tsx
+++ b/frontend/app/components/GolfPlayApps/GolfPlayAppLoading.tsx
@@ -1,9 +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>
- );
+ 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/GolfPlayApps/GolfPlayAppStarting.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppStarting.tsx
index b3378fc..951e001 100644
--- a/frontend/app/components/GolfPlayApps/GolfPlayAppStarting.tsx
+++ b/frontend/app/components/GolfPlayApps/GolfPlayAppStarting.tsx
@@ -2,20 +2,20 @@ import { useAtomValue } from "jotai";
import { startingLeftTimeSecondsAtom } from "../../states/play";
type Props = {
- gameDisplayName: string;
+ gameDisplayName: string;
};
export default function GolfPlayAppStarting({ gameDisplayName }: Props) {
- const leftTimeSeconds = useAtomValue(startingLeftTimeSecondsAtom)!;
+ const leftTimeSeconds = useAtomValue(startingLeftTimeSecondsAtom)!;
- return (
- <div className="min-h-screen bg-gray-100 flex flex-col">
- <div className="text-white bg-brand-600 p-10 text-center">
- <div className="text-4xl font-bold">{gameDisplayName}</div>
- </div>
- <div className="text-center text-black font-black text-10xl">
- {leftTimeSeconds}
- </div>
- </div>
- );
+ return (
+ <div className="min-h-screen bg-gray-100 flex flex-col">
+ <div className="text-white bg-brand-600 p-10 text-center">
+ <div className="text-4xl font-bold">{gameDisplayName}</div>
+ </div>
+ <div className="text-center text-black font-black text-10xl">
+ {leftTimeSeconds}
+ </div>
+ </div>
+ );
}
diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx
index 1341073..5c4e94f 100644
--- a/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx
+++ b/frontend/app/components/GolfPlayApps/GolfPlayAppWaiting.tsx
@@ -2,22 +2,22 @@ import type { PlayerProfile } from "../../types/PlayerProfile";
import PlayerNameAndIcon from "../PlayerNameAndIcon";
type Props = {
- gameDisplayName: string;
- playerProfile: PlayerProfile;
+ gameDisplayName: string;
+ playerProfile: PlayerProfile;
};
export default function GolfPlayAppWaiting({
- gameDisplayName,
- playerProfile,
+ gameDisplayName,
+ playerProfile,
}: Props) {
- return (
- <div className="min-h-screen bg-gray-100 flex flex-col font-bold text-center">
- <div className="text-white bg-brand-600 p-10">
- <div className="text-4xl">{gameDisplayName}</div>
- </div>
- <div className="grow grid mx-auto text-black">
- <PlayerNameAndIcon profile={playerProfile} />
- </div>
- </div>
- );
+ return (
+ <div className="min-h-screen bg-gray-100 flex flex-col font-bold text-center">
+ <div className="text-white bg-brand-600 p-10">
+ <div className="text-4xl">{gameDisplayName}</div>
+ </div>
+ <div className="grow grid mx-auto text-black">
+ <PlayerNameAndIcon profile={playerProfile} />
+ </div>
+ </div>
+ );
}