style : analysis card UI rework adjustments
This commit is contained in:
@@ -54,7 +54,7 @@ export default function PrettyMoveSan({
|
|||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Typography component="span" {...typographyProps}>
|
<Typography component="span" noWrap {...typographyProps}>
|
||||||
{text}
|
{text}
|
||||||
{additionalText}
|
{additionalText}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export default function GameAnalysis() {
|
|||||||
const { reset: resetGame } = useChessActions(gameAtom);
|
const { reset: resetGame } = useChessActions(gameAtom);
|
||||||
const [gameEval, setGameEval] = useAtom(gameEvalAtom);
|
const [gameEval, setGameEval] = useAtom(gameEvalAtom);
|
||||||
const game = useAtomValue(gameAtom);
|
const game = useAtomValue(gameAtom);
|
||||||
|
const board = useAtomValue(boardAtom);
|
||||||
const setBoardOrientation = useSetAtom(boardOrientationAtom);
|
const setBoardOrientation = useSetAtom(boardOrientationAtom);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -50,12 +51,12 @@ export default function GameAnalysis() {
|
|||||||
}
|
}
|
||||||
}, [gameId, setGameEval, setBoardOrientation, resetBoard, resetGame]);
|
}, [gameId, setGameEval, setBoardOrientation, resetBoard, resetGame]);
|
||||||
|
|
||||||
const isGameLoaded = game.history().length > 0;
|
const showMovesTab = game.history().length > 0 || board.history().length > 0;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (tab === 1 && !isGameLoaded) setTab(0);
|
if (tab === 1 && !showMovesTab) setTab(0);
|
||||||
if (tab === 2 && !gameEval) setTab(0);
|
if (tab === 2 && !gameEval) setTab(0);
|
||||||
}, [isGameLoaded, gameEval, tab]);
|
}, [showMovesTab, gameEval, tab]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid container gap={4} justifyContent="space-evenly" alignItems="start">
|
<Grid container gap={4} justifyContent="space-evenly" alignItems="start">
|
||||||
@@ -65,7 +66,7 @@ export default function GameAnalysis() {
|
|||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
justifyContent="center"
|
justifyContent="start"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
borderRadius={2}
|
borderRadius={2}
|
||||||
border={1}
|
border={1}
|
||||||
@@ -81,26 +82,24 @@ export default function GameAnalysis() {
|
|||||||
maxWidth: "1200px",
|
maxWidth: "1200px",
|
||||||
}}
|
}}
|
||||||
rowGap={2}
|
rowGap={2}
|
||||||
maxHeight={{ lg: "calc(95vh - 60px)", xs: "900px" }}
|
height={{ xs: tab === 1 ? "40rem" : "auto", lg: "calc(95vh - 60px)" }}
|
||||||
display="grid"
|
display="flex"
|
||||||
gridTemplateRows={
|
flexDirection="column"
|
||||||
gameEval
|
flexWrap="nowrap"
|
||||||
? "repeat(2, auto) max-content fit-content(100%) fit-content(100%) auto"
|
|
||||||
: "repeat(2, auto) max-content fit-content(100%)"
|
|
||||||
}
|
|
||||||
size={{
|
size={{
|
||||||
xs: 12,
|
xs: 12,
|
||||||
lg: "grow",
|
lg: "grow",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isLgOrGreater ? (
|
{isLgOrGreater ? (
|
||||||
|
<Box width="100%">
|
||||||
<PanelHeader key="analysis-panel-header" />
|
<PanelHeader key="analysis-panel-header" />
|
||||||
|
<Divider sx={{ marginX: "5%", marginTop: 2.5 }} />
|
||||||
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<PanelToolBar key="review-panel-toolbar" />
|
<PanelToolBar key="review-panel-toolbar" />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isLgOrGreater && <Divider sx={{ marginX: "5%" }} />}
|
|
||||||
|
|
||||||
{!isLgOrGreater && !gameEval && <Divider sx={{ marginX: "5%" }} />}
|
{!isLgOrGreater && !gameEval && <Divider sx={{ marginX: "5%" }} />}
|
||||||
{!isLgOrGreater && !gameEval && (
|
{!isLgOrGreater && !gameEval && (
|
||||||
<PanelHeader key="analysis-panel-header" />
|
<PanelHeader key="analysis-panel-header" />
|
||||||
@@ -108,6 +107,7 @@ export default function GameAnalysis() {
|
|||||||
|
|
||||||
{!isLgOrGreater && (
|
{!isLgOrGreater && (
|
||||||
<Box
|
<Box
|
||||||
|
width="95%"
|
||||||
sx={{
|
sx={{
|
||||||
borderBottom: 1,
|
borderBottom: 1,
|
||||||
borderColor: "divider",
|
borderColor: "divider",
|
||||||
@@ -142,7 +142,7 @@ export default function GameAnalysis() {
|
|||||||
sx={{
|
sx={{
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
minHeight: 15,
|
minHeight: 15,
|
||||||
display: isGameLoaded ? undefined : "none",
|
display: showMovesTab ? undefined : "none",
|
||||||
padding: "5px 0em 12px",
|
padding: "5px 0em 12px",
|
||||||
}}
|
}}
|
||||||
disableFocusRipple
|
disableFocusRipple
|
||||||
@@ -177,24 +177,24 @@ export default function GameAnalysis() {
|
|||||||
id="tabContent0"
|
id="tabContent0"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{isGameLoaded && (
|
|
||||||
<ClassificationTab
|
<ClassificationTab
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
hidden={tab !== 1 && !isLgOrGreater}
|
hidden={tab !== 1 && !isLgOrGreater}
|
||||||
id="tabContent1"
|
id="tabContent1"
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
|
|
||||||
{isLgOrGreater && (
|
{isLgOrGreater && (
|
||||||
<Box>
|
<Box width="100%">
|
||||||
<Divider sx={{ marginX: "5%", marginBottom: 1.5 }} />
|
<Divider sx={{ marginX: "5%", marginBottom: 1.5 }} />
|
||||||
<PanelToolBar key="review-panel-toolbar" />
|
<PanelToolBar key="review-panel-toolbar" />
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isLgOrGreater && gameEval && <Divider sx={{ marginX: "5%" }} />}
|
|
||||||
{!isLgOrGreater && gameEval && (
|
{!isLgOrGreater && gameEval && (
|
||||||
|
<Box width="100%">
|
||||||
|
<Divider sx={{ marginX: "5%", marginBottom: 2.5 }} />
|
||||||
<PanelHeader key="analysis-panel-header" />
|
<PanelHeader key="analysis-panel-header" />
|
||||||
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default function BoardContainer() {
|
|||||||
|
|
||||||
// 1200 is the lg layout breakpoint
|
// 1200 is the lg layout breakpoint
|
||||||
if (window?.innerWidth < 1200) {
|
if (window?.innerWidth < 1200) {
|
||||||
return Math.min(width, height - 150);
|
return Math.min(width - 15, height - 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.min(width - 700, height * 0.92);
|
return Math.min(width - 700, height * 0.92);
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { Grid2 as Grid, Grid2Props as GridProps, List } from "@mui/material";
|
||||||
|
import LineEvaluation from "./lineEvaluation";
|
||||||
|
import {
|
||||||
|
boardAtom,
|
||||||
|
currentPositionAtom,
|
||||||
|
engineMultiPvAtom,
|
||||||
|
} from "../../../states";
|
||||||
|
import { useAtomValue } from "jotai";
|
||||||
|
import { LineEval } from "@/types/eval";
|
||||||
|
|
||||||
|
export default function EngineLines(props: GridProps) {
|
||||||
|
const board = useAtomValue(boardAtom);
|
||||||
|
const linesNumber = useAtomValue(engineMultiPvAtom);
|
||||||
|
const position = useAtomValue(currentPositionAtom);
|
||||||
|
|
||||||
|
const linesSkeleton: LineEval[] = Array.from({ length: linesNumber }).map(
|
||||||
|
(_, i) => ({ pv: [`${i}`], depth: 0, multiPv: i + 1 })
|
||||||
|
);
|
||||||
|
|
||||||
|
const engineLines = position?.eval?.lines?.length
|
||||||
|
? position.eval.lines
|
||||||
|
: linesSkeleton;
|
||||||
|
|
||||||
|
if (board.isCheckmate()) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid container justifyContent="center" alignItems="center" {...props}>
|
||||||
|
<List sx={{ width: "95%", padding: 0 }}>
|
||||||
|
{engineLines.map((line) => (
|
||||||
|
<LineEvaluation key={line.multiPv} line={line} />
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { LineEval } from "@/types/eval";
|
import { LineEval } from "@/types/eval";
|
||||||
import { ListItem, Skeleton, Typography } from "@mui/material";
|
import { ListItem, Skeleton, Typography } from "@mui/material";
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { boardAtom } from "../../states";
|
import { boardAtom } from "../../../states";
|
||||||
import { getLineEvalLabel, moveLineUciToSan } from "@/lib/chess";
|
import { getLineEvalLabel, moveLineUciToSan } from "@/lib/chess";
|
||||||
import { useChessActions } from "@/hooks/useChessActions";
|
import { useChessActions } from "@/hooks/useChessActions";
|
||||||
import PrettyMoveSan from "@/components/prettyMoveSan";
|
import PrettyMoveSan from "@/components/prettyMoveSan";
|
||||||
@@ -1,45 +1,47 @@
|
|||||||
import { Grid2 as Grid, Grid2Props as GridProps, List } from "@mui/material";
|
|
||||||
import { useAtomValue } from "jotai";
|
|
||||||
import {
|
import {
|
||||||
boardAtom,
|
Grid2 as Grid,
|
||||||
currentPositionAtom,
|
Grid2Props as GridProps,
|
||||||
engineMultiPvAtom,
|
Stack,
|
||||||
gameEvalAtom,
|
Typography,
|
||||||
} from "../../states";
|
} from "@mui/material";
|
||||||
import LineEvaluation from "./lineEvaluation";
|
import { useAtomValue } from "jotai";
|
||||||
import { LineEval } from "@/types/eval";
|
import { boardAtom, gameAtom, gameEvalAtom } from "../../states";
|
||||||
import PlayersMetric from "./playersMetric";
|
import PlayersMetric from "./playersMetric";
|
||||||
import MoveInfo from "./moveInfo";
|
import MoveInfo from "./moveInfo";
|
||||||
import Opening from "./opening";
|
import Opening from "./opening";
|
||||||
|
import EngineLines from "./engineLines";
|
||||||
|
|
||||||
export default function AnalysisTab(props: GridProps) {
|
export default function AnalysisTab(props: GridProps) {
|
||||||
const linesNumber = useAtomValue(engineMultiPvAtom);
|
|
||||||
const position = useAtomValue(currentPositionAtom);
|
|
||||||
const board = useAtomValue(boardAtom);
|
|
||||||
const gameEval = useAtomValue(gameEvalAtom);
|
const gameEval = useAtomValue(gameEvalAtom);
|
||||||
|
const game = useAtomValue(gameAtom);
|
||||||
|
const board = useAtomValue(boardAtom);
|
||||||
|
|
||||||
const linesSkeleton: LineEval[] = Array.from({ length: linesNumber }).map(
|
const boardHistory = board.history();
|
||||||
(_, i) => ({ pv: [`${i}`], depth: 0, multiPv: i + 1 })
|
const gameHistory = game.history();
|
||||||
);
|
|
||||||
|
|
||||||
const engineLines = position?.eval?.lines?.length
|
const isGameOver =
|
||||||
? position.eval.lines
|
boardHistory.length > 0 &&
|
||||||
: linesSkeleton;
|
(board.isCheckmate() ||
|
||||||
|
board.isDraw() ||
|
||||||
|
boardHistory.join() === gameHistory.join());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
size={12}
|
size={{ xs: 12, lg: gameEval ? 11 : 12 }}
|
||||||
justifyContent="center"
|
justifyContent={{ xs: "center", lg: gameEval ? "start" : "center" }}
|
||||||
alignItems="start"
|
alignItems="center"
|
||||||
height="100%"
|
flexWrap={{ lg: gameEval ? "nowrap" : undefined }}
|
||||||
rowGap={0.8}
|
gap={2}
|
||||||
|
marginY={{ lg: gameEval ? 1 : undefined }}
|
||||||
{...props}
|
{...props}
|
||||||
sx={
|
sx={props.hidden ? { display: "none" } : props.sx}
|
||||||
props.hidden
|
>
|
||||||
? { display: "none" }
|
<Stack
|
||||||
: { overflow: "hidden", overflowY: "auto", ...props.sx }
|
justifyContent="center"
|
||||||
}
|
alignItems="center"
|
||||||
|
rowGap={1}
|
||||||
|
minWidth={gameEval ? "min(25rem, 95vw)" : undefined}
|
||||||
>
|
>
|
||||||
{gameEval && (
|
{gameEval && (
|
||||||
<PlayersMetric
|
<PlayersMetric
|
||||||
@@ -61,14 +63,14 @@ export default function AnalysisTab(props: GridProps) {
|
|||||||
|
|
||||||
<Opening />
|
<Opening />
|
||||||
|
|
||||||
<Grid container justifyContent="center" alignItems="center" size={12}>
|
{isGameOver && (
|
||||||
<List sx={{ width: { xs: "95%", lg: "90%" }, padding: 0 }}>
|
<Typography align="center" fontSize="0.9rem" noWrap>
|
||||||
{!board.isCheckmate() &&
|
Game is over
|
||||||
engineLines.map((line) => (
|
</Typography>
|
||||||
<LineEvaluation key={line.multiPv} line={line} />
|
)}
|
||||||
))}
|
</Stack>
|
||||||
</List>
|
|
||||||
</Grid>
|
<EngineLines size={{ lg: gameEval ? undefined : 12 }} />
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Grid2 as Grid, Skeleton, Stack, Typography } from "@mui/material";
|
import { Skeleton, Stack, Typography } from "@mui/material";
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { boardAtom, currentPositionAtom, gameAtom } from "../../states";
|
import { boardAtom, currentPositionAtom } from "../../states";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { moveLineUciToSan } from "@/lib/chess";
|
import { moveLineUciToSan } from "@/lib/chess";
|
||||||
import { MoveClassification } from "@/types/enums";
|
import { MoveClassification } from "@/types/enums";
|
||||||
@@ -10,7 +10,6 @@ import PrettyMoveSan from "@/components/prettyMoveSan";
|
|||||||
export default function MoveInfo() {
|
export default function MoveInfo() {
|
||||||
const position = useAtomValue(currentPositionAtom);
|
const position = useAtomValue(currentPositionAtom);
|
||||||
const board = useAtomValue(boardAtom);
|
const board = useAtomValue(boardAtom);
|
||||||
const game = useAtomValue(gameAtom);
|
|
||||||
|
|
||||||
const bestMove = position?.lastEval?.bestMove;
|
const bestMove = position?.lastEval?.bestMove;
|
||||||
|
|
||||||
@@ -23,36 +22,22 @@ export default function MoveInfo() {
|
|||||||
return moveLineUciToSan(lastPosition)(bestMove);
|
return moveLineUciToSan(lastPosition)(bestMove);
|
||||||
}, [bestMove, board]);
|
}, [bestMove, board]);
|
||||||
|
|
||||||
const boardHistory = board.history();
|
|
||||||
const gameHistory = game.history();
|
|
||||||
|
|
||||||
if (board.history().length === 0) return null;
|
if (board.history().length === 0) return null;
|
||||||
|
|
||||||
const isGameOver =
|
|
||||||
boardHistory.length > 0 &&
|
|
||||||
(board.isCheckmate() ||
|
|
||||||
board.isDraw() ||
|
|
||||||
boardHistory.join() === gameHistory.join());
|
|
||||||
|
|
||||||
if (!bestMoveSan) {
|
if (!bestMoveSan) {
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Stack direction="row" alignItems="center" columnGap={5} marginTop={0.8}>
|
||||||
size={12}
|
|
||||||
justifyItems="center"
|
|
||||||
alignContent="center"
|
|
||||||
marginTop={0.5}
|
|
||||||
>
|
|
||||||
<Skeleton
|
<Skeleton
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
animation="wave"
|
animation="wave"
|
||||||
width={"12em"}
|
width={"12em"}
|
||||||
sx={{ color: "transparent", maxWidth: "7vw", maxHeight: "3.5vw" }}
|
sx={{ color: "transparent", maxWidth: "7vw" }}
|
||||||
>
|
>
|
||||||
<Typography align="center" fontSize="0.9rem">
|
<Typography align="center" fontSize="0.9rem">
|
||||||
placeholder
|
placeholder
|
||||||
</Typography>
|
</Typography>
|
||||||
</Skeleton>
|
</Skeleton>
|
||||||
</Grid>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,12 +51,13 @@ export default function MoveInfo() {
|
|||||||
moveClassification !== MoveClassification.Perfect;
|
moveClassification !== MoveClassification.Perfect;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Stack
|
||||||
container
|
direction="row"
|
||||||
columnGap={5}
|
alignItems="center"
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
size={12}
|
columnGap={4}
|
||||||
marginTop={0.5}
|
marginTop={0.5}
|
||||||
|
flexWrap="wrap"
|
||||||
>
|
>
|
||||||
{moveClassification && (
|
{moveClassification && (
|
||||||
<Stack direction="row" alignItems="center" spacing={1}>
|
<Stack direction="row" alignItems="center" spacing={1}>
|
||||||
@@ -121,13 +107,7 @@ export default function MoveInfo() {
|
|||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
</Stack>
|
||||||
{isGameOver && (
|
|
||||||
<Typography align="center" fontSize="0.9rem">
|
|
||||||
Game is over
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Grid>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default function Opening() {
|
|||||||
|
|
||||||
if (!opening) {
|
if (!opening) {
|
||||||
return (
|
return (
|
||||||
<Grid size={12} justifyItems="center" alignContent="center">
|
<Grid justifyItems="center" alignContent="center">
|
||||||
<Skeleton
|
<Skeleton
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
animation="wave"
|
animation="wave"
|
||||||
@@ -28,7 +28,7 @@ export default function Opening() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid size={12}>
|
<Grid>
|
||||||
<Typography align="center" fontSize="0.9rem">
|
<Typography align="center" fontSize="0.9rem">
|
||||||
{opening}
|
{opening}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Grid2 as Grid, Typography } from "@mui/material";
|
import { Stack, Typography } from "@mui/material";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -12,21 +12,20 @@ export default function PlayersMetric({
|
|||||||
blackValue,
|
blackValue,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Stack
|
||||||
container
|
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
|
flexDirection="row"
|
||||||
columnGap={{ xs: "8vw", md: 10 }}
|
columnGap={{ xs: "8vw", md: 10 }}
|
||||||
size={12}
|
|
||||||
>
|
>
|
||||||
<ValueBlock value={whiteValue} color="white" />
|
<ValueBlock value={whiteValue} color="white" />
|
||||||
|
|
||||||
<Typography align="center" fontSize="0.8em">
|
<Typography align="center" fontSize="0.8em" noWrap>
|
||||||
{title}
|
{title}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<ValueBlock value={blackValue} color="black" />
|
<ValueBlock value={blackValue} color="black" />
|
||||||
</Grid>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,6 +49,7 @@ const ValueBlock = ({
|
|||||||
padding={0.8}
|
padding={0.8}
|
||||||
fontWeight="500"
|
fontWeight="500"
|
||||||
border="1px solid #424242"
|
border="1px solid #424242"
|
||||||
|
noWrap
|
||||||
>
|
>
|
||||||
{value}
|
{value}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default function ClassificationTab(props: GridProps) {
|
|||||||
container
|
container
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
alignItems="start"
|
alignItems="start"
|
||||||
height="100%"
|
size={12}
|
||||||
maxHeight={{ xs: "18rem", lg: "none" }}
|
flexGrow={1}
|
||||||
{...props}
|
{...props}
|
||||||
sx={
|
sx={
|
||||||
props.hidden ? { display: "none" } : { overflow: "hidden", ...props.sx }
|
props.hidden ? { display: "none" } : { overflow: "hidden", ...props.sx }
|
||||||
|
|||||||
@@ -2,15 +2,19 @@ import { Grid2 as Grid } from "@mui/material";
|
|||||||
import MovesLine from "./movesLine";
|
import MovesLine from "./movesLine";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { gameAtom, gameEvalAtom } from "../../../states";
|
import { boardAtom, gameAtom, gameEvalAtom } from "../../../states";
|
||||||
import { MoveClassification } from "@/types/enums";
|
import { MoveClassification } from "@/types/enums";
|
||||||
|
|
||||||
export default function MovesPanel() {
|
export default function MovesPanel() {
|
||||||
const game = useAtomValue(gameAtom);
|
const game = useAtomValue(gameAtom);
|
||||||
|
const board = useAtomValue(boardAtom);
|
||||||
const gameEval = useAtomValue(gameEvalAtom);
|
const gameEval = useAtomValue(gameEvalAtom);
|
||||||
|
|
||||||
const gameMoves = useMemo(() => {
|
const gameMoves = useMemo(() => {
|
||||||
const history = game.history();
|
const gameHistory = game.history();
|
||||||
|
const boardHistory = board.history();
|
||||||
|
const history = gameHistory.length ? gameHistory : boardHistory;
|
||||||
|
|
||||||
if (!history.length) return undefined;
|
if (!history.length) return undefined;
|
||||||
|
|
||||||
const moves: { san: string; moveClassification?: MoveClassification }[][] =
|
const moves: { san: string; moveClassification?: MoveClassification }[][] =
|
||||||
@@ -20,14 +24,18 @@ export default function MovesPanel() {
|
|||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
san: history[i],
|
san: history[i],
|
||||||
moveClassification: gameEval?.positions[i + 1]?.moveClassification,
|
moveClassification: gameHistory.length
|
||||||
|
? gameEval?.positions[i + 1]?.moveClassification
|
||||||
|
: undefined,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (history[i + 1]) {
|
if (history[i + 1]) {
|
||||||
items.push({
|
items.push({
|
||||||
san: history[i + 1],
|
san: history[i + 1],
|
||||||
moveClassification: gameEval?.positions[i + 2]?.moveClassification,
|
moveClassification: gameHistory.length
|
||||||
|
? gameEval?.positions[i + 2]?.moveClassification
|
||||||
|
: undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,17 +43,19 @@ export default function MovesPanel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return moves;
|
return moves;
|
||||||
}, [game, gameEval]);
|
}, [game, board, gameEval]);
|
||||||
|
|
||||||
|
if (!gameMoves?.length) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
alignItems="start"
|
alignItems="start"
|
||||||
gap={0.7}
|
gap={0.5}
|
||||||
paddingY={1}
|
paddingY={1}
|
||||||
sx={{ scrollbarWidth: "thin", overflowY: "auto" }}
|
sx={{ scrollbarWidth: "thin", overflowY: "auto" }}
|
||||||
height="100%"
|
maxHeight="100%"
|
||||||
size={6}
|
size={6}
|
||||||
id="moves-panel"
|
id="moves-panel"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export default function MoveItem({
|
|||||||
moveColor,
|
moveColor,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const game = useAtomValue(gameAtom);
|
const game = useAtomValue(gameAtom);
|
||||||
|
const board = useAtomValue(boardAtom);
|
||||||
const { goToMove } = useChessActions(boardAtom);
|
const { goToMove } = useChessActions(boardAtom);
|
||||||
const position = useAtomValue(currentPositionAtom);
|
const position = useAtomValue(currentPositionAtom);
|
||||||
const color = getMoveColor(moveClassification);
|
const color = getMoveColor(moveClassification);
|
||||||
@@ -42,7 +43,8 @@ export default function MoveItem({
|
|||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (isCurrentMove) return;
|
if (isCurrentMove) return;
|
||||||
goToMove(moveIdx, game);
|
const gameToUse = game.moveNumber() > 1 ? game : board;
|
||||||
|
goToMove(moveIdx, gameToUse);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -82,7 +84,11 @@ export default function MoveItem({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<PrettyMoveSan san={san} color={moveColor} />
|
<PrettyMoveSan
|
||||||
|
san={san}
|
||||||
|
color={moveColor}
|
||||||
|
typographyProps={{ fontSize: "0.9rem" }}
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,20 +87,17 @@ export default function GraphTab(props: GridProps) {
|
|||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
alignItems="start"
|
alignItems="center"
|
||||||
height="100%"
|
minHeight="min(10rem, 8vh)"
|
||||||
|
height={{ xs: "8rem", lg: "none" }}
|
||||||
|
maxHeight="10rem"
|
||||||
{...props}
|
{...props}
|
||||||
sx={
|
sx={props.hidden ? { display: "none" } : props.sx}
|
||||||
props.hidden
|
size={12}
|
||||||
? { display: "none" }
|
|
||||||
: { overflow: "hidden", overflowY: "auto", ...props.sx }
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
width="max(35rem, 90%)"
|
height="100%"
|
||||||
maxWidth="100%"
|
width={{ xs: "100%", lg: "90%" }}
|
||||||
height="min(8rem, 8vh)"
|
|
||||||
maxHeight="6rem"
|
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: "#2e2e2e",
|
backgroundColor: "#2e2e2e",
|
||||||
borderRadius: "15px",
|
borderRadius: "15px",
|
||||||
|
|||||||
Reference in New Issue
Block a user