diff options
| author | nsfisis <nsfisis@gmail.com> | 2024-07-27 19:02:58 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2024-07-27 19:02:58 +0900 |
| commit | b70fa3abf9c96871cc3e39090e9a00da4ad87b8b (patch) | |
| tree | 848da44374c48edec603fb014c59ad0fbb9307e6 /frontend/src | |
| parent | e487036c5cc9f5b59e9efbaec132a2fd60896317 (diff) | |
| parent | 7cbf34204233df7c7e9e4b24998e25dbd8d2a423 (diff) | |
| download | iosdc-japan-2024-albatross-b70fa3abf9c96871cc3e39090e9a00da4ad87b8b.tar.gz iosdc-japan-2024-albatross-b70fa3abf9c96871cc3e39090e9a00da4ad87b8b.tar.zst iosdc-japan-2024-albatross-b70fa3abf9c96871cc3e39090e9a00da4ad87b8b.zip | |
Merge branch 'remix'
Diffstat (limited to 'frontend/src')
24 files changed, 0 insertions, 620 deletions
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx deleted file mode 100644 index 52b0c29..0000000 --- a/frontend/src/main.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import { createBrowserRouter, RouterProvider } from "react-router-dom"; -import Home from "./routes/Home.tsx"; -import Login, { loginAction } from "./routes/Login.tsx"; -import GolfEntry from "./routes/golf/GolfEntry.tsx"; -import GolfPlay from "./routes/golf/GolfPlay.tsx"; -import GolfWatch from "./routes/golf/GolfWatch.tsx"; -import UserEdit from "./routes/users/Edit.tsx"; -import TeamNew from "./routes/teams/New.tsx"; -import TeamEdit from "./routes/teams/Edit.tsx"; - -const router = createBrowserRouter([ - { - path: "/", - element: <Home />, - }, - { - path: "/login/", - element: <Login />, - action: loginAction, - }, - { - path: "/users/:userId/", - element: <UserEdit />, - }, - { - path: "/teams/new/", - element: <TeamNew />, - }, - { - path: "/teams/:teamId/", - element: <TeamEdit />, - }, - { - path: "/golf/entry/", - element: <GolfEntry />, - }, - { - path: "/golf/:gameId/play/:playerId/", - element: <GolfPlay />, - }, - { - path: "/golf/:gameId/watch/", - element: <GolfWatch />, - }, -]); - -ReactDOM.createRoot(document.getElementById("root")!).render( - <React.StrictMode> - <RouterProvider router={router} /> - </React.StrictMode>, -); diff --git a/frontend/src/routes/Home.tsx b/frontend/src/routes/Home.tsx deleted file mode 100644 index 176ad35..0000000 --- a/frontend/src/routes/Home.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Link } from "react-router-dom"; - -export default function Home() { - return ( - <div> - <h1>Albatross.swift</h1> - <p>iOSDC 2024</p> - <p> - <Link to="/login/">Login</Link> - </p> - </div> - ); -} diff --git a/frontend/src/routes/Login.tsx b/frontend/src/routes/Login.tsx deleted file mode 100644 index 4871060..0000000 --- a/frontend/src/routes/Login.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { redirect, Form, ActionFunctionArgs } from "react-router-dom"; - -export default function Login() { - return ( - <div> - <h1>Albatross.swift</h1> - <h2>Login</h2> - <Form method="post"> - <label>Username</label> - <input type="text" name="username" /> - <label>Password</label> - <input type="password" name="password" /> - <button type="submit">Login</button> - </Form> - </div> - ); -} - -export async function loginAction({ request }: ActionFunctionArgs) { - const formData = await request.formData(); - const username = formData.get("username"); - const password = formData.get("password"); - - const res = await fetch("/api/login", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ username, password }), - }); - if (!res.ok) { - throw res; - } - const { userId } = await res.json(); - return redirect(`/users/${userId}/`); -} diff --git a/frontend/src/routes/golf/GolfEntry.tsx b/frontend/src/routes/golf/GolfEntry.tsx deleted file mode 100644 index a0f9c8e..0000000 --- a/frontend/src/routes/golf/GolfEntry.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function GolfEntry() { - return ( - <div> - <h1>Golf Entry</h1> - </div> - ); -} diff --git a/frontend/src/routes/golf/GolfPlay.tsx b/frontend/src/routes/golf/GolfPlay.tsx deleted file mode 100644 index 42e8e5f..0000000 --- a/frontend/src/routes/golf/GolfPlay.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import App from "./play/App.tsx"; - -export default function GolfPlay() { - return ( - <div> - <h1>Golf Play</h1> - <App gameId={0} playerId={0} /> - </div> - ); -} diff --git a/frontend/src/routes/golf/GolfWatch.tsx b/frontend/src/routes/golf/GolfWatch.tsx deleted file mode 100644 index acd3305..0000000 --- a/frontend/src/routes/golf/GolfWatch.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import App from "./watch/App.tsx"; - -export default function GolfWatch() { - return ( - <div> - <h1>Golf Watch</h1> - <App gameId={0} /> - </div> - ); -} diff --git a/frontend/src/routes/golf/play/App.tsx b/frontend/src/routes/golf/play/App.tsx deleted file mode 100644 index b73830a..0000000 --- a/frontend/src/routes/golf/play/App.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import { useState, useEffect } from "react"; -import useWebSocket, { ReadyState } from "react-use-websocket"; -import { useDebouncedCallback } from "use-debounce"; -import Connecting from "./apps/Connecting.tsx"; -import Waiting from "./apps/Waiting.tsx"; -import Starting from "./apps/Starting.tsx"; -import Gaming from "./apps/Gaming.tsx"; -import Finished from "./apps/Finished.tsx"; -import Failed from "./apps/Failed.tsx"; -import type { GameState } from "./GameState.ts"; - -type Props = { - gameId: number; - playerId: number; -}; - -type WebSocketMessage = - | { type: "connect" } - | { type: "prepare"; data: { problem: string } } - | { type: "ready" } - | { type: "start"; data: { startTime: string } } - | { - type: "finish"; - data: { yourScore: number | null; opponentScore: number | null }; - } - | { type: "score"; data: { score: number } } - | { type: "code"; data: { code: string } } - | { - type: "watch"; - data: { - problem: string; - scoreA: number | null; - codeA: string; - scoreB: number | null; - codeB: string; - }; - }; - -export default function App({ gameId, playerId }: Props) { - // const socketUrl = `wss://t.nil.ninja/iosdc/2024/sock/golf/${gameId}/${playerId}/`; - const socketUrl = `ws://localhost:8002/sock/golf/${gameId}/${playerId}/`; - - const { sendJsonMessage, lastJsonMessage, readyState } = - useWebSocket<WebSocketMessage>(socketUrl); - - const [gameState, setGameState] = useState<GameState>("connecting"); - - const [problem, setProblem] = useState<string | null>(null); - - // in seconds - const [timeLeft, setTimeLeft] = useState<number | null>(null); - useEffect(() => { - if (gameState === "starting" && timeLeft !== null) { - const timer = setInterval(() => { - setTimeLeft((prevTime) => { - // `prevTime` is not null because `timeLeft` is not null. - prevTime = prevTime!; - if (prevTime <= 1) { - clearInterval(timer); - setGameState("gaming"); - return 0; - } - return prevTime - 1; - }); - }, 1000); - - return () => clearInterval(timer); - } - }, [gameState]); - - const [score, setScore] = useState<number | null>(null); - - const [result, setResult] = useState<{ - yourScore: number | null; - opponentScore: number | null; - } | null>(null); - - const onCodeChange = useDebouncedCallback((data) => { - sendJsonMessage({ type: "code", data }); - }, 1000); - - useEffect(() => { - if (readyState === ReadyState.UNINSTANTIATED) { - setGameState("failed"); - } else if ( - readyState === ReadyState.CLOSING || - readyState === ReadyState.CLOSED - ) { - if (gameState !== "finished") { - setGameState("failed"); - } - } else if (readyState === ReadyState.CONNECTING) { - setGameState("connecting"); - } else if (readyState === ReadyState.OPEN) { - if (lastJsonMessage !== null) { - if (lastJsonMessage.type === "prepare") { - const { problem } = lastJsonMessage.data; - setProblem(problem); - sendJsonMessage({ type: "ready", data: {} }); - } else if (lastJsonMessage.type === "start") { - const { startTime } = lastJsonMessage.data; - const startTimeMs = Date.parse(startTime); - setTimeLeft( - Math.max(0, Math.floor((startTimeMs - Date.now()) / 1000)), - ); - setGameState("starting"); - } else if (lastJsonMessage.type === "finish") { - const result = lastJsonMessage.data; - setResult(result); - setGameState("finished"); - } else if (lastJsonMessage.type === "score") { - const { score } = lastJsonMessage.data; - setScore(score); - } else { - setGameState("failed"); - } - } else { - setGameState("waiting"); - sendJsonMessage({ type: "connect", data: {} }); - } - } - }, [readyState, lastJsonMessage]); - - return ( - <div> - <h1> - Game #{gameId} (playerId #{playerId}) - </h1> - <div> - {gameState === "connecting" ? ( - <Connecting gameId={gameId} playerId={playerId} /> - ) : gameState === "waiting" ? ( - <Waiting gameId={gameId} playerId={playerId} /> - ) : gameState === "starting" ? ( - <Starting gameId={gameId} playerId={playerId} timeLeft={timeLeft} /> - ) : gameState === "gaming" ? ( - <Gaming - gameId={gameId} - playerId={playerId} - problem={problem} - score={score} - onCodeChange={onCodeChange} - /> - ) : gameState === "finished" ? ( - <Finished gameId={gameId} playerId={playerId} result={result!} /> - ) : ( - <Failed gameId={gameId} playerId={playerId} /> - )} - </div> - </div> - ); -} diff --git a/frontend/src/routes/golf/play/GameState.ts b/frontend/src/routes/golf/play/GameState.ts deleted file mode 100644 index 7a1de5c..0000000 --- a/frontend/src/routes/golf/play/GameState.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type GameState = - | "connecting" - | "waiting" - | "starting" - | "gaming" - | "finished" - | "failed"; diff --git a/frontend/src/routes/golf/play/apps/Connecting.tsx b/frontend/src/routes/golf/play/apps/Connecting.tsx deleted file mode 100644 index ead4f03..0000000 --- a/frontend/src/routes/golf/play/apps/Connecting.tsx +++ /dev/null @@ -1,8 +0,0 @@ -type Props = { - gameId: number; - playerId: number; -}; - -export default function Connecting(_props: Props) { - return <div>接続中です......</div>; -} diff --git a/frontend/src/routes/golf/play/apps/Failed.tsx b/frontend/src/routes/golf/play/apps/Failed.tsx deleted file mode 100644 index cc1748d..0000000 --- a/frontend/src/routes/golf/play/apps/Failed.tsx +++ /dev/null @@ -1,8 +0,0 @@ -type Props = { - gameId: number; - playerId: number; -}; - -export default function Failed(_props: Props) { - return <div>エラー</div>; -} diff --git a/frontend/src/routes/golf/play/apps/Finished.tsx b/frontend/src/routes/golf/play/apps/Finished.tsx deleted file mode 100644 index e04c7a0..0000000 --- a/frontend/src/routes/golf/play/apps/Finished.tsx +++ /dev/null @@ -1,27 +0,0 @@ -type Props = { - gameId: number; - playerId: number; - result: { yourScore: number | null; opponentScore: number | null }; -}; - -export default function Finished({ result }: Props) { - const { yourScore, opponentScore } = result; - const yourScoreToCompare = yourScore ?? Infinity; - const opponentScoreToCompare = opponentScore ?? Infinity; - const resultText = - yourScoreToCompare === opponentScoreToCompare - ? "引き分け" - : yourScoreToCompare < opponentScoreToCompare - ? "あなたの勝ち" - : "あなたの負け"; - return ( - <> - <div>対戦終了</div> - <div> - <div>{resultText}</div> - <div>あなたのスコア: {yourScore ?? "なし"}</div> - <div>相手のスコア: {opponentScore ?? "なし"}</div> - </div> - </> - ); -} diff --git a/frontend/src/routes/golf/play/apps/Gaming.tsx b/frontend/src/routes/golf/play/apps/Gaming.tsx deleted file mode 100644 index 9be39c8..0000000 --- a/frontend/src/routes/golf/play/apps/Gaming.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from "react"; - -type Props = { - gameId: number; - playerId: number; - problem: string | null; - onCodeChange: (data: { code: string }) => void; - score: number | null; -}; - -export default function Gaming({ problem, onCodeChange, score }: Props) { - const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { - onCodeChange({ code: e.target.value }); - }; - - return ( - <div style={{ display: "flex" }}> - <div style={{ flex: 1, padding: "10px", borderRight: "1px solid #ccc" }}> - <div>{problem}</div> - <div>{score == null ? "Score: -" : `Score: ${score} byte`}</div> - </div> - <div style={{ flex: 1, padding: "10px" }}> - <textarea - style={{ width: "100%", height: "100%" }} - onChange={handleTextChange} - /> - </div> - </div> - ); -} diff --git a/frontend/src/routes/golf/play/apps/Starting.tsx b/frontend/src/routes/golf/play/apps/Starting.tsx deleted file mode 100644 index b260b30..0000000 --- a/frontend/src/routes/golf/play/apps/Starting.tsx +++ /dev/null @@ -1,13 +0,0 @@ -type Props = { - gameId: number; - playerId: number; - timeLeft: number | null; -}; - -export default function Starting({ timeLeft }: Props) { - return ( - <> - <div>対戦相手が見つかりました。{timeLeft} 秒後にゲームを開始します。</div> - </> - ); -} diff --git a/frontend/src/routes/golf/play/apps/Waiting.tsx b/frontend/src/routes/golf/play/apps/Waiting.tsx deleted file mode 100644 index b7e6f31..0000000 --- a/frontend/src/routes/golf/play/apps/Waiting.tsx +++ /dev/null @@ -1,8 +0,0 @@ -type Props = { - gameId: number; - playerId: number; -}; - -export default function Waiting(_props: Props) { - return <div>対戦相手が現れるのを待っています......</div>; -} diff --git a/frontend/src/routes/golf/watch/App.tsx b/frontend/src/routes/golf/watch/App.tsx deleted file mode 100644 index ac2db23..0000000 --- a/frontend/src/routes/golf/watch/App.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { useState, useEffect } from "react"; -import useWebSocket, { ReadyState } from "react-use-websocket"; -import Connecting from "./apps/Connecting.jsx"; -import Waiting from "./apps/Waiting.jsx"; -import Gaming from "./apps/Gaming.jsx"; -import Failed from "./apps/Failed.jsx"; -import type { WatchState } from "./WatchState.js"; - -type Props = { - gameId: number; -}; - -type WebSocketMessage = - | { type: "connect" } - | { type: "prepare"; data: { problem: string } } - | { type: "ready" } - | { type: "start"; data: { startTime: string } } - | { - type: "finish"; - data: { yourScore: number | null; opponentScore: number | null }; - } - | { type: "score"; data: { score: number } } - | { type: "code"; data: { code: string } } - | { - type: "watch"; - data: { - problem: string; - scoreA: number | null; - codeA: string; - scoreB: number | null; - codeB: string; - }; - }; - -export default function App({ gameId }: Props) { - // const socketUrl = `wss://t.nil.ninja/iosdc/2024/sock/golf/${gameId}/watch/`; - const socketUrl = `ws://localhost:8002/sock/golf/${gameId}/watch/`; - - const { lastJsonMessage, readyState } = - useWebSocket<WebSocketMessage>(socketUrl); - - const [watchState, setWatchState] = useState<WatchState>("connecting"); - - const [problem, setProblem] = useState<string | null>(null); - - const [scoreA, setScoreA] = useState<number | null>(null); - const [codeA, setCodeA] = useState<string | null>(null); - const [scoreB, setScoreB] = useState<number | null>(null); - const [codeB, setCodeB] = useState<string | null>(null); - - useEffect(() => { - if (readyState === ReadyState.UNINSTANTIATED) { - setWatchState("failed"); - } else if ( - readyState === ReadyState.CLOSING || - readyState === ReadyState.CLOSED - ) { - if (watchState !== "finished") { - setWatchState("failed"); - } - } else if (readyState === ReadyState.CONNECTING) { - setWatchState("connecting"); - } else if (readyState === ReadyState.OPEN) { - if (lastJsonMessage !== null) { - if (lastJsonMessage.type === "watch") { - const { - problem, - scoreA: scoreA_, - codeA: codeA_, - scoreB: scoreB_, - codeB: codeB_, - } = lastJsonMessage.data; - setProblem(problem); - setScoreA(scoreA_); - setCodeA(codeA_); - setScoreB(scoreB_); - setCodeB(codeB_); - setWatchState("gaming"); - } else { - setWatchState("failed"); - } - } else { - setWatchState("waiting"); - } - } - }, [readyState, lastJsonMessage]); - - return ( - <div> - <h1>Game #{gameId} watching</h1> - <div> - {watchState === "connecting" ? ( - <Connecting gameId={gameId} /> - ) : watchState === "waiting" ? ( - <Waiting gameId={gameId} /> - ) : watchState === "gaming" || watchState === "finished" ? ( - <Gaming - gameId={gameId} - problem={problem} - scoreA={scoreA} - codeA={codeA} - scoreB={scoreB} - codeB={codeB} - /> - ) : ( - <Failed gameId={gameId} /> - )} - </div> - </div> - ); -} diff --git a/frontend/src/routes/golf/watch/WatchState.ts b/frontend/src/routes/golf/watch/WatchState.ts deleted file mode 100644 index 8d9997e..0000000 --- a/frontend/src/routes/golf/watch/WatchState.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type WatchState = - | "connecting" - | "waiting" - | "starting" - | "gaming" - | "finished" - | "failed"; diff --git a/frontend/src/routes/golf/watch/apps/Connecting.tsx b/frontend/src/routes/golf/watch/apps/Connecting.tsx deleted file mode 100644 index 73d28eb..0000000 --- a/frontend/src/routes/golf/watch/apps/Connecting.tsx +++ /dev/null @@ -1,7 +0,0 @@ -type Props = { - gameId: number; -}; - -export default function Connecting(_props: Props) { - return <div>接続中です......</div>; -} diff --git a/frontend/src/routes/golf/watch/apps/Failed.tsx b/frontend/src/routes/golf/watch/apps/Failed.tsx deleted file mode 100644 index 2727663..0000000 --- a/frontend/src/routes/golf/watch/apps/Failed.tsx +++ /dev/null @@ -1,7 +0,0 @@ -type Props = { - gameId: number; -}; - -export default function Failed(_props: Props) { - return <div>エラー</div>; -} diff --git a/frontend/src/routes/golf/watch/apps/Gaming.tsx b/frontend/src/routes/golf/watch/apps/Gaming.tsx deleted file mode 100644 index 3f9c195..0000000 --- a/frontend/src/routes/golf/watch/apps/Gaming.tsx +++ /dev/null @@ -1,44 +0,0 @@ -type Props = { - gameId: number; - problem: string | null; - scoreA: number | null; - codeA: string | null; - scoreB: number | null; - codeB: string | null; -}; - -export default function Gaming({ - problem, - scoreA, - codeA, - scoreB, - codeB, -}: Props) { - return ( - <> - <div style={{ display: "flex", flexDirection: "column" }}> - <div style={{ display: "flex", flex: 1, justifyContent: "center" }}> - {problem} - </div> - <div style={{ display: "flex", flex: 3 }}> - <div style={{ display: "flex", flex: 3, flexDirection: "column" }}> - <div style={{ flex: 1, justifyContent: "center" }}>{scoreA}</div> - <div style={{ flex: 3 }}> - <pre> - <code>{codeA}</code> - </pre> - </div> - </div> - <div style={{ display: "flex", flex: 3, flexDirection: "column" }}> - <div style={{ flex: 1, justifyContent: "center" }}>{scoreB}</div> - <div style={{ flex: 3 }}> - <pre> - <code>{codeB}</code> - </pre> - </div> - </div> - </div> - </div> - </> - ); -} diff --git a/frontend/src/routes/golf/watch/apps/Waiting.tsx b/frontend/src/routes/golf/watch/apps/Waiting.tsx deleted file mode 100644 index a82ee69..0000000 --- a/frontend/src/routes/golf/watch/apps/Waiting.tsx +++ /dev/null @@ -1,7 +0,0 @@ -type Props = { - gameId: number; -}; - -export default function Waiting(_props: Props) { - return <div>対戦相手が現れるのを待っています......</div>; -} diff --git a/frontend/src/routes/teams/Edit.tsx b/frontend/src/routes/teams/Edit.tsx deleted file mode 100644 index 82c1ff8..0000000 --- a/frontend/src/routes/teams/Edit.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Form } from "react-router-dom"; - -export default function Edit() { - return ( - <div> - <h1>Albatross.swift</h1> - <h2>Team Edit</h2> - <Form method="post"> - <label>Team name</label> - <input type="text" name="name" /> - <label>Icon</label> - <input type="text" name="icon" disabled /> - <button type="submit">Save</button> - </Form> - </div> - ); -} diff --git a/frontend/src/routes/teams/New.tsx b/frontend/src/routes/teams/New.tsx deleted file mode 100644 index ba00731..0000000 --- a/frontend/src/routes/teams/New.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Form } from "react-router-dom"; - -export default function New() { - return ( - <div> - <h1>Albatross.swift</h1> - <h2>Team New</h2> - <Form method="post"> - <label>Team name</label> - <input type="text" name="name" /> - <label>Icon</label> - <input type="text" name="icon" disabled /> - <button type="submit">Create</button> - </Form> - </div> - ); -} diff --git a/frontend/src/routes/users/Edit.tsx b/frontend/src/routes/users/Edit.tsx deleted file mode 100644 index 6c9af19..0000000 --- a/frontend/src/routes/users/Edit.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { Form, Link } from "react-router-dom"; - -export default function Edit() { - return ( - <div> - <h1>Albatross.swift</h1> - <h2>User Edit</h2> - <Form method="post"> - <label>Display name</label> - <input type="text" name="display_name" /> - <label>Icon</label> - <input type="text" name="icon" disabled /> - <button type="submit">Save</button> - </Form> - <p> - <Link to="/teams/new/">Create a new team</Link> - </p> - </div> - ); -} diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe..0000000 --- a/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// <reference types="vite/client" /> |
