From fe9ca43433b92543331fede506a6e723b67c30ee Mon Sep 17 00:00:00 2001 From: somnath Date: Tue, 2 Jul 2024 14:37:46 +0530 Subject: [PATCH] fixed sidebar UI --- apps/frontend/src/components/ChessBoard.tsx | 609 +++++++++----------- apps/frontend/src/components/sidebar.tsx | 12 +- 2 files changed, 290 insertions(+), 331 deletions(-) diff --git a/apps/frontend/src/components/ChessBoard.tsx b/apps/frontend/src/components/ChessBoard.tsx index 179de87a..cead4582 100644 --- a/apps/frontend/src/components/ChessBoard.tsx +++ b/apps/frontend/src/components/ChessBoard.tsx @@ -13,11 +13,7 @@ import CaptureSound from '/capture.wav'; import { useRecoilState } from 'recoil'; -import { - isBoardFlippedAtom, - movesAtom, - userSelectedMoveIndexAtom, -} from '@repo/store/chessBoard'; +import { isBoardFlippedAtom, movesAtom, userSelectedMoveIndexAtom } from '@repo/store/chessBoard'; export function isPromoting(chess: Chess, from: Square, to: Square) { if (!from) { @@ -44,356 +40,323 @@ export function isPromoting(chess: Chess, from: Square, to: Square) { .includes(to); } -export const ChessBoard = memo(({ - gameId, - started, - myColor, - chess, - board, - socket, - setBoard, -}: { - myColor: Color; - gameId: string; - started: boolean; - chess: Chess; - setBoard: React.Dispatch< - React.SetStateAction< - ({ - square: Square; - type: PieceSymbol; - color: Color; - } | null)[][] - > - >; - board: ({ - square: Square; - type: PieceSymbol; - color: Color; - } | null)[][]; - socket: WebSocket; -}) => { - console.log("chessboard reloaded") +export const ChessBoard = memo( + ({ + gameId, + started, + myColor, + chess, + board, + socket, + setBoard, + }: { + myColor: Color; + gameId: string; + started: boolean; + chess: Chess; + setBoard: React.Dispatch< + React.SetStateAction< + ({ + square: Square; + type: PieceSymbol; + color: Color; + } | null)[][] + > + >; + board: ({ + square: Square; + type: PieceSymbol; + color: Color; + } | null)[][]; + socket: WebSocket; + }) => { + console.log('chessboard reloaded'); - const [isFlipped, setIsFlipped] = useRecoilState(isBoardFlippedAtom); - const [userSelectedMoveIndex, setUserSelectedMoveIndex] = useRecoilState( - userSelectedMoveIndexAtom, - ); - const [moves, setMoves] = useRecoilState(movesAtom); - const [lastMove, setLastMove] = useState<{ from: string; to: string } | null>( - null, - ); - const [rightClickedSquares, setRightClickedSquares] = useState([]); - const [arrowStart, setArrowStart] = useState(null); + const [isFlipped, setIsFlipped] = useRecoilState(isBoardFlippedAtom); + const [userSelectedMoveIndex, setUserSelectedMoveIndex] = useRecoilState(userSelectedMoveIndexAtom); + const [moves, setMoves] = useRecoilState(movesAtom); + const [lastMove, setLastMove] = useState<{ from: string; to: string } | null>(null); + const [rightClickedSquares, setRightClickedSquares] = useState([]); + const [arrowStart, setArrowStart] = useState(null); - const [from, setFrom] = useState(null); - const isMyTurn = myColor === chess.turn(); - const [legalMoves, setLegalMoves] = useState([]); + const [from, setFrom] = useState(null); + const isMyTurn = myColor === chess.turn(); + const [legalMoves, setLegalMoves] = useState([]); - const labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; - const [canvas, setCanvas] = useState(null); - const boxSize = 80; - const [gameOver, setGameOver] = useState(false); - const moveAudio = new Audio(MoveSound); - const captureAudio = new Audio(CaptureSound); + const labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; + const [canvas, setCanvas] = useState(null); + const boxSize = 80; + const [gameOver, setGameOver] = useState(false); + const moveAudio = new Audio(MoveSound); + const captureAudio = new Audio(CaptureSound); - const handleMouseDown = ( - e: MouseEvent, - squareRep: string, - ) => { - e.preventDefault(); - if (e.button === 2) { - setArrowStart(squareRep); - } - }; - - useEffect(() => { - if (myColor === 'b') { - setIsFlipped(true); - } - }, [myColor]); - - const clearCanvas = () => { - setRightClickedSquares([]); - if (canvas) { - const ctx = canvas.getContext('2d'); - ctx?.clearRect(0, 0, canvas.width, canvas.height); - } - }; + const handleMouseDown = (e: MouseEvent, squareRep: string) => { + e.preventDefault(); + if (e.button === 2) { + setArrowStart(squareRep); + } + }; - const handleRightClick = (squareRep: string) => { - if (rightClickedSquares.includes(squareRep)) { - setRightClickedSquares((prev) => prev.filter((sq) => sq !== squareRep)); - } else { - setRightClickedSquares((prev) => [...prev, squareRep]); - } - }; + useEffect(() => { + if (myColor === 'b') { + setIsFlipped(true); + } + }, [myColor]); - const handleDrawArrow = (squareRep: string) => { - if (arrowStart) { - const stoppedAtSquare = squareRep; + const clearCanvas = () => { + setRightClickedSquares([]); if (canvas) { const ctx = canvas.getContext('2d'); - if (ctx) { - drawArrow({ - ctx, - start: arrowStart, - end: stoppedAtSquare, - isFlipped, - squareSize: boxSize, - }); + ctx?.clearRect(0, 0, canvas.width, canvas.height); + } + }; + + const handleRightClick = (squareRep: string) => { + if (rightClickedSquares.includes(squareRep)) { + setRightClickedSquares((prev) => prev.filter((sq) => sq !== squareRep)); + } else { + setRightClickedSquares((prev) => [...prev, squareRep]); + } + }; + + const handleDrawArrow = (squareRep: string) => { + if (arrowStart) { + const stoppedAtSquare = squareRep; + if (canvas) { + const ctx = canvas.getContext('2d'); + if (ctx) { + drawArrow({ + ctx, + start: arrowStart, + end: stoppedAtSquare, + isFlipped, + squareSize: boxSize, + }); + } } + setArrowStart(null); } - setArrowStart(null); - } - }; + }; - const handleMouseUp = (e: MouseEvent, squareRep: string) => { - e.preventDefault(); - if (!started) { - return; - } - if (e.button === 2) { - if (arrowStart === squareRep) { - handleRightClick(squareRep); + const handleMouseUp = (e: MouseEvent, squareRep: string) => { + e.preventDefault(); + if (!started) { + return; + } + if (e.button === 2) { + if (arrowStart === squareRep) { + handleRightClick(squareRep); + } else { + handleDrawArrow(squareRep); + } } else { - handleDrawArrow(squareRep); + clearCanvas(); } - } else { + }; + + useEffect(() => { clearCanvas(); - } - }; + const lMove = moves.at(-1); + if (lMove) { + setLastMove({ + from: lMove.from, + to: lMove.to, + }); + } else { + setLastMove(null); + } + }, [moves]); - useEffect(() => { - clearCanvas(); - const lMove = moves.at(-1); - if (lMove) { - setLastMove({ - from: lMove.from, - to: lMove.to, - }); - } else { - setLastMove(null); - } - }, [moves]); + useEffect(() => { + if (userSelectedMoveIndex !== null) { + const move = moves[userSelectedMoveIndex]; + setLastMove({ + from: move.from, + to: move.to, + }); + chess.load(move.after); + setBoard(chess.board()); + return; + } + }, [userSelectedMoveIndex]); - useEffect(() => { - if (userSelectedMoveIndex !== null) { - const move = moves[userSelectedMoveIndex]; - setLastMove({ - from: move.from, - to: move.to, - }); - chess.load(move.after); - setBoard(chess.board()); - return; - } - }, [userSelectedMoveIndex]); + useEffect(() => { + if (userSelectedMoveIndex !== null) { + chess.reset(); + moves.forEach((move) => { + chess.move({ from: move.from, to: move.to }); + }); + setBoard(chess.board()); + setUserSelectedMoveIndex(null); + } else { + setBoard(chess.board()); + } + }, [moves]); - useEffect(() => { - if (userSelectedMoveIndex !== null) { - chess.reset(); - moves.forEach((move) => { - chess.move({ from: move.from, to: move.to }); - }); - setBoard(chess.board()); - setUserSelectedMoveIndex(null); - } else { - setBoard(chess.board()); - } - }, [moves]); + return ( + <> + {gameOver && } +
+
+ {(isFlipped ? board.slice().reverse() : board).map((row, i) => { + i = isFlipped ? i + 1 : 8 - i; + return ( +
+ + {(isFlipped ? row.slice().reverse() : row).map((square, j) => { + j = isFlipped ? 7 - (j % 8) : j % 8; - return ( - <> - {gameOver && } -
-
- {(isFlipped ? board.slice().reverse() : board).map((row, i) => { - i = isFlipped ? i + 1 : 8 - i; - return ( -
- - {(isFlipped ? row.slice().reverse() : row).map((square, j) => { - j = isFlipped ? 7 - (j % 8) : j % 8; + const isMainBoxColor = (i + j) % 2 !== 0; + const isPiece: boolean = !!square; + const squareRepresentation = (String.fromCharCode(97 + j) + '' + i) as Square; + const isHighlightedSquare = + from === squareRepresentation || + squareRepresentation === lastMove?.from || + squareRepresentation === lastMove?.to; + const isRightClickedSquare = rightClickedSquares.includes(squareRepresentation); - const isMainBoxColor = (i + j) % 2 !== 0; - const isPiece: boolean = !!square; - const squareRepresentation = (String.fromCharCode(97 + j) + - '' + - i) as Square; - const isHighlightedSquare = - from === squareRepresentation || - squareRepresentation === lastMove?.from || - squareRepresentation === lastMove?.to; - const isRightClickedSquare = - rightClickedSquares.includes(squareRepresentation); + const piece = square && square.type; + const isKingInCheckSquare = piece === 'k' && square?.color === chess.turn() && chess.inCheck(); - const piece = square && square.type; - const isKingInCheckSquare = - piece === 'k' && - square?.color === chess.turn() && - chess.inCheck(); + return ( +
{ + if (!started) { + return; + } + if (userSelectedMoveIndex !== null) { + chess.reset(); + moves.forEach((move) => { + chess.move({ from: move.from, to: move.to }); + }); + setBoard(chess.board()); + setUserSelectedMoveIndex(null); + return; + } + if (!from && square?.color !== chess.turn()) return; + if (!isMyTurn) return; + if (from != squareRepresentation) { + setFrom(squareRepresentation); + if (isPiece) { + setLegalMoves( + chess + .moves({ + verbose: true, + square: square?.square, + }) + .map((move) => move.to) + ); + } + } else { + setFrom(null); + } + if (!isPiece) { + setLegalMoves([]); + } - return ( -
{ - if (!started) { - return; - } - if (userSelectedMoveIndex !== null) { - chess.reset(); - moves.forEach((move) => { - chess.move({ from: move.from, to: move.to }); - }); - setBoard(chess.board()); - setUserSelectedMoveIndex(null); - return; - } - if (!from && square?.color !== chess.turn()) return; - if (!isMyTurn) return; - if (from != squareRepresentation) { - setFrom(squareRepresentation); - if (isPiece) { + if (!from) { + setFrom(squareRepresentation); setLegalMoves( chess .moves({ verbose: true, square: square?.square, }) - .map((move) => move.to), + .map((move) => move.to) ); - } - } else { - setFrom(null); - } - if (!isPiece) { - setLegalMoves([]); - } - - if (!from) { - setFrom(squareRepresentation); - setLegalMoves( - chess - .moves({ - verbose: true, - square: square?.square, - }) - .map((move) => move.to), - ); - } else { - try { - let moveResult: Move; - if ( - isPromoting(chess, from, squareRepresentation) - ) { - moveResult = chess.move({ - from, - to: squareRepresentation, - promotion: 'q', - }); - } else { - moveResult = chess.move({ - from, - to: squareRepresentation, - }); - } - if (moveResult) { - moveAudio.play(); - - if (moveResult?.captured) { - captureAudio.play(); + } else { + try { + let moveResult: Move; + if (isPromoting(chess, from, squareRepresentation)) { + moveResult = chess.move({ + from, + to: squareRepresentation, + promotion: 'q', + }); + } else { + moveResult = chess.move({ + from, + to: squareRepresentation, + }); } - setMoves((prev) => [...prev, moveResult]); - setFrom(null); - setLegalMoves([]); - if (moveResult.san.includes('#')) { - setGameOver(true); + if (moveResult) { + moveAudio.play(); + + if (moveResult?.captured) { + captureAudio.play(); + } + setMoves((prev) => [...prev, moveResult]); + setFrom(null); + setLegalMoves([]); + if (moveResult.san.includes('#')) { + setGameOver(true); + } + socket.send( + JSON.stringify({ + type: MOVE, + payload: { + gameId, + move: moveResult, + }, + }) + ); } - socket.send( - JSON.stringify({ - type: MOVE, - payload: { - gameId, - move: moveResult, - }, - }), - ); + } catch (e) { + console.log('e', e); } - } catch (e) { - console.log('e', e); } - } - }} - style={{ - width: boxSize, - height: boxSize, - }} - key={j} - className={`${isRightClickedSquare ? (isMainBoxColor ? 'bg-[#CF664E]' : 'bg-[#E87764]') : isKingInCheckSquare ? 'bg-[#FF6347]' : isHighlightedSquare ? `${isMainBoxColor ? 'bg-[#BBCB45]' : 'bg-[#F4F687]'}` : isMainBoxColor ? 'bg-boardDark' : 'bg-boardLight'} ${''}`} - onContextMenu={(e) => { - e.preventDefault(); - }} - onMouseDown={(e) => { - handleMouseDown(e, squareRepresentation); - }} - onMouseUp={(e) => { - handleMouseUp(e, squareRepresentation); - }} - > -
- {square && } - {isFlipped - ? i === 8 && ( - - ) - : i === 1 && ( - - )} - {!!from && - legalMoves.includes(squareRepresentation) && ( - + }} + style={{ + width: boxSize, + height: boxSize, + }} + key={j} + className={`${isRightClickedSquare ? (isMainBoxColor ? 'bg-[#CF664E]' : 'bg-[#E87764]') : isKingInCheckSquare ? 'bg-[#FF6347]' : isHighlightedSquare ? `${isMainBoxColor ? 'bg-[#BBCB45]' : 'bg-[#F4F687]'}` : isMainBoxColor ? 'bg-boardDark' : 'bg-boardLight'} ${''}`} + onContextMenu={(e) => { + e.preventDefault(); + }} + onMouseDown={(e) => { + handleMouseDown(e, squareRepresentation); + }} + onMouseUp={(e) => { + handleMouseUp(e, squareRepresentation); + }} + > +
+ {square && } + {isFlipped + ? i === 8 && + : i === 1 && } + {!!from && legalMoves.includes(squareRepresentation) && ( + )} +
-
- ); - })} -
- ); - })} -
- - setCanvas(ref)} - width={boxSize * 8} - height={boxSize * 8} - style={{ - position: 'absolute', - top: 0, - left: 0, - pointerEvents: 'none', - }} - onContextMenu={(e) => e.preventDefault()} - onMouseDown={(e) => { - e.preventDefault(); - }} - onMouseUp={(e) => e.preventDefault()} - > -
- - ); - -}; - + ); + })} +
+ ); + })} +
+ setCanvas(ref)} + width={boxSize * 8} + height={boxSize * 8} + style={{ + position: 'absolute', + top: 0, + left: 0, + pointerEvents: 'none', + }} + onContextMenu={(e) => e.preventDefault()} + onMouseDown={(e) => { + e.preventDefault(); + }} + onMouseUp={(e) => e.preventDefault()} + > +
+ + ); + } +); diff --git a/apps/frontend/src/components/sidebar.tsx b/apps/frontend/src/components/sidebar.tsx index 28bbcc29..82ac27e5 100644 --- a/apps/frontend/src/components/sidebar.tsx +++ b/apps/frontend/src/components/sidebar.tsx @@ -36,26 +36,22 @@ export default function Sidebar({ className }: SidebarProps) {