contextProvider
This commit is contained in:
@@ -14,6 +14,7 @@ import gameRouter from './routers/gameRouter';
|
||||
import { LoggingService, logStartup, logConnection, logError, logRequest } from '../Application/Services/Logger';
|
||||
import { WebSocketService } from '../Application/Services/WebSocketService';
|
||||
import { GameWebSocketService } from '../Application/Services/GameWebSocketService';
|
||||
import { container } from '../Application/Services/DIContainer';
|
||||
import { GameRepository } from '../Infrastructure/Repository/GameRepository';
|
||||
import { UserRepository } from '../Infrastructure/Repository/UserRepository';
|
||||
import { RedisService } from '../Application/Services/RedisService';
|
||||
@@ -183,17 +184,9 @@ AppDataSource.initialize()
|
||||
chatInactivityTimeout: process.env.CHAT_INACTIVITY_TIMEOUT_MINUTES || '30'
|
||||
});
|
||||
|
||||
// Initialize Game WebSocket service for /game namespace
|
||||
const gameRepository = new GameRepository();
|
||||
const userRepository = new UserRepository();
|
||||
const redisService = RedisService.getInstance();
|
||||
|
||||
gameWebSocketService = new GameWebSocketService(
|
||||
webSocketService['io'], // Access the io property directly
|
||||
gameRepository,
|
||||
userRepository,
|
||||
redisService
|
||||
);
|
||||
// Initialize Game WebSocket service for /game namespace via DIContainer
|
||||
container.setSocketIO(webSocketService['io']);
|
||||
gameWebSocketService = container.gameWebSocketService;
|
||||
logStartup('Game WebSocket service initialized for /game namespace');
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
@@ -226,21 +226,43 @@ export class StartGamePlayCommandHandler {
|
||||
|
||||
private async notifyGameStart(game: GameAggregate): Promise<void> {
|
||||
try {
|
||||
// Note: WebSocket notifications will be handled when WebSocket service is available
|
||||
// For now, just log the game start
|
||||
logOther('Game start notifications prepared', {
|
||||
// Get board data from Redis
|
||||
const redisKey = `game_board_${game.id}`;
|
||||
const boardDataStr = await this.redisService.get(redisKey);
|
||||
|
||||
if (!boardDataStr) {
|
||||
logError('Board data not found in Redis during game start notification', new Error('Missing board data'));
|
||||
return;
|
||||
}
|
||||
|
||||
const boardData: BoardData = JSON.parse(boardDataStr);
|
||||
|
||||
// Get turn sequence from Redis
|
||||
const gamePlayData = await this.getGamePlayFromRedis(game.id);
|
||||
if (!gamePlayData) {
|
||||
logError('Game play data not found in Redis', new Error('Missing game play data'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get WebSocket service from DIContainer and broadcast game start
|
||||
const gameWebSocketService = DIContainer.getInstance().gameWebSocketService;
|
||||
await gameWebSocketService.broadcastGameStart(
|
||||
game.gamecode,
|
||||
boardData,
|
||||
gamePlayData.turnSequence,
|
||||
game
|
||||
);
|
||||
|
||||
logOther('Game start notifications sent via WebSocket', {
|
||||
gameId: game.id,
|
||||
gameCode: game.gamecode,
|
||||
playerCount: game.players.length,
|
||||
websocketRoom: `game_${game.gamecode}`
|
||||
websocketRoom: `game_${game.gamecode}`,
|
||||
firstPlayer: gamePlayData.turnSequence[0]
|
||||
});
|
||||
|
||||
// TODO: Implement WebSocket notifications when service is properly integrated
|
||||
// wsService.notifyGameStart(game.gamecode, game.players);
|
||||
// wsService.broadcastGameStateUpdate(game.gamecode, gameStateData);
|
||||
|
||||
} catch (error) {
|
||||
logError('Failed to prepare game start notifications', error instanceof Error ? error : new Error(String(error)));
|
||||
logError('Failed to send game start notifications', error instanceof Error ? error : new Error(String(error)));
|
||||
// Don't throw error here - notification failure shouldn't prevent game start
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,8 @@ import { RedisService } from './RedisService';
|
||||
import { GameService } from '../Game/GameService';
|
||||
import { BoardGenerationService } from '../Game/BoardGenerationService';
|
||||
import { GenerateBoardCommandHandler } from '../Game/commands/GenerateBoardCommandHandler';
|
||||
import { GameWebSocketService } from './GameWebSocketService';
|
||||
import type { Server as SocketIOServer } from 'socket.io';
|
||||
|
||||
/**
|
||||
* Central Dependency Injection Container
|
||||
@@ -96,6 +98,8 @@ export class DIContainer {
|
||||
private _fieldEffectService: FieldEffectService | null = null;
|
||||
private _gameService: GameService | null = null;
|
||||
private _boardGenerationService: BoardGenerationService | null = null;
|
||||
private _gameWebSocketService: GameWebSocketService | null = null;
|
||||
private _socketIOInstance: SocketIOServer | null = null;
|
||||
|
||||
// Command Handlers
|
||||
private _createUserCommandHandler: CreateUserCommandHandler | null = null;
|
||||
@@ -272,6 +276,30 @@ export class DIContainer {
|
||||
return this._boardGenerationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Socket.IO instance (must be called before accessing gameWebSocketService)
|
||||
*/
|
||||
public setSocketIO(io: SocketIOServer): void {
|
||||
this._socketIOInstance = io;
|
||||
// Reset gameWebSocketService so it gets recreated with new IO instance
|
||||
this._gameWebSocketService = null;
|
||||
}
|
||||
|
||||
public get gameWebSocketService(): GameWebSocketService {
|
||||
if (!this._gameWebSocketService) {
|
||||
if (!this._socketIOInstance) {
|
||||
throw new Error('Socket.IO instance must be set before accessing gameWebSocketService. Call setSocketIO() first.');
|
||||
}
|
||||
this._gameWebSocketService = new GameWebSocketService(
|
||||
this._socketIOInstance,
|
||||
this.gameRepository as any, // Cast to concrete type
|
||||
this.userRepository as any, // Cast to concrete type
|
||||
RedisService.getInstance()
|
||||
);
|
||||
}
|
||||
return this._gameWebSocketService;
|
||||
}
|
||||
|
||||
// Command Handler getters
|
||||
public get createUserCommandHandler(): CreateUserCommandHandler {
|
||||
if (!this._createUserCommandHandler) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import VerifyEmailPage from "./pages/Auth/VerifyEmailPage"
|
||||
import ChooseDeck from "./pages/Game/ChooseDeck"
|
||||
import PlayerSetup from "./pages/Game/PlayerSetup"
|
||||
import GameModalsDemo from "./pages/Game/GameModalsDemo"
|
||||
import { GameWebSocketProvider } from "./contexts/GameWebSocketContext"
|
||||
|
||||
function App() {
|
||||
const [isMobile, setIsMobile] = useState(false)
|
||||
@@ -53,6 +54,7 @@ function App() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<GameWebSocketProvider>
|
||||
<Router>
|
||||
<Routes>
|
||||
<Route path={ROUTES.VERIFY_EMAIL} element={<VerifyEmailPage />} />
|
||||
@@ -78,6 +80,7 @@ function App() {
|
||||
<Route path={ROUTES.PLAYER_SETUP} element={<PlayerSetup />} />
|
||||
</Routes>
|
||||
</Router>
|
||||
</GameWebSocketProvider>
|
||||
|
||||
{/* ✅ Toastify Container */}
|
||||
<ToastConfig />
|
||||
|
||||
@@ -0,0 +1,371 @@
|
||||
import React, { createContext, useContext, useRef, useState, useCallback, useMemo, useEffect } from 'react';
|
||||
import { io } from 'socket.io-client';
|
||||
import { API_CONFIG } from '../api/userApi';
|
||||
|
||||
const GameWebSocketContext = createContext(null);
|
||||
|
||||
const isDev = import.meta.env.DEV;
|
||||
const log = (...args) => isDev && console.log(...args);
|
||||
const warn = (...args) => isDev && console.warn(...args);
|
||||
const logError = (...args) => console.error(...args);
|
||||
|
||||
/**
|
||||
* Provider that maintains WebSocket connection across page navigation
|
||||
*/
|
||||
export const GameWebSocketProvider = ({ children }) => {
|
||||
const socketRef = useRef(null);
|
||||
const gameTokenRef = useRef(null);
|
||||
const [isConnected, setIsConnected] = useState(false);
|
||||
const [gameState, setGameState] = useState(null);
|
||||
const [boardData, setBoardData] = useState(null);
|
||||
const [error, setError] = useState(null);
|
||||
const [isGamemaster, setIsGamemaster] = useState(false);
|
||||
const [gameStarted, setGameStarted] = useState(false);
|
||||
const [pendingPlayers, setPendingPlayers] = useState([]);
|
||||
const [approvalStatus, setApprovalStatus] = useState(null);
|
||||
|
||||
// Memoized derived values
|
||||
const players = useMemo(() => {
|
||||
const connectedPlayers = gameState?.connectedPlayers || [];
|
||||
const currentPlayers = gameState?.currentPlayers || [];
|
||||
|
||||
if (currentPlayers.length > 0) {
|
||||
return currentPlayers;
|
||||
}
|
||||
|
||||
if (connectedPlayers.length > 0) {
|
||||
return connectedPlayers.map((nameOrObj, index) => {
|
||||
const playerName = typeof nameOrObj === 'string'
|
||||
? nameOrObj
|
||||
: (nameOrObj.playerName || nameOrObj.name || `Player ${index + 1}`);
|
||||
|
||||
return {
|
||||
id: `player-${index}`,
|
||||
name: playerName,
|
||||
isOnline: true,
|
||||
isReady: gameState?.readyPlayers?.includes(playerName) || false,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return [];
|
||||
}, [gameState?.connectedPlayers, gameState?.currentPlayers, gameState?.readyPlayers]);
|
||||
|
||||
const currentTurn = useMemo(() => gameState?.currentPlayer || null, [gameState?.currentPlayer]);
|
||||
|
||||
/**
|
||||
* Connect to game WebSocket with a game token
|
||||
* This maintains the connection even when navigating between pages
|
||||
*/
|
||||
const connect = useCallback((gameToken) => {
|
||||
if (!gameToken) {
|
||||
warn('⚠️ Cannot connect without game token');
|
||||
return;
|
||||
}
|
||||
|
||||
// If already connected with same token, don't reconnect
|
||||
if (socketRef.current?.connected && gameTokenRef.current === gameToken) {
|
||||
log('✅ Already connected with same token');
|
||||
return;
|
||||
}
|
||||
|
||||
// Disconnect old socket if exists
|
||||
if (socketRef.current) {
|
||||
log('🔌 Disconnecting old socket');
|
||||
socketRef.current.removeAllListeners();
|
||||
socketRef.current.disconnect();
|
||||
}
|
||||
|
||||
log('🔌 Connecting to game WebSocket...');
|
||||
gameTokenRef.current = gameToken;
|
||||
|
||||
// Connect to /game namespace
|
||||
socketRef.current = io(`${API_CONFIG.wsURL}/game`, {
|
||||
transports: ['websocket'],
|
||||
reconnection: true,
|
||||
reconnectionAttempts: 5,
|
||||
reconnectionDelay: 1000,
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
const socket = socketRef.current;
|
||||
|
||||
// Connection handlers
|
||||
socket.on('connect', () => {
|
||||
log('✅ Connected to game WebSocket');
|
||||
setIsConnected(true);
|
||||
setError(null);
|
||||
socket.emit('game:join', { gameToken });
|
||||
});
|
||||
|
||||
socket.on('connect_error', (err) => {
|
||||
logError('❌ Connection error:', err);
|
||||
setIsConnected(false);
|
||||
setError(err.message);
|
||||
});
|
||||
|
||||
socket.on('disconnect', (reason) => {
|
||||
log('🔌 Disconnected:', reason);
|
||||
setIsConnected(false);
|
||||
});
|
||||
|
||||
// Game state handlers
|
||||
socket.on('game:state', (state) => {
|
||||
log('📊 Game state received:', state);
|
||||
if (state?.isGamemaster !== undefined) {
|
||||
setIsGamemaster(state.isGamemaster);
|
||||
}
|
||||
setGameState(state);
|
||||
});
|
||||
|
||||
socket.on('game:state-update', (state) => {
|
||||
log('📊 Game state update:', state);
|
||||
if (state?.isGamemaster !== undefined) {
|
||||
setIsGamemaster(state.isGamemaster);
|
||||
}
|
||||
setGameState(state);
|
||||
});
|
||||
|
||||
socket.on('game:joined', (data) => {
|
||||
log('✅ Joined game:', data);
|
||||
if (data.isGamemaster !== undefined) {
|
||||
setIsGamemaster(data.isGamemaster);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('game:player-joined', (data) => {
|
||||
log('👤 Player joined:', data.playerName);
|
||||
setGameState(prev => {
|
||||
if (!prev) return prev;
|
||||
const currentConnected = prev.connectedPlayers || [];
|
||||
if (!currentConnected.includes(data.playerName)) {
|
||||
return {
|
||||
...prev,
|
||||
connectedPlayers: [...currentConnected, data.playerName]
|
||||
};
|
||||
}
|
||||
return prev;
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('game:start', (data) => {
|
||||
log('🎮 Game started:', data);
|
||||
setGameStarted(true);
|
||||
|
||||
// Store board data if provided
|
||||
if (data.boardData) {
|
||||
setBoardData(data.boardData);
|
||||
log('✅ Board data stored from game:start event');
|
||||
}
|
||||
|
||||
// Update game state with turn info
|
||||
if (data.playerOrder) {
|
||||
setGameState(prev => ({
|
||||
...prev,
|
||||
playerOrder: data.playerOrder,
|
||||
currentPlayer: data.currentPlayer,
|
||||
turnSequence: data.playerOrder
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('game:started', (data) => {
|
||||
log('🎮 Game started (legacy event):', data);
|
||||
setGameStarted(true);
|
||||
});
|
||||
|
||||
socket.on('game:player-moved', (moveData) => {
|
||||
log('🏃 Player moved:', moveData.playerName);
|
||||
setGameState(prev => {
|
||||
if (!prev?.currentPlayers) return prev;
|
||||
return {
|
||||
...prev,
|
||||
currentPlayers: prev.currentPlayers.map(p =>
|
||||
p.playerId === moveData.playerId
|
||||
? { ...p, boardPosition: moveData.newPosition }
|
||||
: p
|
||||
),
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('game:turn-changed', (data) => {
|
||||
log('🔄 Turn changed to:', data.currentPlayerName);
|
||||
setGameState(prev => prev ? { ...prev, currentPlayer: data.currentPlayer } : prev);
|
||||
});
|
||||
|
||||
socket.on('game:error', (err) => {
|
||||
logError('❌ Game error:', err);
|
||||
setError(err.message);
|
||||
});
|
||||
|
||||
// Approval system handlers
|
||||
socket.on('game:pending-approval', (data) => {
|
||||
log('⏳ Pending gamemaster approval:', data);
|
||||
setApprovalStatus('pending');
|
||||
setError('Waiting for gamemaster approval...');
|
||||
});
|
||||
|
||||
socket.on('game:player-requesting-join', (data) => {
|
||||
log('🔔 Player requesting to join:', data.playerName);
|
||||
setPendingPlayers(prev => {
|
||||
if (prev.some(p => p.playerName === data.playerName)) return prev;
|
||||
return [...prev, {
|
||||
playerName: data.playerName,
|
||||
isAuthenticated: data.isAuthenticated,
|
||||
timestamp: data.timestamp
|
||||
}];
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('game:approval-granted', (data) => {
|
||||
log('✅ Join request approved:', data);
|
||||
setApprovalStatus('approved');
|
||||
setError(null);
|
||||
socket.emit('game:join-approved', { gameToken });
|
||||
});
|
||||
|
||||
socket.on('game:approval-denied', (data) => {
|
||||
logError('❌ Join request denied:', data.reason || data.message);
|
||||
setApprovalStatus('denied');
|
||||
setError(data.reason || 'Your request to join was denied');
|
||||
});
|
||||
|
||||
socket.on('game:player-approved', (data) => {
|
||||
log('✅ Player approved by gamemaster:', data.playerName);
|
||||
setPendingPlayers(prev => prev.filter(p => p.playerName !== data.playerName));
|
||||
setGameState(prev => {
|
||||
if (!prev) return prev;
|
||||
const currentConnected = prev.connectedPlayers || [];
|
||||
if (!currentConnected.includes(data.playerName)) {
|
||||
return {
|
||||
...prev,
|
||||
connectedPlayers: [...currentConnected, data.playerName]
|
||||
};
|
||||
}
|
||||
return prev;
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Disconnect from WebSocket
|
||||
*/
|
||||
const disconnect = useCallback(() => {
|
||||
if (socketRef.current) {
|
||||
log('🔌 Disconnecting from game WebSocket');
|
||||
socketRef.current.removeAllListeners();
|
||||
socketRef.current.disconnect();
|
||||
socketRef.current = null;
|
||||
gameTokenRef.current = null;
|
||||
setIsConnected(false);
|
||||
setGameState(null);
|
||||
setBoardData(null);
|
||||
setError(null);
|
||||
setIsGamemaster(false);
|
||||
setGameStarted(false);
|
||||
setPendingPlayers([]);
|
||||
setApprovalStatus(null);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Action methods
|
||||
const rollDice = useCallback((diceValue) => {
|
||||
const socket = socketRef.current;
|
||||
if (!socket || !isConnected) {
|
||||
warn('⚠️ Cannot roll dice: not connected');
|
||||
return false;
|
||||
}
|
||||
log('🎲 Rolling dice:', diceValue);
|
||||
socket.emit('game:dice-roll', { gameCode: gameState?.gameCode, diceValue });
|
||||
return true;
|
||||
}, [isConnected, gameState?.gameCode]);
|
||||
|
||||
const sendMessage = useCallback((message) => {
|
||||
const socket = socketRef.current;
|
||||
if (!socket || !isConnected) return false;
|
||||
socket.emit('game:chat', { gameCode: gameState?.gameCode, message });
|
||||
return true;
|
||||
}, [isConnected, gameState?.gameCode]);
|
||||
|
||||
const setReady = useCallback((ready = true) => {
|
||||
const socket = socketRef.current;
|
||||
if (!socket || !isConnected) return false;
|
||||
socket.emit('game:ready', { gameCode: gameState?.gameCode, ready });
|
||||
return true;
|
||||
}, [isConnected, gameState?.gameCode]);
|
||||
|
||||
const leaveGame = useCallback(() => {
|
||||
const socket = socketRef.current;
|
||||
if (!socket || !isConnected) return false;
|
||||
socket.emit('game:leave', { gameCode: gameState?.gameCode });
|
||||
return true;
|
||||
}, [isConnected, gameState?.gameCode]);
|
||||
|
||||
const approvePlayer = useCallback((playerName) => {
|
||||
const socket = socketRef.current;
|
||||
if (!socket || !isConnected || !isGamemaster) return false;
|
||||
socket.emit('game:approve-player', { gameCode: gameState?.gameCode, playerName });
|
||||
return true;
|
||||
}, [isConnected, isGamemaster, gameState?.gameCode]);
|
||||
|
||||
const rejectPlayer = useCallback((playerName, reason = 'Join request denied') => {
|
||||
const socket = socketRef.current;
|
||||
if (!socket || !isConnected || !isGamemaster) return false;
|
||||
socket.emit('game:reject-player', { gameCode: gameState?.gameCode, playerName, reason });
|
||||
return true;
|
||||
}, [isConnected, isGamemaster, gameState?.gameCode]);
|
||||
|
||||
const addEventListener = useCallback((event, handler) => {
|
||||
const socket = socketRef.current;
|
||||
if (socket) socket.on(event, handler);
|
||||
}, []);
|
||||
|
||||
const removeEventListener = useCallback((event, handler) => {
|
||||
const socket = socketRef.current;
|
||||
if (socket) socket.off(event, handler);
|
||||
}, []);
|
||||
|
||||
const value = {
|
||||
socket: socketRef.current,
|
||||
isConnected,
|
||||
gameState,
|
||||
players,
|
||||
boardData,
|
||||
currentTurn,
|
||||
error,
|
||||
isGamemaster,
|
||||
gameStarted,
|
||||
pendingPlayers,
|
||||
approvalStatus,
|
||||
// Connection management
|
||||
connect,
|
||||
disconnect,
|
||||
// Methods
|
||||
rollDice,
|
||||
sendMessage,
|
||||
setReady,
|
||||
leaveGame,
|
||||
approvePlayer,
|
||||
rejectPlayer,
|
||||
addEventListener,
|
||||
removeEventListener,
|
||||
};
|
||||
|
||||
return (
|
||||
<GameWebSocketContext.Provider value={value}>
|
||||
{children}
|
||||
</GameWebSocketContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to access the shared WebSocket connection
|
||||
*/
|
||||
export const useGameWebSocketContext = () => {
|
||||
const context = useContext(GameWebSocketContext);
|
||||
if (!context) {
|
||||
throw new Error('useGameWebSocketContext must be used within GameWebSocketProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect, useMemo, useCallback } from "react"
|
||||
import { getVerticalOffset } from "../../utils/randomUtils"
|
||||
import Dice from "../../utils/dice/Dice"
|
||||
import { useGameWebSocket } from "../../hooks/useGameWebSocket"
|
||||
import { useGameWebSocketContext } from "../../contexts/GameWebSocketContext"
|
||||
import JokerApprovalModal from "./JokerApprovalModal"
|
||||
import CardDisplayModal from "./CardDisplayModal"
|
||||
import ConsequenceModal from "./ConsequenceModal"
|
||||
@@ -45,8 +45,7 @@ const getDefaultFieldType = (count) => {
|
||||
}
|
||||
|
||||
const GameScreen = () => {
|
||||
// WebSocket connection
|
||||
const gameToken = localStorage.getItem('gameToken')
|
||||
// WebSocket connection from context (maintains connection across navigation)
|
||||
const {
|
||||
isConnected,
|
||||
gameState,
|
||||
@@ -61,7 +60,7 @@ const GameScreen = () => {
|
||||
submitPositionGuess,
|
||||
addEventListener,
|
||||
removeEventListener
|
||||
} = useGameWebSocket(gameToken)
|
||||
} = useGameWebSocketContext()
|
||||
|
||||
// Try to get boardData from WebSocket, fallback to localStorage
|
||||
const boardData = useMemo(() => {
|
||||
@@ -626,7 +625,7 @@ const GameScreen = () => {
|
||||
<div>👥 Players: {backendPlayers?.length || 0}</div>
|
||||
<div>🎲 Board Fields: {boardData?.fields?.length || 0}</div>
|
||||
<div>🏁 Current Turn: {currentTurn || 'N/A'}</div>
|
||||
<div>🔑 Token: {gameToken ? '✅' : '❌'}</div>
|
||||
{/* <div>🔑 Token: {gameToken ? '✅' : '❌'}</div> */}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -4,7 +4,7 @@ import HandleNavigate from "../../utils/HandleNavigate/HandleNavigate"
|
||||
import Navbar from "../../components/Navbar/Navbar.jsx"
|
||||
import Background from "../../assets/backgrounds/Background.jsx"
|
||||
import useRequireAuth from "../../hooks/useRequireAuth.jsx"
|
||||
import { useGameWebSocket } from "../../hooks/useGameWebSocket.js"
|
||||
import { useGameWebSocketContext } from "../../contexts/GameWebSocketContext"
|
||||
import { startGame } from "../../api/gameApi.js"
|
||||
|
||||
const Lobby = () => {
|
||||
@@ -20,7 +20,9 @@ const Lobby = () => {
|
||||
const gameCodeFromState = location.state?.gameCode
|
||||
const gameToken = localStorage.getItem('gameToken')
|
||||
|
||||
// Use the shared WebSocket context
|
||||
const {
|
||||
connect,
|
||||
isConnected,
|
||||
gameState,
|
||||
players,
|
||||
@@ -30,7 +32,14 @@ const Lobby = () => {
|
||||
approvalStatus,
|
||||
approvePlayer,
|
||||
rejectPlayer,
|
||||
} = useGameWebSocket(gameToken)
|
||||
} = useGameWebSocketContext()
|
||||
|
||||
// Connect to WebSocket when component mounts
|
||||
useEffect(() => {
|
||||
if (gameToken) {
|
||||
connect(gameToken)
|
||||
}
|
||||
}, [gameToken, connect])
|
||||
|
||||
const gameCode = gameCodeFromState || gameState?.gameCode || 'Loading...'
|
||||
|
||||
@@ -67,18 +76,18 @@ const Lobby = () => {
|
||||
console.log('🎮 Game started, navigating to /game')
|
||||
goGame()
|
||||
}
|
||||
}, [gameStarted, navigate])
|
||||
}, [gameStarted, goGame])
|
||||
|
||||
// Handle approval status changes
|
||||
useEffect(() => {
|
||||
if (approvalStatus === 'denied') {
|
||||
alert('A gamemaster elutasította a csatlakozási kérelmedet.')
|
||||
localStorage.removeItem('gameToken')
|
||||
navigate("/home")
|
||||
goHome()
|
||||
} else if (approvalStatus === 'approved') {
|
||||
console.log('✅ Join approved, you can now see the lobby')
|
||||
}
|
||||
}, [approvalStatus, navigate])
|
||||
}, [approvalStatus, goHome])
|
||||
|
||||
const handleExit = () => {
|
||||
if (window.confirm("Biztosan ki szeretnél lépni a lobbyból?")) {
|
||||
@@ -116,7 +125,7 @@ const Lobby = () => {
|
||||
|
||||
// Navigate immediately after successful start (don't wait for WebSocket)
|
||||
console.log('🎮 Navigating to /game...')
|
||||
navigate('/game')
|
||||
goGame()
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to start game:', error)
|
||||
@@ -125,7 +134,7 @@ const Lobby = () => {
|
||||
if (error.response?.status === 409) {
|
||||
console.log('Game already started, navigating to /game...')
|
||||
// Navigate anyway - game is already running
|
||||
navigate('/game')
|
||||
goGame()
|
||||
} else {
|
||||
alert(`Nem sikerült elindítani a játékot: ${error.response?.data?.error || error.message}`)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user