52 lines
1.8 KiB
TypeScript
52 lines
1.8 KiB
TypeScript
import type { LobbyPlayer, Observation } from '../../api/types'
|
|
import { Button } from '../../components/Button/Button'
|
|
import styles from './GameOver.module.css'
|
|
|
|
interface GameOverProps {
|
|
observation: Observation
|
|
players: LobbyPlayer[]
|
|
isHost: boolean
|
|
onShowScores: () => void
|
|
onBackToLobby: () => void
|
|
onLeave: () => void
|
|
}
|
|
|
|
export function GameOver({ observation, players, isHost, onShowScores, onBackToLobby, onLeave }: GameOverProps) {
|
|
const ranking = observation.scores
|
|
.map((score, seat) => ({ seat, score }))
|
|
.sort((a, b) => b.score - a.score)
|
|
const winners = new Set(observation.winners)
|
|
const youWon = winners.has(observation.player)
|
|
|
|
return (
|
|
<div className={styles.content}>
|
|
<p className={styles.headline}>{youWon ? 'You win! ✦' : `${players[ranking[0].seat]?.name ?? 'Someone'} wins!`}</p>
|
|
<ol className={styles.ranking}>
|
|
{ranking.map(({ seat, score }, index) => (
|
|
<li key={seat} className={`${styles.row} ${winners.has(seat) ? styles.winner : ''}`}>
|
|
<span className={styles.place}>{index + 1}.</span>
|
|
<span className={styles.name}>
|
|
{players[seat]?.name ?? `Player ${seat + 1}`}
|
|
{seat === observation.player && <span className={styles.muted}> (you)</span>}
|
|
</span>
|
|
<span className={styles.score}>{score}</span>
|
|
</li>
|
|
))}
|
|
</ol>
|
|
<div className={styles.actions}>
|
|
<Button variant="ghost" onClick={onShowScores}>
|
|
Scoreboard
|
|
</Button>
|
|
<Button variant="danger" onClick={onLeave}>
|
|
Leave
|
|
</Button>
|
|
{isHost ? (
|
|
<Button onClick={onBackToLobby}>Back to lobby</Button>
|
|
) : (
|
|
<span className={styles.muted}>The host can start a new game.</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|