Add React frontend and clean up legacy HTTP backend
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
import { useEffect } from 'react';
|
||||
import { BrowserRouter, Routes, Route, Navigate, useNavigate } from 'react-router-dom';
|
||||
import { useGameStore } from './store/gameStore';
|
||||
import { socket, emit } from './lib/socket';
|
||||
import type { MyPlayer } from './types';
|
||||
import GameList from './pages/GameList';
|
||||
import Lobby from './pages/Lobby';
|
||||
import GameTable from './pages/GameTable';
|
||||
|
||||
function AppInner() {
|
||||
const navigate = useNavigate();
|
||||
const myPlayer = useGameStore((s) => s.myPlayer);
|
||||
const gameStatus = useGameStore((s) => s.gameStatus);
|
||||
const error = useGameStore((s) => s.error);
|
||||
const clearError = useGameStore((s) => s.clearError);
|
||||
|
||||
// Reconnect on every socket connect event (handles auto-reconnects after network drops)
|
||||
useEffect(() => {
|
||||
const doReconnect = () => {
|
||||
const saved = localStorage.getItem('bridzik_player');
|
||||
if (!saved) return;
|
||||
const player = JSON.parse(saved) as MyPlayer;
|
||||
emit.reconnectToGame(player.gid, player.token);
|
||||
};
|
||||
socket.on('connect', doReconnect);
|
||||
if (socket.connected) doReconnect();
|
||||
return () => { socket.off('connect', doReconnect); };
|
||||
}, []);
|
||||
|
||||
// Single authoritative navigation: derive target from store state
|
||||
const targetRoute = myPlayer
|
||||
? gameStatus ? `/game/${gameStatus.gid}` : `/lobby/${myPlayer.gid}`
|
||||
: null;
|
||||
|
||||
useEffect(() => {
|
||||
if (!targetRoute) return;
|
||||
navigate(targetRoute, { replace: true });
|
||||
}, [targetRoute, navigate]);
|
||||
|
||||
// Auto-dismiss errors after 4 s
|
||||
useEffect(() => {
|
||||
if (!error) return;
|
||||
const t = setTimeout(clearError, 4000);
|
||||
return () => clearTimeout(t);
|
||||
}, [error, clearError]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{error && (
|
||||
<div className="fixed top-4 left-1/2 -translate-x-1/2 z-50 bg-red-600 text-white px-4 py-2 rounded-lg shadow-lg text-sm max-w-xs text-center">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
<Routes>
|
||||
<Route path="/" element={<GameList />} />
|
||||
<Route path="/lobby/:gid" element={<Lobby />} />
|
||||
<Route path="/game/:gid" element={<GameTable />} />
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
</Routes>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<AppInner />
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user