30c32b7714
- db/ package: async SQLAlchemy engine + Player/Game/Guess models - api/auth.py: passwordless TOTP login (pyotp), session token via socket auth - api/history.py: record guesses/points, DB-backed standings, restore unfinished games on startup, host-only end_game - api/__init__.py: auth-gated handlers, accounts map, rejoin via account - frontend: Auth (QR + code) and History pages, resume/end-game in lobby/table - docker-compose: real PostgreSQL service wired via DATABASE_URL - tests_history.py for the persistence/auth layer; refresh CLAUDE.md Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
84 lines
2.3 KiB
TypeScript
84 lines
2.3 KiB
TypeScript
import { create } from 'zustand';
|
|
import type {
|
|
Account,
|
|
GameDetail,
|
|
GameInfo,
|
|
GameStatusPayload,
|
|
Hand,
|
|
HistoryGame,
|
|
MyPlayer,
|
|
Registration,
|
|
} from '../types';
|
|
|
|
interface GameStore {
|
|
games: GameInfo[];
|
|
account: Account | null;
|
|
registration: Registration | null;
|
|
history: HistoryGame[];
|
|
gameDetail: GameDetail | null;
|
|
myPlayer: MyPlayer | null;
|
|
gameStatus: GameStatusPayload | null;
|
|
hand: Hand;
|
|
error: string | null;
|
|
|
|
setGames: (games: GameInfo[]) => void;
|
|
setAccount: (account: Account | null) => void;
|
|
setRegistration: (registration: Registration | null) => void;
|
|
setHistory: (history: HistoryGame[]) => void;
|
|
setGameDetail: (detail: GameDetail | null) => void;
|
|
setMyPlayer: (player: MyPlayer | null) => void;
|
|
setGameStatus: (status: GameStatusPayload) => void;
|
|
setHand: (hand: Hand) => void;
|
|
setError: (error: string | null) => void;
|
|
clearError: () => void;
|
|
updatePlayerConnection: (order: number, connected: boolean) => void;
|
|
reset: () => void;
|
|
logout: () => void;
|
|
}
|
|
|
|
export const useGameStore = create<GameStore>((set) => ({
|
|
games: [],
|
|
account: null,
|
|
registration: null,
|
|
history: [],
|
|
gameDetail: null,
|
|
myPlayer: null,
|
|
gameStatus: null,
|
|
hand: {},
|
|
error: null,
|
|
|
|
setGames: (games) => set({ games }),
|
|
setAccount: (account) => set({ account }),
|
|
setRegistration: (registration) => set({ registration }),
|
|
setHistory: (history) => set({ history }),
|
|
setGameDetail: (gameDetail) => set({ gameDetail }),
|
|
setMyPlayer: (myPlayer) => set({ myPlayer }),
|
|
setGameStatus: (gameStatus) => set({ gameStatus }),
|
|
setHand: (hand) => set({ hand }),
|
|
setError: (error) => set({ error }),
|
|
clearError: () => set({ error: null }),
|
|
updatePlayerConnection: (order, connected) =>
|
|
set((state) => ({
|
|
gameStatus: state.gameStatus
|
|
? {
|
|
...state.gameStatus,
|
|
players: state.gameStatus.players.map((p) =>
|
|
p.order === order ? { ...p, connected } : p
|
|
),
|
|
}
|
|
: null,
|
|
})),
|
|
reset: () => set({ myPlayer: null, gameStatus: null, hand: {}, error: null }),
|
|
logout: () =>
|
|
set({
|
|
account: null,
|
|
registration: null,
|
|
history: [],
|
|
gameDetail: null,
|
|
myPlayer: null,
|
|
gameStatus: null,
|
|
hand: {},
|
|
error: null,
|
|
}),
|
|
}));
|