feat : useScreenSize for board size
This commit is contained in:
@@ -2,18 +2,30 @@ import { useEffect, useState } from "react";
|
||||
|
||||
export const useScreenSize = () => {
|
||||
const [screenSize, setScreenSize] = useState({
|
||||
width: window?.innerWidth ?? 500,
|
||||
height: window?.innerHeight ?? 500,
|
||||
width: document?.querySelector(".MuiGrid-root")?.clientWidth ?? 500,
|
||||
height: window?.innerHeight - 120 ?? 500,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (window === undefined) return;
|
||||
const mainDiv = document?.querySelector(".MuiGrid-root");
|
||||
if (!mainDiv) return;
|
||||
|
||||
const observer = new ResizeObserver(() =>
|
||||
setScreenSize((prev) => ({ ...prev, width: mainDiv.clientWidth }))
|
||||
);
|
||||
observer.observe(mainDiv);
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
setScreenSize({
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
});
|
||||
setScreenSize((prev) => ({
|
||||
...prev,
|
||||
height: window.innerHeight - 120,
|
||||
}));
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
@@ -23,5 +35,17 @@ export const useScreenSize = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
return screenSize;
|
||||
const getBoardSize = () => {
|
||||
const width = screenSize.width;
|
||||
const height = screenSize.height;
|
||||
|
||||
// 900 is the md layout breakpoint
|
||||
if (width < 900) {
|
||||
return Math.min(width, height) * 0.95;
|
||||
}
|
||||
|
||||
return Math.min(width - 500, height) * 0.95;
|
||||
};
|
||||
|
||||
return { ...screenSize, boardSize: getBoardSize() };
|
||||
};
|
||||
|
||||
@@ -4,8 +4,6 @@ import "@fontsource/roboto/500.css";
|
||||
import "@fontsource/roboto/700.css";
|
||||
import { AppProps } from "next/app";
|
||||
import Head from "next/head";
|
||||
// import "../../styles/global.css";
|
||||
// import "../../styles/index.css";
|
||||
import Layout from "@/sections/layout";
|
||||
|
||||
export default function MyApp({ Component, pageProps }: AppProps) {
|
||||
|
||||
@@ -152,10 +152,8 @@ export default function GameDatabase() {
|
||||
marginTop={6}
|
||||
>
|
||||
<Grid item container xs={12} justifyContent="center" alignItems="center">
|
||||
<Grid item container justifyContent="center" sx={{ maxWidth: "250px" }}>
|
||||
<LoadGameButton />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid item container xs={12} justifyContent="center" alignItems="center">
|
||||
<Typography variant="subtitle2">
|
||||
|
||||
@@ -38,7 +38,7 @@ export default function GameReport() {
|
||||
rowGap={6}
|
||||
justifyContent="center"
|
||||
alignItems="start"
|
||||
marginTop={1}
|
||||
gap={6}
|
||||
>
|
||||
<Grid
|
||||
item
|
||||
@@ -46,8 +46,7 @@ export default function GameReport() {
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
xs={12}
|
||||
md={9}
|
||||
lg={6}
|
||||
md
|
||||
>
|
||||
<Board />
|
||||
</Grid>
|
||||
@@ -55,11 +54,11 @@ export default function GameReport() {
|
||||
<Grid
|
||||
item
|
||||
container
|
||||
paddingLeft={{ xs: 0, lg: 6 }}
|
||||
marginTop={{ xs: 0, md: "2.5em" }}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
xs={12}
|
||||
lg={6}
|
||||
md
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
@@ -76,7 +75,7 @@ export default function GameReport() {
|
||||
borderWidth: 2,
|
||||
}}
|
||||
padding={3}
|
||||
gap={4}
|
||||
gap={3}
|
||||
>
|
||||
<ReviewPanelHeader />
|
||||
|
||||
|
||||
@@ -13,9 +13,11 @@ import { useChessActions } from "@/hooks/useChess";
|
||||
import { useMemo, useRef } from "react";
|
||||
import PlayerInfo from "./playerInfo";
|
||||
import EvaluationBar from "./evaluationBar";
|
||||
import { useScreenSize } from "@/hooks/useScreenSize";
|
||||
|
||||
export default function Board() {
|
||||
const boardRef = useRef<HTMLDivElement>(null);
|
||||
const { boardSize } = useScreenSize();
|
||||
const board = useAtomValue(boardAtom);
|
||||
const boardOrientation = useAtomValue(boardOrientationAtom);
|
||||
const showBestMoveArrow = useAtomValue(showBestMoveArrowAtom);
|
||||
@@ -76,10 +78,10 @@ export default function Board() {
|
||||
container
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
xs={12}
|
||||
wrap="nowrap"
|
||||
width={boardSize}
|
||||
>
|
||||
<EvaluationBar height={boardRef?.current?.offsetHeight || 800} />
|
||||
<EvaluationBar height={boardRef?.current?.offsetHeight || boardSize} />
|
||||
|
||||
<Grid
|
||||
item
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function PlayerInfo({ color }: Props) {
|
||||
|
||||
return (
|
||||
<Grid item container xs={12} justifyContent="center" alignItems="center">
|
||||
<Typography variant="h5">
|
||||
<Typography variant="h6">
|
||||
{playerName || (color === "white" ? "White" : "Black")}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
@@ -35,7 +35,7 @@ export default function ReviewPanelBody() {
|
||||
xs={12}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
gap={1}
|
||||
>
|
||||
<Grid
|
||||
item
|
||||
@@ -48,16 +48,16 @@ export default function ReviewPanelBody() {
|
||||
<Icon
|
||||
icon="pepicons-pop:star-filled-circle"
|
||||
color="#27f019"
|
||||
height={30}
|
||||
height={25}
|
||||
/>
|
||||
<Typography variant="h5" align="center">
|
||||
Game Review
|
||||
<Typography variant="h6" align="center">
|
||||
Engine evaluation
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
{!!bestMove && (
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h6" align="center">
|
||||
<Typography align="center">
|
||||
{`${bestMove} was the best move`}
|
||||
</Typography>
|
||||
</Grid>
|
||||
@@ -65,9 +65,7 @@ export default function ReviewPanelBody() {
|
||||
|
||||
{isGameOver && (
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h6" align="center">
|
||||
Game is over
|
||||
</Typography>
|
||||
<Typography align="center">Game is over</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ export default function AnalyzeButton() {
|
||||
return (
|
||||
<LoadingButton
|
||||
variant="contained"
|
||||
size="large"
|
||||
size="small"
|
||||
startIcon={
|
||||
!evaluationInProgress && (
|
||||
<Icon icon="streamline:magnifying-glass-solid" />
|
||||
|
||||
@@ -10,13 +10,7 @@ export default function GamePanel() {
|
||||
|
||||
const hasGameInfo = gameFromUrl !== undefined || !!game.header().White;
|
||||
|
||||
if (!hasGameInfo) {
|
||||
return (
|
||||
<Grid item container xs={12} justifyContent="center" alignItems="center">
|
||||
<Typography variant="h6">No game loaded</Typography>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
if (!hasGameInfo) return null;
|
||||
|
||||
return (
|
||||
<Grid
|
||||
@@ -25,14 +19,12 @@ export default function GamePanel() {
|
||||
xs={12}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
gap={1}
|
||||
>
|
||||
<Grid item container xs={12} justifyContent="center" alignItems="center">
|
||||
<PlayerInfo color="white" />
|
||||
|
||||
<Grid item container xs={1} justifyContent="center" alignItems="center">
|
||||
<Typography variant="h6">vs</Typography>
|
||||
</Grid>
|
||||
<Typography marginX={1.5}>vs</Typography>
|
||||
|
||||
<PlayerInfo color="black" />
|
||||
</Grid>
|
||||
@@ -40,10 +32,11 @@ export default function GamePanel() {
|
||||
<Grid
|
||||
item
|
||||
container
|
||||
xs={10}
|
||||
xs={11}
|
||||
justifyContent="space-evenly"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
rowGap={1}
|
||||
columnGap={3}
|
||||
>
|
||||
<Typography>
|
||||
Site : {gameFromUrl?.site || game.header().Site || "?"}
|
||||
|
||||
@@ -26,13 +26,13 @@ export default function PlayerInfo({ color }: Props) {
|
||||
xs={5}
|
||||
justifyContent={color === "white" ? "flex-end" : "flex-start"}
|
||||
alignItems="center"
|
||||
gap={1}
|
||||
gap={0.5}
|
||||
>
|
||||
<Typography variant="h6">
|
||||
<Typography>
|
||||
{playerName || (color === "white" ? "White" : "Black")}
|
||||
</Typography>
|
||||
|
||||
<Typography variant="h6">{rating ? `(${rating})` : "(?)"}</Typography>
|
||||
<Typography>{rating ? `(${rating})` : "(?)"}</Typography>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,34 +13,47 @@ export default function ReviewPanelHeader() {
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
xs={12}
|
||||
gap={3}
|
||||
rowGap={3}
|
||||
>
|
||||
<Grid
|
||||
item
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
>
|
||||
<Grid item xs={1} />
|
||||
|
||||
<Grid
|
||||
item
|
||||
container
|
||||
xs
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
columnGap={1}
|
||||
>
|
||||
<Icon icon="ph:file-magnifying-glass-fill" height={40} />
|
||||
<Typography variant="h4" align="center">
|
||||
<Icon icon="ph:file-magnifying-glass-fill" height={28} />
|
||||
|
||||
<Typography variant="h5" align="center">
|
||||
Game Report
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<EngineSettingsButton />
|
||||
</Grid>
|
||||
|
||||
<Grid
|
||||
item
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
gap={3}
|
||||
rowGap={3}
|
||||
columnGap={15}
|
||||
>
|
||||
<GamePanel />
|
||||
<LoadGame />
|
||||
<AnalyzeButton />
|
||||
<EngineSettingsButton />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Grid } from "@mui/material";
|
||||
import LoadGameButton from "../../loadGame/loadGameButton";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { useChessActions } from "@/hooks/useChess";
|
||||
@@ -50,14 +49,13 @@ export default function LoadGame() {
|
||||
const isGameLoaded = gameFromUrl !== undefined || !!game.header().White;
|
||||
|
||||
return (
|
||||
<Grid item container xs={12} justifyContent="center" alignItems="center">
|
||||
<LoadGameButton
|
||||
label={isGameLoaded ? "Load another game" : "Load game"}
|
||||
size="small"
|
||||
setGame={async (game) => {
|
||||
await router.push("/");
|
||||
resetAndSetGamePgn(game.pgn());
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import { Button } from "@mui/material";
|
||||
import { IconButton, Tooltip } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import EngineSettingsDialog from "./engineSettingsDialog";
|
||||
import { Icon } from "@iconify/react";
|
||||
|
||||
export default function EngineSettingsButton() {
|
||||
const [openDialog, setOpenDialog] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button variant="contained" onClick={() => setOpenDialog(true)}>
|
||||
Engine Settings
|
||||
</Button>
|
||||
<Tooltip title="Engine settings">
|
||||
<IconButton onClick={() => setOpenDialog(true)}>
|
||||
<Icon icon="ri:settings-3-line" height={20} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
<EngineSettingsDialog
|
||||
open={openDialog}
|
||||
|
||||
@@ -28,9 +28,10 @@ export default function EngineSettingsDialog({ open, onClose }: Props) {
|
||||
<DialogTitle marginY={1} variant="h5">
|
||||
Set engine parameters
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContent sx={{ paddingBottom: 0 }}>
|
||||
<Typography>
|
||||
Only Stockfish 16 is available now, more engine choices will come !
|
||||
Stockfish 16 is the only engine available now, more engine choices
|
||||
will come soon !
|
||||
</Typography>
|
||||
<Grid
|
||||
marginTop={4}
|
||||
|
||||
@@ -6,14 +6,19 @@ import { Chess } from "chess.js";
|
||||
interface Props {
|
||||
setGame?: (game: Chess) => void;
|
||||
label?: string;
|
||||
size?: "small" | "medium" | "large";
|
||||
}
|
||||
|
||||
export default function LoadGameButton({ setGame, label }: Props) {
|
||||
export default function LoadGameButton({ setGame, label, size }: Props) {
|
||||
const [openDialog, setOpenDialog] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button variant="contained" onClick={() => setOpenDialog(true)}>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => setOpenDialog(true)}
|
||||
size={size}
|
||||
>
|
||||
{label || "Add game"}
|
||||
</Button>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user