diff --git a/client/src/app/ai/page.tsx b/client/src/app/ai/page.tsx index c7677f7..5c318ac 100644 --- a/client/src/app/ai/page.tsx +++ b/client/src/app/ai/page.tsx @@ -66,7 +66,10 @@ export default function AiGamePage() { const { move } = await res.json(); if (move) { setGame((prev) => { - const newGame = new Chess(prev.fen()); + // Load from PGN (not FEN) to preserve the full move history + const newGame = new Chess(); + const prevPgn = prev.pgn(); + if (prevPgn) newGame.loadPgn(prevPgn); const result = newGame.move({ from: move.slice(0, 2), to: move.slice(2, 4), promotion: move[4] || "q" }); if (result) setLastMove({ from: result.from, to: result.to }); setStatus(getStatus(newGame)); @@ -86,7 +89,10 @@ export default function AiGamePage() { const currentTurn = game.turn() === "w" ? "white" : "black"; if (currentTurn !== playerColor) return false; - const newGame = new Chess(game.fen()); + // Load from PGN (not FEN) to preserve the full move history + const newGame = new Chess(); + const currentPgn = game.pgn(); + if (currentPgn) newGame.loadPgn(currentPgn); let move = null; try { move = newGame.move({ from: sourceSquare, to: targetSquare, promotion: "q" }); diff --git a/client/src/app/page.tsx b/client/src/app/page.tsx index d74b5c3..b3116db 100644 --- a/client/src/app/page.tsx +++ b/client/src/app/page.tsx @@ -1,9 +1,8 @@ "use client"; -import CreateGame from "@/components/home/CreateGame"; -import JoinGame from "@/components/home/JoinGame"; import PublicGames from "@/components/home/PublicGames/PublicGames"; import LiveGames from "@/components/home/LiveGames"; +import RecentGames from "@/components/home/RecentGames"; import Link from "next/link"; import { useSession } from "@/context/session"; @@ -14,77 +13,35 @@ export default function Home() { return (
- {/* Hauptaktionen */} -
- -
-
-

Spiel erstellen

-

Erstelle eine Partie und teile den Einladungslink mit Freunden

-
- -
+
+ {/* Spielen-Karte */} + +
+ +

Spielen

+

+ Partie erstellen, gegen KI, Turnier & mehr +

-
+ -
-
-

Gegen KI spielen

-

Fordere Stockfish auf verschiedenen Stufen heraus — von Anfänger bis Meister

-
- Jetzt spielen -
-
+ {/* Öffentliche Spiele */} +
+
- -
-
- {isLoggedIn ? ( - <> -

Freunde

-

Freunde hinzufügen, verwalten und zu einer Partie einladen

-
- Freunde verwalten -
- - ) : ( - <> -

Einladung annehmen

-

Einladungslink oder Code eingeben um beizutreten

- - - )} -
-
- -
-
-

Tagespartien

-

Spiele in deinem eigenen Tempo — Züge bis zu 3 Tage Zeit

-
- Tagespartien -
-
-
- -
-
-

Turnier

-

Spiele Round-Robin Turniere gegen mehrere Gegner

-
- Turniere -
-
-
-
+ {/* Letzte Spiele des eingeloggten Users */} + {isLoggedIn && user.id && typeof user.id === "number" && ( + + )} + {/* Laufende Partien – Live-Kacheln */} - {/* Öffentliche Spiele */} - -
); } diff --git a/client/src/app/play/page.tsx b/client/src/app/play/page.tsx new file mode 100644 index 0000000..e412fa5 --- /dev/null +++ b/client/src/app/play/page.tsx @@ -0,0 +1,81 @@ +"use client"; + +import CreateGame from "@/components/home/CreateGame"; +import JoinGame from "@/components/home/JoinGame"; +import Link from "next/link"; +import { useSession } from "@/context/session"; + +export default function PlayPage() { + const { user } = useSession(); + const isLoggedIn = user?.id && typeof user.id === "number"; + + return ( +
+

Spielen

+ +
+ +
+
+

Spiel erstellen

+

Erstelle eine Partie und teile den Einladungslink mit Freunden

+
+ +
+
+
+ +
+
+

Gegen KI spielen

+

Fordere Stockfish auf verschiedenen Stufen heraus — von Anfänger bis Meister

+
+ Jetzt spielen +
+
+
+ + {isLoggedIn ? ( +
+
+

Freunde

+

Freunde hinzufügen, verwalten und zu einer Partie einladen

+
+ Freunde verwalten +
+
+
+ ) : ( +
+
+

Einladung annehmen

+

Einladungslink oder Code eingeben um beizutreten

+ +
+
+ )} + +
+
+

Tagespartien

+

Spiele in deinem eigenen Tempo — Züge bis zu 3 Tage Zeit

+
+ Tagespartien +
+
+
+ +
+
+

Turnier

+

Spiele Round-Robin Turniere gegen mehrere Gegner

+
+ Turniere +
+
+
+ +
+
+ ); +} diff --git a/client/src/components/home/RecentGames.tsx b/client/src/components/home/RecentGames.tsx new file mode 100644 index 0000000..2b51ae6 --- /dev/null +++ b/client/src/components/home/RecentGames.tsx @@ -0,0 +1,82 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { Chessboard } from "react-chessboard"; +import { Chess } from "chess.js"; +import Link from "next/link"; +import { API_URL } from "@/config"; +import type { Game } from "@michess/types"; + +function getFen(pgn?: string): string { + if (!pgn) return "start"; + try { + const c = new Chess(); + c.loadPgn(pgn); + return c.fen(); + } catch { + return "start"; + } +} + +const BOARD_SIZE = 160; + +export default function RecentGames({ userId }: { userId: number }) { + const [games, setGames] = useState([]); + + useEffect(() => { + fetch(`${API_URL}/v1/games?userid=${userId}`, { cache: "no-store" }) + .then((r) => (r.ok ? r.json() : [])) + .then((data: Game[] | Game) => { + if (Array.isArray(data)) setGames(data.slice(0, 3)); + }) + .catch(() => {}); + }, [userId]); + + if (!games.length) return null; + + return ( +
+

Letzte Spiele

+
+ {games.map((game) => { + const fen = getFen(game.pgn); + const myColor = game.white?.id === userId ? "white" : "black"; + const opponent = myColor === "white" ? game.black?.name : game.white?.name; + const won = game.winner === myColor; + const drew = game.winner === "draw"; + + return ( + +
+ false} + customDarkSquareStyle={{ backgroundColor: "#4b7399" }} + customLightSquareStyle={{ backgroundColor: "#eae9d2" }} + areArrowsAllowed={false} + /> +
+
+
vs {opponent ?? "?"}
+
+ {won ? "Gewonnen" : drew ? "Remis" : "Verloren"} +
+
+ + ); + })} +
+
+ ); +}