'use client'; import { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { useSocket } from '../../hooks/useSocket'; import { Shield, Users, Gamepad2, LogOut, Clock, History, UserMinus, Key, ChevronDown } from 'lucide-react'; const ADMIN_PASSWORD = process.env.NEXT_PUBLIC_ADMIN_PASSWORD || "admin123"; export default function Dashboard() { const { socket, isConnected } = useSocket(); const [password, setPassword] = useState(''); const [isAuthenticated, setIsAuthenticated] = useState(false); const [activeGames, setActiveGames] = useState([]); const [gameHistory, setGameHistory] = useState([]); const [error, setError] = useState(''); const [expandedGames, setExpandedGames] = useState>(new Set()); // Comprobar sesión al cargar useEffect(() => { const savedSession = localStorage.getItem('resistencia_admin_session'); if (savedSession === 'active') { setIsAuthenticated(true); } }, []); // Cargar datos y escuchar actualizaciones en tiempo real useEffect(() => { if (isAuthenticated && socket) { // Solicitar datos iniciales socket.emit('admin_get_data'); // Escuchar actualizaciones (el servidor emite a admin-room) socket.on('admin_data', (data: any) => { console.log('[ADMIN] Datos recibidos:', data); setActiveGames(data.activeGames); setGameHistory(data.history); }); socket.on('admin_action_success', () => { console.log('[ADMIN] Acción realizada con éxito'); socket.emit('admin_get_data'); }); return () => { socket.off('admin_data'); socket.off('admin_action_success'); }; } }, [isAuthenticated, socket]); const handleLogin = (e: React.FormEvent) => { e.preventDefault(); if (password === ADMIN_PASSWORD) { setIsAuthenticated(true); localStorage.setItem('resistencia_admin_session', 'active'); setError(''); } else { setError('Acceso Denegado: Contraseña incorrecta'); } }; const handleLogout = () => { localStorage.removeItem('resistencia_admin_session'); setIsAuthenticated(false); setPassword(''); }; const closeGame = (roomId: string) => { if (confirm('¿Seguro que quieres forzar el cierre de esta partida?')) { socket?.emit('admin_close_game', { roomId }); } }; const kickPlayer = (roomId: string, socketId: string) => { if (confirm('¿Seguro que quieres expulsar a este jugador?')) { socket?.emit('admin_kick_player', { roomId, targetSocketId: socketId }); } }; const toggleGame = (id: string) => { setExpandedGames(prev => { const newSet = new Set(prev); if (newSet.has(id)) newSet.delete(id); else newSet.add(id); return newSet; }); }; if (!isAuthenticated) { return (

Acceso Admin

Panel de Control de La Resistencia

setPassword(e.target.value)} placeholder="Introduce la contraseña" className="w-full bg-[#1a1a20] border border-white/5 rounded-2xl pl-12 pr-6 py-4 text-white focus:outline-none focus:ring-2 focus:ring-red-600/50 transition-all placeholder:text-gray-600 font-medium" />
{error && ( {error} )}
); } return (
{/* Header */}
Seguimiento de Operaciones

Comandante

Status Servidor
{isConnected ? 'OPERATIVO' : 'DESCONECTADO'}
{/* Panel Latino: Estadísticas Rápidas */}
{[ { label: 'Partidas Activas', value: activeGames.length, color: 'text-red-500', icon: Gamepad2 }, { label: 'Agentes Online', value: activeGames.reduce((acc, g) => acc + g.currentPlayers, 0), color: 'text-blue-400', icon: Users }, { label: 'Misiones Registradas', value: gameHistory.length, color: 'text-orange-400', icon: History }, { label: 'Uso de CPU', value: '4%', color: 'text-green-400', icon: Clock } ].map((stat, i) => (

{stat.label}

{stat.value}

))}
{/* Columna Principal: Partidas Activas */}

Canales de Radio Activos

{activeGames.length === 0 ? (

Silencio Radioeléctrico

Buscando señales de misiones activas...

) : ( activeGames.map((game: any) => ( {/* Cabecera Compacta (Clickable) */}
toggleGame(game.id)} className="flex flex-wrap items-center justify-between p-6 cursor-pointer gap-4" >

{game.name}

ID: {game.id.slice(0, 6)} {new Date(game.created_at || Date.now()).toLocaleTimeString()}
{game.currentPlayers} / {game.maxPlayers}
{game.status}
{game.currentRound > 0 && (
{game.matchNumber > 1 ? `P${game.matchNumber} - R${game.currentRound}` : `Ronda ${game.currentRound}`}
)}
{/* Contenido Expandible */} {expandedGames.has(game.id) && (
{/* Panel de Control */}
{/* Grid de Jugadores */}
{game.players.map((player: any) => (
{player.name[0].toUpperCase()}

{player.name}

AG-{player.id.slice(0, 4)}

))}
)}
)) )}
{/* Columna Lateral: Archivo Histórico */}

Informe Forense

Archivos Recientes

{gameHistory.length === 0 ? (

Sin registros

) : ( gameHistory.map((entry: any) => (
{/* Cabecera Historial */}
toggleGame(entry.id)} className={`p-4 cursor-pointer hover:bg-white/5 transition-colors flex justify-between items-center group relative overflow-hidden ${expandedGames.has(entry.id) ? 'bg-white/[0.02]' : ''}`} >

{entry.room_name}

{entry.host_name}
{entry.winner ? (entry.winner === 'resistance' ? 'ALIAD' : 'AXIS') : '??'}
{/* Detalles Historial Expandido */} {expandedGames.has(entry.id) && (
FECHA: {new Date(entry.created_at).toLocaleDateString()}
HORA: {new Date(entry.created_at).toLocaleTimeString()}
AGENTES: {entry.players.split(',').length}
{entry.matches_played > 0 && ( <>
PARTIDAS: {entry.matches_played}
{entry.match_results && entry.match_results.length > 0 && (
RESULTADOS:
{entry.match_results.split(',').map((res: string, idx: number) => (
))}
)} )} {entry.players && (

PARTICIPANTES:

{entry.players.split(',').join(', ')}

)}
)}
)) )}
); }