refactor(page): extract handlers and utils into dedicated modules

This commit is contained in:
jessy-david-dev
2026-04-10 16:44:24 +02:00
parent 58d1a43a35
commit 4f6e793c74
3 changed files with 118 additions and 79 deletions
+17 -78
View File
@@ -6,6 +6,8 @@ import type { Screen } from "../lib/types";
import { useSoloGame, useSoloKeyboard } from "../lib/useSoloGame"; import { useSoloGame, useSoloKeyboard } from "../lib/useSoloGame";
import { useMultiGame } from "../lib/useMultiGame"; import { useMultiGame } from "../lib/useMultiGame";
import { loadSession, clearSession } from "../lib/session"; import { loadSession, clearSession } from "../lib/session";
import { fmt, saveGame } from "../lib/utils";
import { useGameHandlers } from "../lib/useGameHandlers";
import { HomeScreen } from "./components/HomeScreen"; import { HomeScreen } from "./components/HomeScreen";
import { LobbyScreen } from "./components/LobbyScreen"; import { LobbyScreen } from "./components/LobbyScreen";
import { SoloScreen } from "./components/SoloScreen"; import { SoloScreen } from "./components/SoloScreen";
@@ -13,30 +15,6 @@ import { GameScreen } from "./components/GameScreen";
import { AuthModal } from "./components/AuthModal"; import { AuthModal } from "./components/AuthModal";
import { ProfileScreen } from "./components/ProfileScreen"; import { ProfileScreen } from "./components/ProfileScreen";
function fmt(s: number): string {
const m = Math.floor(s / 60);
const sec = Math.floor(s % 60);
return `${m}:${String(sec).padStart(2, "0")}`;
}
async function saveGame(data: {
mode: string;
startArticle: string;
targetArticle: string;
path: string[];
clicks: number;
timeSeconds: number;
won: boolean;
}) {
try {
await fetch("/api/games", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
} catch { /* silencieux — pas de compte ou hors ligne */ }
}
export default function WikiRush() { export default function WikiRush() {
const { data: session } = useSession(); const { data: session } = useSession();
const [screen, setScreen] = useState<Screen>("home"); const [screen, setScreen] = useState<Screen>("home");
@@ -49,12 +27,16 @@ export default function WikiRush() {
const solo = useSoloGame(); const solo = useSoloGame();
const multi = useMultiGame(); const multi = useMultiGame();
const handlers = useGameHandlers({
solo, multi, playerName, joinCode, setScreen, setError, setLoading,
});
// Pré-remplir le pseudo avec le nom du compte connecté // Pré-remplir le pseudo avec le nom du compte connecté
useEffect(() => { useEffect(() => {
if (session?.user?.name && !playerName) setPlayerName(session.user.name); if (session?.user?.name && !playerName) setPlayerName(session.user.name);
}, [session]); // eslint-disable-line react-hooks/exhaustive-deps }, [session]); // eslint-disable-line react-hooks/exhaustive-deps
// Restaurer la session apres F5 // Restaurer la session après F5
useEffect(() => { useEffect(() => {
const saved = loadSession(); const saved = loadSession();
if (!saved) return; if (!saved) return;
@@ -84,10 +66,10 @@ export default function WikiRush() {
return () => window.removeEventListener("popstate", onPop); return () => window.removeEventListener("popstate", onPop);
}, []); }, []);
// Backspace = retour arriere en solo // Backspace = retour arrière en solo
useSoloKeyboard(screen === "solo" && solo.phase === "playing", solo.goBack); useSoloKeyboard(screen === "solo" && solo.phase === "playing", solo.goBack);
// Sync ecran quand la room change de phase // Sync écran quand la room change de phase
useEffect(() => { useEffect(() => {
if (!multi.room) return; if (!multi.room) return;
const { phase } = multi.room; const { phase } = multi.room;
@@ -128,49 +110,6 @@ export default function WikiRush() {
}); });
}, [multi.room?.phase]); // eslint-disable-line react-hooks/exhaustive-deps }, [multi.room?.phase]); // eslint-disable-line react-hooks/exhaustive-deps
// ---- Actions home ----
async function handleCreateRoom() {
if (!playerName.trim()) { setError("Entre ton pseudo !"); return; }
setLoading(true); setError(null);
const { error: err } = await multi.createRoom(playerName.trim());
setLoading(false);
if (err) { setError(err); return; }
setScreen("lobby");
}
async function handleJoinRoom() {
if (!playerName.trim()) { setError("Entre ton pseudo !"); return; }
if (joinCode.trim().length !== 4) { setError("Le code doit faire 4 lettres"); return; }
setLoading(true); setError(null);
const { error: err } = await multi.joinRoom(playerName.trim(), joinCode.trim().toUpperCase());
setLoading(false);
if (err) { setError(err); return; }
setScreen("lobby");
}
async function handleStartGame() {
setLoading(true); setError(null);
const { error: err } = await multi.startGame();
setLoading(false);
if (err) setError(err);
}
async function handleNextRound() {
await multi.nextRound();
setScreen("lobby");
}
async function handleResetGame() {
await multi.resetGame();
setScreen("lobby");
}
function handleLeave() {
multi.leave();
setScreen("home");
}
// ---- Rendu ---- // ---- Rendu ----
if (screen === "profile") { if (screen === "profile") {
@@ -189,9 +128,9 @@ export default function WikiRush() {
playerName={playerName} setPlayerName={setPlayerName} playerName={playerName} setPlayerName={setPlayerName}
joinCode={joinCode} setJoinCode={setJoinCode} joinCode={joinCode} setJoinCode={setJoinCode}
error={error} setError={setError} loading={loading} error={error} setError={setError} loading={loading}
onCreateRoom={handleCreateRoom} onCreateRoom={handlers.handleCreateRoom}
onJoinRoom={handleJoinRoom} onJoinRoom={handlers.handleJoinRoom}
onSolo={() => { solo.reset(); setScreen("solo"); }} onSolo={handlers.handleSolo}
session={session} session={session}
onShowAuth={() => setShowAuth(true)} onShowAuth={() => setShowAuth(true)}
onShowProfile={() => setScreen("profile")} onShowProfile={() => setScreen("profile")}
@@ -230,9 +169,9 @@ export default function WikiRush() {
<LobbyScreen <LobbyScreen
room={multi.room} playerId={multi.playerId} room={multi.room} playerId={multi.playerId}
error={error} setError={setError} loading={loading} error={error} setError={setError} loading={loading}
onLeave={handleLeave} onLeave={handlers.handleLeave}
onStart={handleStartGame} onStart={handlers.handleStartGame}
onReset={handleResetGame} onReset={handlers.handleResetGame}
/> />
); );
} }
@@ -248,8 +187,8 @@ export default function WikiRush() {
countdown={multi.countdown} countdown={multi.countdown}
onNavigate={multi.navigate} onNavigate={multi.navigate}
onRetry={multi.retryLoad} onRetry={multi.retryLoad}
onNextRound={handleNextRound} onNextRound={handlers.handleNextRound}
onResetGame={handleResetGame} onResetGame={handlers.handleResetGame}
/> />
); );
} }
+77
View File
@@ -0,0 +1,77 @@
import { Dispatch, SetStateAction } from "react";
import type { Screen } from "./types";
import type { useSoloGame } from "./useSoloGame";
import type { useMultiGame } from "./useMultiGame";
type UseSoloGame = ReturnType<typeof useSoloGame>;
type UseMultiGame = ReturnType<typeof useMultiGame>;
type Handlers = {
solo: UseSoloGame;
multi: UseMultiGame;
playerName: string;
joinCode: string;
setScreen: Dispatch<SetStateAction<Screen>>;
setError: Dispatch<SetStateAction<string | null>>;
setLoading: Dispatch<SetStateAction<boolean>>;
};
export function useGameHandlers({
solo, multi, playerName, joinCode, setScreen, setError, setLoading,
}: Handlers) {
async function handleCreateRoom() {
if (!playerName.trim()) { setError("Entre ton pseudo !"); return; }
setLoading(true); setError(null);
const { error: err } = await multi.createRoom(playerName.trim());
setLoading(false);
if (err) { setError(err); return; }
setScreen("lobby");
}
async function handleJoinRoom() {
if (!playerName.trim()) { setError("Entre ton pseudo !"); return; }
if (joinCode.trim().length !== 4) { setError("Le code doit faire 4 lettres"); return; }
setLoading(true); setError(null);
const { error: err } = await multi.joinRoom(playerName.trim(), joinCode.trim().toUpperCase());
setLoading(false);
if (err) { setError(err); return; }
setScreen("lobby");
}
async function handleStartGame() {
setLoading(true); setError(null);
const { error: err } = await multi.startGame();
setLoading(false);
if (err) setError(err);
}
async function handleNextRound() {
await multi.nextRound();
setScreen("lobby");
}
async function handleResetGame() {
await multi.resetGame();
setScreen("lobby");
}
function handleLeave() {
multi.leave();
setScreen("home");
}
function handleSolo() {
solo.reset();
setScreen("solo");
}
return {
handleCreateRoom,
handleJoinRoom,
handleStartGame,
handleNextRound,
handleResetGame,
handleLeave,
handleSolo,
};
}
+23
View File
@@ -0,0 +1,23 @@
export function fmt(s: number): string {
const m = Math.floor(s / 60);
const sec = Math.floor(s % 60);
return `${m}:${String(sec).padStart(2, "0")}`;
}
export async function saveGame(data: {
mode: string;
startArticle: string;
targetArticle: string;
path: string[];
clicks: number;
timeSeconds: number;
won: boolean;
}) {
try {
await fetch("/api/games", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
} catch { /* silencieux — pas de compte ou hors ligne */ }
}