fix: Corregir errores de linter y dependencias de React para Gitea
Some checks failed
CI/CD - Francia Ocupada (La Resistencia) / build-and-deploy (push) Failing after 5s
Some checks failed
CI/CD - Francia Ocupada (La Resistencia) / build-and-deploy (push) Failing after 5s
- Memoizar acciones en useSocket (useMemo) - Memoizar funciones en useSessionStorage (useCallback) - Completar dependency arrays en page.tsx y dashboard/page.tsx - Resolver advertencias de 'exhaustive-deps' para asegurar builds limpios
This commit is contained in:
@@ -46,7 +46,7 @@ export default function Dashboard() {
|
|||||||
socket.off('admin_action_success');
|
socket.off('admin_action_success');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, [isAuthenticated, socket]);
|
}, [isAuthenticated, socket, setActiveGames, setGameHistory]);
|
||||||
|
|
||||||
const handleLogin = (e: React.FormEvent) => {
|
const handleLogin = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -308,7 +308,7 @@ export default function Dashboard() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`text-[9px] font-black uppercase px-2 py-1 rounded shadow-sm ${entry.winner === 'resistance' ? 'bg-green-500/20 text-green-500' :
|
<div className={`text-[9px] font-black uppercase px-2 py-1 rounded shadow-sm ${entry.winner === 'resistance' ? 'bg-green-500/20 text-green-500' :
|
||||||
entry.winner === 'spies' ? 'bg-red-500/20 text-red-500' : 'bg-gray-700/20 text-gray-500'
|
entry.winner === 'spies' ? 'bg-red-500/20 text-red-500' : 'bg-gray-700/20 text-gray-500'
|
||||||
}`}>
|
}`}>
|
||||||
{entry.winner ? (entry.winner === 'resistance' ? 'RES' : 'SPIES') : 'LOGOUT'}
|
{entry.winner ? (entry.winner === 'resistance' ? 'RES' : 'SPIES') : 'LOGOUT'}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export default function Home() {
|
|||||||
|
|
||||||
setHasReconnected(true);
|
setHasReconnected(true);
|
||||||
}
|
}
|
||||||
}, [session, isConnected, hasReconnected]);
|
}, [session, isConnected, hasReconnected, actions, setPlayerName, setFullPlayerName, setView, setHasReconnected]);
|
||||||
|
|
||||||
// Efecto para cambiar a vista de juego cuando el servidor nos une
|
// Efecto para cambiar a vista de juego cuando el servidor nos une
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -71,7 +71,7 @@ export default function Home() {
|
|||||||
updateSession({ currentView: 'lobby', roomId: undefined });
|
updateSession({ currentView: 'lobby', roomId: undefined });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [gameState, view, hasReconnected]);
|
}, [gameState, view, hasReconnected, updateSession, setView]);
|
||||||
|
|
||||||
// Listener para errores de socket que deben expulsar al lobby
|
// Listener para errores de socket que deben expulsar al lobby
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -88,7 +88,7 @@ export default function Home() {
|
|||||||
return () => {
|
return () => {
|
||||||
socket.off('error', handleError);
|
socket.off('error', handleError);
|
||||||
};
|
};
|
||||||
}, [socket, updateSession]);
|
}, [socket, updateSession, setView]);
|
||||||
|
|
||||||
const handleLogin = (e: React.FormEvent) => {
|
const handleLogin = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
|
|
||||||
interface SessionData {
|
interface SessionData {
|
||||||
playerName: string;
|
playerName: string;
|
||||||
@@ -25,24 +25,26 @@ export function useSessionStorage() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Guardar sesión
|
// Guardar sesión
|
||||||
const saveSession = (data: SessionData) => {
|
const saveSession = useCallback((data: SessionData) => {
|
||||||
localStorage.setItem('resistencia_session', JSON.stringify(data));
|
localStorage.setItem('resistencia_session', JSON.stringify(data));
|
||||||
setSession(data);
|
setSession(data);
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
// Actualizar sesión parcialmente
|
// Actualizar sesión parcialmente
|
||||||
const updateSession = (partial: Partial<SessionData>) => {
|
const updateSession = useCallback((partial: Partial<SessionData>) => {
|
||||||
if (session) {
|
setSession(prev => {
|
||||||
const updated = { ...session, ...partial };
|
if (!prev) return null;
|
||||||
saveSession(updated);
|
const updated = { ...prev, ...partial };
|
||||||
}
|
localStorage.setItem('resistencia_session', JSON.stringify(updated));
|
||||||
};
|
return updated;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Limpiar sesión
|
// Limpiar sesión
|
||||||
const clearSession = () => {
|
const clearSession = useCallback(() => {
|
||||||
localStorage.removeItem('resistencia_session');
|
localStorage.removeItem('resistencia_session');
|
||||||
setSession(null);
|
setSession(null);
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
session,
|
session,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState, useMemo } from 'react';
|
||||||
import { io, Socket } from 'socket.io-client';
|
import { io, Socket } from 'socket.io-client';
|
||||||
import { GameState, Player } from '../../../shared/types';
|
import { GameState } from '../../../shared/types';
|
||||||
|
|
||||||
const SOCKET_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000';
|
const SOCKET_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000';
|
||||||
|
|
||||||
@@ -35,25 +35,23 @@ export const useSocket = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Manejar propio unirse a partida
|
// Manejar propio unirse a partida
|
||||||
socketInstance.on('game_joined', ({ roomId, state }) => {
|
socketInstance.on('game_joined', ({ state }) => {
|
||||||
setGameState(state);
|
setGameState(state);
|
||||||
// Podríamos guardar el roomId en localStorage o similar si quisiéramos persistencia
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socketInstance.on('error', (msg: string) => {
|
socketInstance.on('error', (msg: string) => {
|
||||||
alert(msg); // Simple error handling for now
|
alert(msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Manejar finalización de partida por el host
|
// Manejar finalización de partida por el host
|
||||||
socketInstance.on('game_finalized', () => {
|
socketInstance.on('game_finalized', () => {
|
||||||
console.log('La partida ha sido finalizada por el host');
|
console.log('La partida ha sido finalizada por el host');
|
||||||
setGameState(null); // Resetear estado para volver al lobby
|
setGameState(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Manejar cuando un jugador abandona la partida
|
// Manejar cuando un jugador abandona la partida
|
||||||
socketInstance.on('player_left_game', ({ playerName }: { playerName: string }) => {
|
socketInstance.on('player_left_game', ({ playerName }: { playerName: string }) => {
|
||||||
console.log(`${playerName} ha abandonado la partida`);
|
console.log(`${playerName} ha abandonado la partida`);
|
||||||
// El servidor ya habrá cerrado la partida, solo mostramos mensaje
|
|
||||||
});
|
});
|
||||||
|
|
||||||
setSocket(socketInstance);
|
setSocket(socketInstance);
|
||||||
@@ -63,71 +61,52 @@ export const useSocket = () => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Funciones helper para enviar acciones
|
const actions = useMemo(() => ({
|
||||||
const createGame = (hostName: string, maxPlayers: number, password?: string) => {
|
createGame: (hostName: string, maxPlayers: number, password?: string) => {
|
||||||
socket?.emit('create_game', { hostName, maxPlayers, password });
|
socket?.emit('create_game', { hostName, maxPlayers, password });
|
||||||
};
|
},
|
||||||
|
joinGame: (roomId: string, playerName: string, password?: string) => {
|
||||||
const joinGame = (roomId: string, playerName: string, password?: string) => {
|
socket?.emit('join_game', { roomId, playerName, password });
|
||||||
socket?.emit('join_game', { roomId, playerName, password });
|
},
|
||||||
};
|
refreshRooms: () => {
|
||||||
|
socket?.emit('get_rooms');
|
||||||
const refreshRooms = () => {
|
},
|
||||||
socket?.emit('get_rooms');
|
startGame: () => {
|
||||||
};
|
socket?.emit('start_game', { roomId: gameState?.roomId });
|
||||||
|
},
|
||||||
const startGame = () => {
|
proposeTeam: (teamIds: string[]) => {
|
||||||
socket?.emit('start_game', { roomId: gameState?.roomId });
|
socket?.emit('propose_team', { roomId: gameState?.roomId, teamIds });
|
||||||
};
|
},
|
||||||
|
voteTeam: (approve: boolean) => {
|
||||||
const proposeTeam = (teamIds: string[]) => {
|
socket?.emit('vote_team', { roomId: gameState?.roomId, approve });
|
||||||
socket?.emit('propose_team', { roomId: gameState?.roomId, teamIds });
|
},
|
||||||
};
|
voteMission: (success: boolean) => {
|
||||||
|
socket?.emit('vote_mission', { roomId: gameState?.roomId, success });
|
||||||
const voteTeam = (approve: boolean) => {
|
},
|
||||||
socket?.emit('vote_team', { roomId: gameState?.roomId, approve });
|
voteLeader: (approve: boolean) => socket?.emit('vote_leader', { roomId: gameState?.roomId, approve }),
|
||||||
};
|
assassinKill: (targetId: string) => {
|
||||||
|
socket?.emit('assassin_kill', { roomId: gameState?.roomId, targetId });
|
||||||
const voteMission = (success: boolean) => {
|
},
|
||||||
socket?.emit('vote_mission', { roomId: gameState?.roomId, success });
|
leaveGame: () => {
|
||||||
};
|
socket?.emit('leave_game', { roomId: gameState?.roomId });
|
||||||
|
},
|
||||||
const assassinKill = (targetId: string) => {
|
reconnectSession: (sessionData: { playerName: string; roomId?: string }) => {
|
||||||
socket?.emit('assassin_kill', { roomId: gameState?.roomId, targetId });
|
socket?.emit('reconnect_session', sessionData);
|
||||||
};
|
},
|
||||||
|
finishIntro: () => socket?.emit('finish_intro', { roomId: gameState?.roomId }),
|
||||||
const leaveGame = () => {
|
finishReveal: () => socket?.emit('finish_reveal', { roomId: gameState?.roomId }),
|
||||||
socket?.emit('leave_game', { roomId: gameState?.roomId });
|
finishRollCall: () => socket?.emit('finish_roll_call', { roomId: gameState?.roomId }),
|
||||||
};
|
finishMissionReveal: () => socket?.emit('finish_reveal', { roomId: gameState?.roomId }),
|
||||||
|
finishMissionResult: () => socket?.emit('finish_mission_result', { roomId: gameState?.roomId }),
|
||||||
const reconnectSession = (sessionData: { playerName: string; roomId?: string }) => {
|
restartGame: () => socket?.emit('restart_game', { roomId: gameState?.roomId }),
|
||||||
socket?.emit('reconnect_session', sessionData);
|
finalizeGame: () => socket?.emit('finalize_game', { roomId: gameState?.roomId })
|
||||||
};
|
}), [socket, gameState?.roomId]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
socket,
|
socket,
|
||||||
isConnected,
|
isConnected,
|
||||||
gameState,
|
gameState,
|
||||||
roomsList,
|
roomsList,
|
||||||
actions: {
|
actions
|
||||||
createGame,
|
|
||||||
joinGame,
|
|
||||||
refreshRooms,
|
|
||||||
startGame,
|
|
||||||
proposeTeam,
|
|
||||||
voteTeam,
|
|
||||||
voteMission,
|
|
||||||
voteLeader: (approve: boolean) => socket?.emit('vote_leader', { roomId: gameState?.roomId, approve }),
|
|
||||||
assassinKill,
|
|
||||||
leaveGame,
|
|
||||||
reconnectSession,
|
|
||||||
finishIntro: () => socket?.emit('finish_intro', { roomId: gameState?.roomId }),
|
|
||||||
finishReveal: () => socket?.emit('finish_reveal', { roomId: gameState?.roomId }),
|
|
||||||
finishRollCall: () => socket?.emit('finish_roll_call', { roomId: gameState?.roomId }),
|
|
||||||
finishMissionReveal: () => socket?.emit('finish_reveal', { roomId: gameState?.roomId }),
|
|
||||||
finishMissionResult: () => socket?.emit('finish_mission_result', { roomId: gameState?.roomId }),
|
|
||||||
restartGame: () => socket?.emit('restart_game', { roomId: gameState?.roomId }),
|
|
||||||
finalizeGame: () => socket?.emit('finalize_game', { roomId: gameState?.roomId })
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user