feat(ui): Enhance responsive design and game flow

- Intro: Change title to 'Sombras en París'
- Roll Call: Make screen fully responsive with fixed header
- Team Building: Clean up leader UI and make player tokens responsive
- Mission History: Fix expand/collapse interaction (z-index issue)
This commit is contained in:
Resistencia Dev
2025-12-12 19:14:14 +01:00
parent 1a7b667c77
commit c67f97845a
2 changed files with 43 additions and 33 deletions

View File

@@ -120,7 +120,7 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
</div>
<h1 className="z-10 text-5xl font-bold uppercase tracking-[0.3em] mb-8 text-yellow-500 drop-shadow-lg text-center">
Guerra Total
Sombras en París
</h1>
{/* Audio Auto-Play - Solo para el host */}
@@ -237,7 +237,7 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
// FASE ROLL CALL
if (gameState.phase === 'roll_call' as any) {
return (
<div className="relative w-full h-screen flex flex-col items-center justify-center bg-black overflow-hidden text-white font-mono">
<div className="relative w-full h-screen flex flex-col bg-black overflow-hidden text-white font-mono">
<div className="absolute inset-0 z-0">
@@ -245,11 +245,15 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
<div className="absolute inset-0 bg-black/70" />
</div>
<div className="z-10 w-full max-w-5xl px-4">
<h2 className="text-3xl text-center mb-12 uppercase tracking-[0.2em] text-gray-300 border-b border-gray-600 pb-4">
{/* --- 1. SECCIÓN SUPERIOR: TÍTULO (20-25% altura) --- */}
<div className="relative z-10 w-full h-[20vh] flex items-center justify-center px-4 border-b border-gray-600/50 bg-black/20 backdrop-blur-sm">
<h2 className="text-2xl md:text-3xl lg:text-4xl text-center uppercase tracking-[0.2em] text-gray-300 drop-shadow-lg">
Pasando Lista...
</h2>
</div>
{/* --- 2. SECCIÓN INFERIOR: JUGADORES (Resto de altura) --- */}
<div className="relative z-10 w-full flex-1 overflow-y-auto p-4 flex flex-col items-center">
{isHost && (
<audio
src="/assets/audio/Rondas.ogg"
@@ -258,7 +262,7 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
/>
)}
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-8">
<div className="w-full max-w-6xl grid grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-3 md:gap-8 justify-items-center content-center py-4">
{gameState.players.map((p, i) => {
return (
<motion.div
@@ -266,9 +270,10 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: i * 0.3 }} // Aparecen uno a uno
className="flex flex-col items-center gap-3"
className="flex flex-col items-center gap-1 md:gap-3 w-full"
>
<div className="w-32 h-32 rounded-full border-4 border-gray-400 overflow-hidden relative shadow-2xl bg-black">
{/* Avatar Responsive */}
<div className="w-20 h-20 md:w-32 md:h-32 rounded-full border-2 md:border-4 border-gray-400 overflow-hidden relative shadow-2xl bg-black">
<Image
src={`/assets/images/characters/${p.avatar}`}
alt="Avatar"
@@ -276,7 +281,8 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
className="object-cover grayscale contrast-125"
/>
</div>
<div className="bg-black/80 px-4 py-1 rounded border border-white/20 text-xl font-bold text-yellow-500 uppercase">
{/* Nombre Responsive */}
<div className="bg-black/80 px-2 py-0.5 md:px-4 md:py-1 rounded border border-white/20 text-xs md:text-xl font-bold text-yellow-500 uppercase text-center w-full truncate max-w-[120px] md:max-w-none">
{p.name}
</div>
</motion.div>
@@ -502,27 +508,31 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
className="flex flex-col items-center gap-6 w-full max-w-4xl"
>
{/* Información del líder */}
<div className="bg-yellow-600/90 text-black p-4 rounded-lg shadow-xl border-4 border-yellow-400 w-full text-center">
{/* Información del líder - SOLO para NO líderes */}
{!isLeader && (
<div className="bg-yellow-600/90 text-black p-2 rounded-lg shadow-xl border-4 border-yellow-400 w-full text-center mb-2">
<div className="flex items-center justify-center gap-3">
<Image src="/assets/images/tokens/token_leader.png" alt="Leader" width={40} height={40} />
<div>
<div className="text-sm uppercase tracking-wider font-bold">Líder Actual</div>
<div className="text-2xl font-bold">
<div className="text-xs uppercase tracking-wider font-bold">Líder Actual</div>
<div className="text-xl font-bold">
{gameState.players.find(p => p.id === gameState.currentLeaderId)?.name || 'Desconocido'}
</div>
</div>
<Image src="/assets/images/tokens/token_leader.png" alt="Leader" width={40} height={40} />
</div>
</div>
)}
{/* Mensaje para el líder o para los demás */}
<div className="bg-paper-bg text-black p-6 rounded shadow-2xl rotate-1 w-full text-center">
<h2 className="text-2xl font-bold font-mono mb-2 uppercase text-resistance-blue">
{/* Mensaje para el líder o para los demás */}
<div className="bg-paper-bg text-black p-4 md:p-6 rounded shadow-2xl w-full text-center">
<h2 className="text-xl md:text-2xl font-bold font-mono mb-2 uppercase text-resistance-blue">
{isLeader ? '🎯 TU TURNO: ELIGE TU EQUIPO' : '⏳ ESPERANDO AL LÍDER...'}
</h2>
{isLeader && (
<p className="mb-4 font-serif italic text-gray-700">
Se necesitan <span className="font-bold text-red-700 text-xl">{currentQuestSize} agentes</span> para la misión #{gameState.currentRound}.
</p>
)}
{/* Contador de seleccionados */}
{isLeader && (
@@ -790,9 +800,9 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
</AnimatePresence>
</div>
{/* JUGADORES (TIENDA DE CAMPAÑA) */}
<div className="z-10 w-full overflow-x-auto pb-4">
<div className="flex justify-center gap-4 min-w-max px-4">
{/* JUGADORES (TIENDA DE CAMPAÑA - Adaptable) */}
<div className="z-10 w-full py-2 bg-black/40 backdrop-blur-sm border-t border-white/10">
<div className="flex flex-wrap justify-center items-center gap-2 md:gap-6 px-2 w-full">
{gameState.players.map((player) => {
const isSelected = selectedTeam.includes(player.id);
const isMe = player.id === currentPlayerId;
@@ -811,8 +821,8 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
>
{/* Avatar */}
<div className={`
w-16 h-16 rounded-full border-2 overflow-hidden relative shadow-lg bg-black
${isSelected ? 'border-yellow-400 ring-4 ring-yellow-400/30' : 'border-gray-400'}
w-12 h-12 md:w-20 md:h-20 rounded-full border-2 overflow-hidden relative shadow-lg bg-black
${isSelected ? 'border-yellow-400 ring-2 md:ring-4 ring-yellow-400/30' : 'border-gray-400'}
${gameState.currentLeaderId === player.id ? 'ring-2 ring-white' : ''}
`}>
<Image
@@ -854,7 +864,7 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
{/* HISTÓRICO DE MISIONES (Esquina superior derecha) */}
{gameState.missionHistory.length > 0 && (
<div className="absolute top-4 right-4 bg-black/80 p-3 rounded-lg border border-white/20 backdrop-blur-sm">
<div className="absolute top-4 right-4 bg-black/80 p-3 rounded-lg border border-white/20 backdrop-blur-sm z-50">
<div className="text-[10px] text-gray-400 uppercase mb-2 text-center font-bold tracking-wider">Historial</div>
<div className="flex gap-2">
{gameState.missionHistory.map((mission, idx) => {
@@ -866,12 +876,12 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB
className={`w-8 h-8 rounded-full flex items-center justify-center text-xs font-bold border-2 cursor-pointer transition-all hover:scale-110 ${mission.isSuccess
? 'bg-blue-600 border-blue-400 text-white'
: 'bg-red-600 border-red-400 text-white'
} ${isExpanded ? 'ring-2 ring-yellow-400' : ''}`}
} ${isExpanded ? 'ring-2 ring-yellow-400 relative z-[60]' : ''}`}
title={`Misión ${mission.round}: ${mission.isSuccess ? 'Éxito' : 'Fracaso'} (${mission.successes} ${mission.fails})`}
onClick={(e) => {
e.stopPropagation();
console.log('Click en misión', idx, 'Estado actual:', expandedMission);
setExpandedMission(isExpanded ? null : idx);
console.log('Click en misión', idx);
setExpandedMission(prev => prev === idx ? null : idx);
}}
>
{mission.round}