feat : add board interactions
This commit is contained in:
14
src/sections/analysis/reviewPanelToolbar/flipBoardButton.tsx
Normal file
14
src/sections/analysis/reviewPanelToolbar/flipBoardButton.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { useSetAtom } from "jotai";
|
||||
import { boardOrientationAtom } from "../states";
|
||||
import { IconButton } from "@mui/material";
|
||||
import { Icon } from "@iconify/react";
|
||||
|
||||
export default function FlipBoardButton() {
|
||||
const setBoardOrientation = useSetAtom(boardOrientationAtom);
|
||||
|
||||
return (
|
||||
<IconButton onClick={() => setBoardOrientation((prev) => !prev)}>
|
||||
<Icon icon="eva:flip-fill" />
|
||||
</IconButton>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Icon } from "@iconify/react";
|
||||
import { IconButton } from "@mui/material";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { boardAtom, gameAtom } from "../states";
|
||||
import { useChessActions } from "@/hooks/useChess";
|
||||
|
||||
export default function GoToLastPositionButton() {
|
||||
const boardActions = useChessActions(boardAtom);
|
||||
const game = useAtomValue(gameAtom);
|
||||
const board = useAtomValue(boardAtom);
|
||||
|
||||
const gameHistory = game.history();
|
||||
const boardHistory = board.history();
|
||||
|
||||
const isButtonDisabled = boardHistory >= gameHistory;
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
if (isButtonDisabled) return;
|
||||
boardActions.setPgn(game.pgn());
|
||||
}}
|
||||
disabled={isButtonDisabled}
|
||||
>
|
||||
<Icon icon="ri:skip-forward-line" />
|
||||
</IconButton>
|
||||
);
|
||||
}
|
||||
46
src/sections/analysis/reviewPanelToolbar/index.tsx
Normal file
46
src/sections/analysis/reviewPanelToolbar/index.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import { Divider, Grid, IconButton } from "@mui/material";
|
||||
import { Icon } from "@iconify/react";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { boardAtom } from "../states";
|
||||
import { useChessActions } from "@/hooks/useChess";
|
||||
import FlipBoardButton from "./flipBoardButton";
|
||||
import NextMoveButton from "./nextMoveButton";
|
||||
import GoToLastPositionButton from "./goToLastPositionButton";
|
||||
import SaveButton from "./saveButton";
|
||||
|
||||
export default function ReviewPanelToolBar() {
|
||||
const board = useAtomValue(boardAtom);
|
||||
const boardActions = useChessActions(boardAtom);
|
||||
|
||||
const boardHistory = board.history();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Divider sx={{ width: "90%", marginY: 3 }} />
|
||||
|
||||
<Grid container item justifyContent="center" alignItems="center" xs={12}>
|
||||
<FlipBoardButton />
|
||||
|
||||
<IconButton
|
||||
onClick={() => boardActions.reset()}
|
||||
disabled={boardHistory.length === 0}
|
||||
>
|
||||
<Icon icon="ri:skip-back-line" />
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
onClick={() => boardActions.undo()}
|
||||
disabled={boardHistory.length === 0}
|
||||
>
|
||||
<Icon icon="ri:arrow-left-s-line" height={30} />
|
||||
</IconButton>
|
||||
|
||||
<NextMoveButton />
|
||||
|
||||
<GoToLastPositionButton />
|
||||
|
||||
<SaveButton />
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
}
|
||||
42
src/sections/analysis/reviewPanelToolbar/nextMoveButton.tsx
Normal file
42
src/sections/analysis/reviewPanelToolbar/nextMoveButton.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Icon } from "@iconify/react";
|
||||
import { IconButton } from "@mui/material";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { boardAtom, gameAtom } from "../states";
|
||||
import { useChessActions } from "@/hooks/useChess";
|
||||
|
||||
export default function NextMoveButton() {
|
||||
const boardActions = useChessActions(boardAtom);
|
||||
const game = useAtomValue(gameAtom);
|
||||
const board = useAtomValue(boardAtom);
|
||||
|
||||
const gameHistory = game.history();
|
||||
const boardHistory = board.history();
|
||||
|
||||
const isButtonEnabled =
|
||||
boardHistory.length < gameHistory.length &&
|
||||
gameHistory.slice(0, boardHistory.length).join() === boardHistory.join();
|
||||
|
||||
const addNextGameMoveToBoard = () => {
|
||||
if (!isButtonEnabled) return;
|
||||
|
||||
const nextMoveIndex = boardHistory.length;
|
||||
const nextMove = game.history({ verbose: true })[nextMoveIndex];
|
||||
|
||||
if (nextMove) {
|
||||
boardActions.move({
|
||||
from: nextMove.from,
|
||||
to: nextMove.to,
|
||||
promotion: nextMove.promotion,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
onClick={() => addNextGameMoveToBoard()}
|
||||
disabled={!isButtonEnabled}
|
||||
>
|
||||
<Icon icon="ri:arrow-right-s-line" height={30} />
|
||||
</IconButton>
|
||||
);
|
||||
}
|
||||
36
src/sections/analysis/reviewPanelToolbar/saveButton.tsx
Normal file
36
src/sections/analysis/reviewPanelToolbar/saveButton.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { useGameDatabase } from "@/hooks/useGameDatabase";
|
||||
import { Icon } from "@iconify/react";
|
||||
import { IconButton } from "@mui/material";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useRouter } from "next/router";
|
||||
import { gameAtom } from "../states";
|
||||
|
||||
export default function SaveButton() {
|
||||
const game = useAtomValue(gameAtom);
|
||||
const { addGame } = useGameDatabase();
|
||||
|
||||
const router = useRouter();
|
||||
const { gameId } = router.query;
|
||||
|
||||
const isButtonEnabled = router.isReady && typeof gameId === undefined;
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
onClick={async () => {
|
||||
if (!isButtonEnabled) return;
|
||||
const gameId = await addGame(game);
|
||||
router.replace(
|
||||
{
|
||||
query: { gameId: gameId },
|
||||
pathname: router.pathname,
|
||||
},
|
||||
undefined,
|
||||
{ shallow: true, scroll: false }
|
||||
);
|
||||
}}
|
||||
disabled={!isButtonEnabled}
|
||||
>
|
||||
<Icon icon="ri:save-3-line" />
|
||||
</IconButton>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user