Files
super-auto-pets-board-game/web/src/components/Home.tsx
T

104 lines
2.9 KiB
TypeScript

import { useState } from 'react'
import { createGame, joinGame } from '../api'
import type { BotDifficulty } from '../api'
import type { Session } from '../types'
const BOT_LEVELS: { value: BotDifficulty; label: string; blurb: string }[] = [
{ value: 'easy', label: '🐣 Easy', blurb: 'Learns you the ropes' },
{ value: 'medium', label: '🐺 Medium', blurb: 'Puts up a fight' },
{ value: 'hard', label: '🦁 Hard', blurb: 'Shows no mercy' },
]
// Home is the create/join screen shown when there's no active session.
export function Home({ onSession }: { onSession: (s: Session) => void }) {
const [name, setName] = useState('')
const [code, setCode] = useState('')
const [busy, setBusy] = useState(false)
const [error, setError] = useState<string | null>(null)
async function run(fn: () => Promise<Session>) {
setBusy(true)
setError(null)
try {
onSession(await fn())
} catch (e) {
setError(e instanceof Error ? e.message : 'something went wrong')
} finally {
setBusy(false)
}
}
return (
<div className="home">
<div className="home-pets" aria-hidden>
🐷🦔🐶🦩🐉
</div>
<h1 className="home-title">
Super Auto Pets
<span className="home-subtitle">The Board Game</span>
</h1>
<div className="home-card">
<label className="field">
<span>Your name</span>
<input
value={name}
maxLength={20}
placeholder="Enter your name"
onChange={(e) => setName(e.target.value)}
/>
</label>
<button
className="btn btn-primary btn-big"
disabled={busy}
onClick={() => run(() => createGame(name))}
>
Host a new game
</button>
<div className="home-divider">
<span>or challenge the computer</span>
</div>
<div className="home-bots">
{BOT_LEVELS.map((b) => (
<button
key={b.value}
className="btn btn-secondary"
disabled={busy}
title={b.blurb}
onClick={() => run(() => createGame(name, b.value))}
>
{b.label}
</button>
))}
</div>
<div className="home-divider">
<span>or join a friend</span>
</div>
<div className="home-join">
<input
className="code-input"
value={code}
maxLength={5}
placeholder="CODE"
onChange={(e) => setCode(e.target.value.toUpperCase())}
/>
<button
className="btn btn-secondary"
disabled={busy || code.length < 5}
onClick={() => run(() => joinGame(code, name))}
>
Join
</button>
</div>
{error && <div className="home-error">{error}</div>}
</div>
</div>
)
}