Fix WebSocket game:join to emit game:state event

Backend was returning the state but not emitting the game:state
event that the frontend listens for. Added explicit emit call
to send game:state to the client after successful join.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Cal Corum 2026-02-01 12:27:01 -06:00
parent c594f0c8f8
commit 52c8edcf93
3 changed files with 30 additions and 2 deletions

View File

@ -177,6 +177,20 @@ class GameNamespaceHandler:
response["turn_timeout_seconds"] = result.turn_timeout_seconds
response["turn_deadline"] = result.turn_deadline
# Emit game:state event to the client
if result.visible_state:
await sio.emit(
"game:state",
{
"game_id": game_id,
"state": response["state"],
"is_your_turn": response["is_your_turn"],
"game_over": response["game_over"],
},
to=sid,
namespace="/game",
)
logger.info(f"Player {user_id} joined game {game_id}")
return response

View File

@ -43,7 +43,20 @@ async function parseErrorResponse(response: Response): Promise<ApiError> {
try {
const data: ErrorResponse = await response.json()
detail = data.detail || data.message
// Handle Pydantic validation errors (422) - detail is an array
if (Array.isArray(data.detail)) {
// Extract error messages from validation error array
detail = data.detail
.map((err: any) => {
const field = err.loc ? err.loc.join('.') : 'unknown'
return `${field}: ${err.msg || 'Invalid value'}`
})
.join('; ')
} else {
detail = data.detail || data.message
}
code = data.code
} catch {
// Response body is not JSON or empty

View File

@ -92,9 +92,10 @@ export interface PaginatedResponse<T> {
/**
* Backend error response shape.
* For validation errors (422), detail is an array of validation error objects.
*/
export interface ErrorResponse {
detail?: string
detail?: string | Array<{ loc: string[]; msg: string; type: string }>
message?: string
code?: string
}