From 6f9a9bc5dc9e9ae66209e0cabe9152ff2c3c1e85 Mon Sep 17 00:00:00 2001 From: Ross Andrews Date: Tue, 26 May 2026 20:02:59 -0500 Subject: [PATCH] Add placeholder page flow with localStorage-backed navigation Four screens (Title, Player Setup, Score Sheet, Enter Scores) wired together via a simple useState state machine. Auto-resumes to Score Sheet if a game exists in localStorage under the key 'currentGame'. Co-Authored-By: Claude Sonnet 4.6 --- src/App.tsx | 55 ++++++++++++++++++++++++++++++++++----- src/pages/EnterScores.tsx | 12 +++++++++ src/pages/PlayerSetup.tsx | 12 +++++++++ src/pages/ScoreSheet.tsx | 14 ++++++++++ src/pages/TitleScreen.tsx | 12 +++++++++ src/types.ts | 6 +++++ 6 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 src/pages/EnterScores.tsx create mode 100644 src/pages/PlayerSetup.tsx create mode 100644 src/pages/ScoreSheet.tsx create mode 100644 src/pages/TitleScreen.tsx create mode 100644 src/types.ts diff --git a/src/App.tsx b/src/App.tsx index d383c28..9e6457a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,50 @@ -export default function App() { - return ( -
-

Black 7

-
- ) +import { useState } from 'react' +import { type Page, type GameState } from './types' +import TitleScreen from './pages/TitleScreen' +import PlayerSetup from './pages/PlayerSetup' +import ScoreSheet from './pages/ScoreSheet' +import EnterScores from './pages/EnterScores' + +const STORAGE_KEY = 'currentGame' + +function loadGame(): GameState | null { + const raw = localStorage.getItem(STORAGE_KEY) + return raw ? (JSON.parse(raw) as GameState) : null +} + +function saveGame(game: GameState) { + localStorage.setItem(STORAGE_KEY, JSON.stringify(game)) +} + +function clearGame() { + localStorage.removeItem(STORAGE_KEY) +} + +export default function App() { + const [page, setPage] = useState(() => + loadGame() ? 'scoresheet' : 'title' + ) + const [game, setGame] = useState(() => loadGame()) + + function handleNewGame() { + clearGame() + setGame(null) + setPage('setup') + } + + function handleStart() { + const newGame: GameState = { players: [], rounds: [] } + saveGame(newGame) + setGame(newGame) + setPage('scoresheet') + } + + function handleSubmitScores() { + setPage('scoresheet') + } + + if (page === 'title') return + if (page === 'setup') return + if (page === 'scoresheet') return setPage('enterscores')} onNewGame={handleNewGame} /> + if (page === 'enterscores') return } diff --git a/src/pages/EnterScores.tsx b/src/pages/EnterScores.tsx new file mode 100644 index 0000000..f04bbf5 --- /dev/null +++ b/src/pages/EnterScores.tsx @@ -0,0 +1,12 @@ +interface Props { + onSubmit: () => void +} + +export default function EnterScores({ onSubmit }: Props) { + return ( +
+

Enter Scores

+ +
+ ) +} diff --git a/src/pages/PlayerSetup.tsx b/src/pages/PlayerSetup.tsx new file mode 100644 index 0000000..7f9c798 --- /dev/null +++ b/src/pages/PlayerSetup.tsx @@ -0,0 +1,12 @@ +interface Props { + onStart: () => void +} + +export default function PlayerSetup({ onStart }: Props) { + return ( +
+

Player Setup

+ +
+ ) +} diff --git a/src/pages/ScoreSheet.tsx b/src/pages/ScoreSheet.tsx new file mode 100644 index 0000000..b00e871 --- /dev/null +++ b/src/pages/ScoreSheet.tsx @@ -0,0 +1,14 @@ +interface Props { + onScoreRound: () => void + onNewGame: () => void +} + +export default function ScoreSheet({ onScoreRound, onNewGame }: Props) { + return ( +
+

Score Sheet

+ + +
+ ) +} diff --git a/src/pages/TitleScreen.tsx b/src/pages/TitleScreen.tsx new file mode 100644 index 0000000..d344f84 --- /dev/null +++ b/src/pages/TitleScreen.tsx @@ -0,0 +1,12 @@ +interface Props { + onNewGame: () => void +} + +export default function TitleScreen({ onNewGame }: Props) { + return ( +
+

Black 7

+ +
+ ) +} diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..a7db06f --- /dev/null +++ b/src/types.ts @@ -0,0 +1,6 @@ +export type Page = 'title' | 'setup' | 'scoresheet' | 'enterscores' + +export interface GameState { + players: string[] + rounds: number[][] // rounds[i][j] = player j's score in round i +}