diff --git a/client/src/components/GameBoard.tsx b/client/src/components/GameBoard.tsx index 2afb4ac..95263a9 100644 --- a/client/src/components/GameBoard.tsx +++ b/client/src/components/GameBoard.tsx @@ -48,6 +48,22 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB } }, [gameState.phase, gameState.currentLeaderId]); + // Estado para controlar cuándo mostrar el tablero + const [showBoard, setShowBoard] = useState(false); + + // Mostrar tablero solo 5 segundos después de MISSION_RESULT + useEffect(() => { + if (gameState.phase === GamePhase.MISSION_RESULT) { + setShowBoard(true); + const timer = setTimeout(() => { + setShowBoard(false); + }, 5000); // 5 segundos + return () => clearTimeout(timer); + } else { + setShowBoard(false); + } + }, [gameState.phase]); + const currentPlayer = gameState.players.find(p => p.id === currentPlayerId); const isLeader = gameState.currentLeaderId === currentPlayerId; // FIX: Usar currentLeaderId del estado @@ -80,6 +96,15 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB { left: '82%', top: '40%' }, // Misión 5 ]; + // Nombres de las misiones + const missionNames = [ + 'Sabotaje en el Tren', + 'Rescate del Prisionero', + 'Destrucción del Puente', + 'Robo de Documentos', + 'Asalto al Cuartel General' + ]; + // --- UI/Efectos para FASES TEMPRANAS --- const isHost = gameState.hostId === currentPlayerId; @@ -277,82 +302,106 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
- {/* --- MAPA TÁCTICO (TABLERO) --- */} + {/* --- MAPA TÁCTICO (TABLERO) O CARTA DE MISIÓN --- */}
- Tactical Map + {showBoard ? ( + <> + {/* TABLERO CON TOKENS */} + Tactical Map - {/* TOKENS SOBRE EL MAPA */} - {missionCoords.map((coord, idx) => { - const result = gameState.questResults[idx]; - const isCurrent = gameState.currentRound === idx + 1; + {/* TOKENS SOBRE EL MAPA */} + {missionCoords.map((coord, idx) => { + const result = gameState.questResults[idx]; + const isCurrent = gameState.currentRound === idx + 1; - return ( -
- {/* Marcador de Ronda Actual */} - {isCurrent && ( - - Current Round - - )} + {/* Marcador de Ronda Actual */} + {isCurrent && ( + + Current Round + + )} - {/* Resultado de Misión (Éxito/Fracaso) */} - {result === true && ( - -
- Success -
-
- )} - {result === false && ( - -
- Fail -
-
- )} + {/* Resultado de Misión (Éxito/Fracaso) */} + {result === true && ( + +
+ Success +
+
+ )} + {result === false && ( + +
+ Fail +
+
+ )} +
+ ); + })} + + {/* TRACK DE VOTOS FALLIDOS */} +
+
Votos Rechazados
+
+ {[...Array(5)].map((_, i) => ( +
+ ))} +
- ); - })} - - {/* TRACK DE VOTOS FALLIDOS (Pequeño indicador en la esquina inferior izquierda del mapa) */} -
-
Votos Rechazados
-
- {[...Array(5)].map((_, i) => ( -
- ))} -
-
+ + ) : ( + /* CARTA DE MISIÓN CON TÍTULO */ + <> + {`Mission + {/* Título y subtítulo sobre la carta */} +
+

+ Misión {gameState.currentRound} +

+

+ {missionNames[gameState.currentRound - 1]} +

+
+ + )}
{/* --- ÁREA DE JUEGO (CARTAS Y ACCIONES) --- */} diff --git a/server/src/index.ts b/server/src/index.ts index 97d239b..cc616bf 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -5,6 +5,7 @@ import cors from 'cors'; import dotenv from 'dotenv'; import crypto from 'crypto'; import { Game } from './models/Game'; +import { GamePhase } from '../../shared/types'; dotenv.config(); @@ -251,9 +252,15 @@ io.on('connection', (socket) => { // 5.2 FINALIZAR PANTALLA DE RESULTADO socket.on('finish_mission_result', ({ roomId }) => { const game = games[roomId]; - if (game && game.hostId === socket.id && game.state.phase === 'mission_result') { + if (game && game.hostId === socket.id && game.state.phase === GamePhase.MISSION_RESULT) { game.finishMissionResult(); io.to(roomId).emit('game_state', game.state); + + // Si volvió a vote_leader (nueva ronda), iniciar timer + // TypeScript no detecta que finishMissionResult() cambia la fase, usamos type assertion + if ((game.state.phase as GamePhase) === GamePhase.VOTE_LEADER) { + startLeaderVoteTimer(roomId); + } } });