From 00e878282ba3ef6d2a3dfa9afb77248720e06341 Mon Sep 17 00:00:00 2001 From: Gavin McDonald Date: Tue, 15 Apr 2025 08:56:10 -0400 Subject: [PATCH] Display error when game not found --- app/[gameID]/page.tsx | 24 +++++++++++++++++------- app/page.tsx | 3 ++- components/NotFound.tsx | 10 ++++++++++ lib/GameStore.ts | 2 +- server.ts | 34 +++++++++++++++++++++++++++------- 5 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 components/NotFound.tsx diff --git a/app/[gameID]/page.tsx b/app/[gameID]/page.tsx index 3f27da2..260106f 100644 --- a/app/[gameID]/page.tsx +++ b/app/[gameID]/page.tsx @@ -5,6 +5,7 @@ import { useParams } from 'next/navigation'; import { socket } from '@/socket'; import Card from '@/components/Card'; +import NotFound from '@/components/NotFound'; import CopyButton from '@/components/CopyButton'; import { cardMap, layout } from '@/constants/tarokka'; @@ -14,6 +15,7 @@ export default function GamePage() { const { gameID: gameIDParam } = useParams(); const [gameID, setGameID] = useState(''); + const [noGame, setNoGame] = useState(false); const [{ dmID, spectatorID, cards }, setGameData] = useState({ dmID: '', spectatorID: '', @@ -39,14 +41,20 @@ export default function GamePage() { console.log('>>>', data); setGameData(data); }); + + socket.on('join-error', (error) => { + console.error('Error:', error); + setNoGame(true); + }); + + socket.on('flip-error', (error) => { + console.error('Error:', error); + }); } - return gameID - ? () => { - socket.off('init'); - socket.off('card-flipped'); - } - : undefined; + return () => { + socket.removeAllListeners(); + }; }, [gameID]); const flipCard = (cardIndex: number) => { @@ -63,7 +71,9 @@ export default function GamePage() { // high deck cards: bottom and center const arrangeCards = (_cell: any, index: number) => cards[cardMap[index]]; - return cards ? ( + return noGame ? ( + + ) : cards ? (
{dmID && } diff --git a/app/page.tsx b/app/page.tsx index 5d90935..71bfa07 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,6 +1,7 @@ 'use client'; -import { useRouter } from 'next/navigation'; import { socket } from '@/socket'; +import { useRouter } from 'next/navigation'; + import { GameUpdate } from '@/types'; export default function Home() { diff --git a/components/NotFound.tsx b/components/NotFound.tsx new file mode 100644 index 0000000..e89a9f5 --- /dev/null +++ b/components/NotFound.tsx @@ -0,0 +1,10 @@ +export default function Custom404() { + return ( +
+

404 - Game Not Found

+

+ The game you're looking for doesn't exist or has expired. +

+
+ ); +} diff --git a/lib/GameStore.ts b/lib/GameStore.ts index e1db643..7dcd6b1 100644 --- a/lib/GameStore.ts +++ b/lib/GameStore.ts @@ -50,7 +50,7 @@ export default class GameStore { } joinGame(gameID: string, playerID: string): GameUpdate { - const game = this.getGame(gameID) || this.createGame(); + const game = this.getGame(gameID); game.players.add(playerID); game.lastUpdated = Date.now(); diff --git a/server.ts b/server.ts index 0b35b08..9e40cd9 100644 --- a/server.ts +++ b/server.ts @@ -31,20 +31,40 @@ app.prepare().then(() => { }); socket.on('join', (gameID) => { - socket.join(gameID); - const gameUpdate = gameStore.joinGame(gameID, socket.id); + try { + const gameUpdate = gameStore.joinGame(gameID, socket.id); - console.log(`Socket ${socket.id} joined game ${gameID}`); + console.log(`Socket ${socket.id} joined game ${gameID}`); - socket.emit('init', gameUpdate); + socket.join(gameID); + + if (gameID === gameUpdate.spectatorID) { + const { spectatorID, cards } = gameUpdate; + socket.emit('init', { spectatorID, cards }); + } else { + socket.emit('init', gameUpdate); + } + } catch (e) { + const error = e instanceof Error ? e.message : e; + + console.error('Error', error); + socket.emit('join-error', error); + } }); socket.on('flip-card', ({ gameID, cardIndex }: ClientUpdate) => { - console.log('Card flipped:', { gameID, cardIndex }); + try { + console.log('Card flipped:', { gameID, cardIndex }); - const gameUpdate = gameStore.flipCard(gameID, cardIndex); + const gameUpdate = gameStore.flipCard(gameID, cardIndex); - io.to(gameID).emit('card-flipped', gameUpdate); + io.to(gameID).emit('card-flipped', gameUpdate); + } catch (e) { + const error = e instanceof Error ? e.message : e; + + console.error('Error', error); + socket.emit('flip-error', error); + } }); socket.on('disconnect', () => {