1
0
Fork 0

fix(blackjack): return players to the lobby when a table is force-ended

This commit is contained in:
Jason Fraley 2026-09-19 17:39:18 -04:00
parent 27b5b4537f
commit 40b7cbb025

View file

@ -1,6 +1,7 @@
"use client"; "use client";
import { useCallback, useEffect, useRef, useState } from "react"; import { useCallback, useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { import {
fetchBlackjackTable, fetchBlackjackTable,
joinBlackjackTable, joinBlackjackTable,
@ -11,7 +12,6 @@ import {
} from "@/app/(frontend)/minigames/blackjack/actions"; } from "@/app/(frontend)/minigames/blackjack/actions";
import type { BlackjackPhase } from "@/lib/minigames/blackjack"; import type { BlackjackPhase } from "@/lib/minigames/blackjack";
import { useRealtimePresence } from "@/hooks/useRealtimePresence"; import { useRealtimePresence } from "@/hooks/useRealtimePresence";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { ChipBankCard } from "@/components/frontend/minigames/ChipBankCard"; import { ChipBankCard } from "@/components/frontend/minigames/ChipBankCard";
import { BlackjackGuide } from "./BlackjackGuide"; import { BlackjackGuide } from "./BlackjackGuide";
@ -61,7 +61,6 @@ export function BlackjackArena({
const [activeTableId, setActiveTableId] = useState<string | null>(initialTableId ?? null); const [activeTableId, setActiveTableId] = useState<string | null>(initialTableId ?? null);
const [tableError, setTableError] = useState<string | null>(null); const [tableError, setTableError] = useState<string | null>(null);
const [loading, setLoading] = useState(Boolean(initialTableId)); const [loading, setLoading] = useState(Boolean(initialTableId));
const [terminated, setTerminated] = useState<string | null>(null);
const [leaderboardRefreshKey, setLeaderboardRefreshKey] = useState(0); const [leaderboardRefreshKey, setLeaderboardRefreshKey] = useState(0);
const [lobbyRefreshKey, setLobbyRefreshKey] = useState(0); const [lobbyRefreshKey, setLobbyRefreshKey] = useState(0);
const lastRoundRef = useRef<number | null>(null); const lastRoundRef = useRef<number | null>(null);
@ -73,7 +72,6 @@ export function BlackjackArena({
return next; return next;
}); });
setActiveTableId(next.tableId); setActiveTableId(next.tableId);
setTerminated((current) => (current !== next.tableId ? null : current));
if (syncedTableIdRef.current !== next.tableId) { if (syncedTableIdRef.current !== next.tableId) {
syncedTableIdRef.current = next.tableId; syncedTableIdRef.current = next.tableId;
window.history.replaceState( window.history.replaceState(
@ -134,7 +132,8 @@ export function BlackjackArena({
const handleTerminated = (event: Event) => { const handleTerminated = (event: Event) => {
const detail = readBlackjackTerminatedEvent(event); const detail = readBlackjackTerminatedEvent(event);
if (!detail || detail.tableId !== activeTableId) return; if (!detail || detail.tableId !== activeTableId) return;
setTerminated(detail.tableId); toast.info("An administrator ended your blackjack game.");
resetToLobby();
}; };
window.addEventListener(BLACKJACK_STATE_EVENT, handleState); window.addEventListener(BLACKJACK_STATE_EVENT, handleState);
window.addEventListener(BLACKJACK_TABLES_EVENT, handleTables); window.addEventListener(BLACKJACK_TABLES_EVENT, handleTables);
@ -150,13 +149,18 @@ export function BlackjackArena({
// deliver server-action pushes (dev per-bundle module duplication). The // deliver server-action pushes (dev per-bundle module duplication). The
// SSE push stays as an instant bonus; applySnapshot dedupes by version. // SSE push stays as an instant bonus; applySnapshot dedupes by version.
useEffect(() => { useEffect(() => {
if (view !== "table" || activeTableId === null || terminated === activeTableId) return; if (view !== "table" || activeTableId === null) return;
let cancelled = false; let cancelled = false;
const poll = window.setInterval(() => { const poll = window.setInterval(() => {
void fetchBlackjackTable(activeTableId) void fetchBlackjackTable(activeTableId)
.then((result) => { .then((result) => {
if (cancelled) return; if (cancelled) return;
if (result.success && result.data) applySnapshot(result.data); if (result.success && result.data) {
applySnapshot(result.data);
} else if (result.error === "Table not found.") {
toast.info("An administrator ended your blackjack game.");
resetToLobby();
}
}) })
.catch(() => undefined); .catch(() => undefined);
}, 1250); }, 1250);
@ -164,7 +168,7 @@ export function BlackjackArena({
cancelled = true; cancelled = true;
window.clearInterval(poll); window.clearInterval(poll);
}; };
}, [activeTableId, terminated, view, applySnapshot]); }, [activeTableId, view, applySnapshot]);
const resetToLobby = useCallback(() => { const resetToLobby = useCallback(() => {
setView("lobby"); setView("lobby");
@ -172,7 +176,6 @@ export function BlackjackArena({
setActiveTableId(null); setActiveTableId(null);
setTableError(null); setTableError(null);
setLoading(false); setLoading(false);
setTerminated(null);
lastRoundRef.current = null; lastRoundRef.current = null;
if (syncedTableIdRef.current !== null) { if (syncedTableIdRef.current !== null) {
syncedTableIdRef.current = null; syncedTableIdRef.current = null;
@ -304,22 +307,6 @@ export function BlackjackArena({
onOpenTable={applySnapshot} onOpenTable={applySnapshot}
isSuperuser={isSuperuser} isSuperuser={isSuperuser}
/> />
) : terminated === activeTableId ? (
<Card className="rounded-none border-destructive/40" role="alert">
<CardHeader className="border-b border-destructive/20 p-4">
<CardTitle className="text-base text-destructive">
Game ended by an administrator
</CardTitle>
</CardHeader>
<CardContent className="flex flex-col items-start gap-4 p-4">
<p className="text-sm text-muted-foreground">
An administrator forcefully ended this blackjack table.
</p>
<Button type="button" variant="outline" onClick={resetToLobby}>
Back to lobby
</Button>
</CardContent>
</Card>
) : ( ) : (
<BlackjackTable <BlackjackTable
snapshot={snapshot} snapshot={snapshot}