fix: add error handling for making moves

This commit is contained in:
Cozma Rares
2023-07-30 15:25:44 +03:00
parent 7088f89065
commit ce09e99c28
6 changed files with 86 additions and 61 deletions
+4 -3
View File
@@ -40,7 +40,7 @@ const ChessBoard: React.FC<{
chess: Chess;
makeMove: (move: Move) => void;
blackPerspective?: boolean;
disabled: boolean;
disabled?: boolean;
}> = ({ chess, makeMove, blackPerspective, disabled }) => {
const { width, height } = useWindowSize();
const [activeTile, setActiveTile] = useState<number>(-1);
@@ -92,12 +92,13 @@ const ChessBoard: React.FC<{
makeMove(moveObj);
setActiveTile(-1);
return;
}
if (tileProps[tile].piece == null) return setActiveTile(-1);
if (tile == activeTile) setActiveTile(-1);
else setActiveTile(tile);
console.log({ tile: algebraic(tile), activeTile: algebraic(activeTile) });
setActiveTile(tile == activeTile ? -1 : tile);
};
const sendPromotionMove = (promotion: PiecePromotionType) => {
+12 -6
View File
@@ -7,6 +7,7 @@ import useCopyToClipboard from "../utils/useCopyToClipboard";
import { socket } from "../sockets/socket";
import { CopyIcon } from "../utils/icons";
import Show from "../utils/Show";
import ErrorNorification from "../utils/ErrorNotification";
const Game = () => {
const navigate = useNavigate();
@@ -18,12 +19,9 @@ const Game = () => {
const [chess] = useState(Chess.load());
const [game, setGame] = useState(false);
const [, setRerender] = useState(false);
const [err, setErr] = useState<Error>();
const makeMove = (move: Move) => {
socket.emit("make move", id, move);
chess.makeMove(move);
setRerender((prev) => !prev);
};
const makeMove = (move: Move) => socket.emit("make move", id, move);
useEffect(() => {
console.log({ id, color });
@@ -51,6 +49,10 @@ const Game = () => {
});
});
socket.on("move error", (message: string) => {
setErr(new Error(message));
});
socket.on("start game", () => setGame(true));
socket.on("receive move", (move: Move) => {
@@ -65,12 +67,16 @@ const Game = () => {
return (
<Show when={game} fallback={<Waiting id={id} />}>
<ErrorNorification
error={err?.message}
removeError={() => setErr(undefined)}
/>
<ChessBoard
key={chess.getFEN()}
chess={chess}
makeMove={makeMove}
blackPerspective={color === COLOR.BLACK}
disabled={color != chess.getTurn()}
disabled={color !== chess.getTurn()}
/>
</Show>
);
+3 -50
View File
@@ -1,8 +1,8 @@
import { useEffect, useRef, useState } from "react";
import { useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { Color, COLOR } from "../../../server/src/engine";
import Show from "../utils/Show";
import { CircleExclamation } from "../utils/icons";
import ErrorNorification from "../utils/ErrorNotification";
const Home = () => {
const navigate = useNavigate();
@@ -66,10 +66,7 @@ const Home = () => {
return (
<>
<Err
key={errObj.error}
{...errObj}
/>
<ErrorNorification key={errObj.error} {...errObj} />
<div className="text-xl">
<div className="absolute top-0 left-0 right-0 bottom-0 m-auto p-6 bg-gray-800 text-white w-fit h-fit rounded-[25px]">
<button
@@ -148,48 +145,4 @@ const Home = () => {
);
};
const Err: React.FC<{
error?: string;
removeError: () => void;
}> = ({ error, removeError }) => {
const [err, setErr] = useState(error);
const divRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
const id = setTimeout(() => {
let duration = 1;
if (divRef.current != null) {
divRef.current.classList.add(
"opacity-0",
"transition-opacity",
"duration-300"
);
duration = 300;
}
setTimeout(() => {
removeError();
setErr(undefined);
console.log("Removed error");
}, duration);
}, 2 * 1000);
return () => clearTimeout(id);
}, []);
return (
<Show when={err != undefined}>
<div
ref={divRef}
className="flex justify-center items-center gap-1 w-fit mt-2 mr-4 ml-auto border border-black p-2 rounded-md text-lg"
>
<span className="text-red-700">
<CircleExclamation />
</span>
{err}
</div>
</Show>
);
};
export default Home;
+51
View File
@@ -0,0 +1,51 @@
import { useEffect, useRef, useState } from "react";
import Show from "./Show";
import { CircleExclamation } from "./icons";
const ErrorNorification: React.FC<{
error?: string;
removeError: () => void;
}> = ({ error, removeError }) => {
const [err, setErr] = useState(error);
const divRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
const id = setTimeout(() => {
if (err == undefined) return;
let duration = 1;
if (divRef.current != null) {
divRef.current.classList.add(
"opacity-0",
"transition-opacity",
"duration-300"
);
duration = 300;
}
setTimeout(() => {
removeError();
setErr(undefined);
console.log("Removed error");
}, duration);
}, 2 * 1000);
return () => clearTimeout(id);
}, []);
return (
<Show when={err != undefined}>
<div
ref={divRef}
className="absolute top-0 right-0 flex justify-center items-center gap-1 w-fit mt-2 mr-4 border border-black p-2 rounded-md text-lg"
>
<span className="text-red-700">
<CircleExclamation />
</span>
{err}
</div>
</Show>
);
};
export default ErrorNorification;
+1 -1
View File
@@ -821,7 +821,7 @@ export default class Chess {
}
if (moveObj == null)
throw new Error(`Move ${JSON.stringify(move)} not found`);
throw new Error("Move not found");
this._makeMove(moveObj);
}
+15 -1
View File
@@ -68,7 +68,21 @@ io.on("connection", (socket) => {
});
socket.on("make move", (id: string, move: Move) => {
socket.to(id).emit("receive move", move);
const room = rooms.get(id);
if (room == undefined) return socket.emit("move error", "Invalid game ID");
const chess = room.game;
if (socket.id != room[chess.getTurn()])
return socket.emit("move error", "Not your turn!");
try {
chess.makeMove(move);
io.to(id).emit("receive move", move);
} catch (e) {
socket.emit("move error", (e as Error).message);
}
});
});