fix(blackjack): return players to the lobby when a table is force-ended
This commit is contained in:
parent
27b5b4537f
commit
40b7cbb025
1 changed files with 11 additions and 24 deletions
|
|
@ -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}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue