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 <noreply@anthropic.com>
This commit is contained in:
+49
-6
@@ -1,7 +1,50 @@
|
||||
export default function App() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Black 7</h1>
|
||||
</div>
|
||||
)
|
||||
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<Page>(() =>
|
||||
loadGame() ? 'scoresheet' : 'title'
|
||||
)
|
||||
const [game, setGame] = useState<GameState | null>(() => 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 <TitleScreen onNewGame={handleNewGame} />
|
||||
if (page === 'setup') return <PlayerSetup onStart={handleStart} />
|
||||
if (page === 'scoresheet') return <ScoreSheet onScoreRound={() => setPage('enterscores')} onNewGame={handleNewGame} />
|
||||
if (page === 'enterscores') return <EnterScores onSubmit={handleSubmitScores} />
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
interface Props {
|
||||
onSubmit: () => void
|
||||
}
|
||||
|
||||
export default function EnterScores({ onSubmit }: Props) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Enter Scores</h1>
|
||||
<button onClick={onSubmit}>Submit</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
interface Props {
|
||||
onStart: () => void
|
||||
}
|
||||
|
||||
export default function PlayerSetup({ onStart }: Props) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Player Setup</h1>
|
||||
<button onClick={onStart}>Start</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
interface Props {
|
||||
onScoreRound: () => void
|
||||
onNewGame: () => void
|
||||
}
|
||||
|
||||
export default function ScoreSheet({ onScoreRound, onNewGame }: Props) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Score Sheet</h1>
|
||||
<button onClick={onScoreRound}>Score Round</button>
|
||||
<button onClick={onNewGame} style={{ fontSize: '0.75em' }}>New Game</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
interface Props {
|
||||
onNewGame: () => void
|
||||
}
|
||||
|
||||
export default function TitleScreen({ onNewGame }: Props) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Black 7</h1>
|
||||
<button onClick={onNewGame}>New Game</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user