import React, { useCallback, useState } from 'react' import { Square } from 'chess.js' import { ChessPiece } from './ChessPiece' import { GameState, DraggedPiece } from '../types/chess' import { isSquareLight } from '../utils/chessUtils' import { AudioEngine } from '../engines/AudioEngine' import '../styles/ChessBoard.css' import '../styles/ChessSquare.css' export const ChessBoard: React.FC<{ gameState: GameState draggedPiece: DraggedPiece | null audioEngine: AudioEngine | null onSquareClick: (square: Square) => void onPieceDragStart: (square: Square) => void onPieceDrop: (targetSquare: Square | null) => void }> = ({ gameState, draggedPiece, audioEngine, onSquareClick, onPieceDragStart, onPieceDrop }) => { const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }) const [isDragging, setIsDragging] = useState(false) const handleMouseMove = useCallback((event: React.MouseEvent) => { setMousePosition({ x: event.clientX, y: event.clientY }) }, []) const handleSquareClick = useCallback((square: Square) => { if (!isDragging) { onSquareClick(square) } }, [onSquareClick, isDragging]) const handleMouseDown = useCallback((square: Square) => { const piece = gameState.board.get(square) if (piece && piece.color === gameState.playerColor) { setIsDragging(true) onPieceDragStart(square) } }, [gameState, onPieceDragStart]) const handleMouseUp = useCallback((square: Square) => { if (isDragging) { onPieceDrop(square) setIsDragging(false) } }, [isDragging, onPieceDrop]) const renderSquares = () => { const renderedSquares = [] for (let rank = 8; rank >= 1; rank--) { for (let file = 0; file < 8; file++) { const square = (String.fromCharCode(97 + file) + rank) as Square let displayFile = file let displayRank = rank if (gameState.playerColor === 'b') { displayFile = 7 - file displayRank = 9 - rank } const piece = gameState.board.get(square) || null const isSelected = gameState.selectedSquare === square const isLegalMove = gameState.legalMoves.some(move => move.to === square) const isDraggedSquare = draggedPiece?.square === square const isLight = isSquareLight(square) renderedSquares.push(
handleSquareClick(square)} onMouseDown={() => handleMouseDown(square)} onMouseUp={() => handleMouseUp(square)} > {piece && !isDraggedSquare && (
)} {isLegalMove && (
)}
) } } return renderedSquares } const renderDraggedPiece = () => { if (!draggedPiece) return null return (
) } return (
{renderSquares()}
{Array.from({ length: 8 }, (_, i) => { const fileIndex = gameState.playerColor === 'w' ? i : 7 - i const fileLabel = String.fromCharCode(97 + fileIndex) const noteName = audioEngine?.getFileNoteName(fileIndex) || '' return (
{fileLabel} ({noteName})
) })}
{Array.from({ length: 8 }, (_, i) => { const rankIndex = gameState.playerColor === 'w' ? 8 - i : i + 1 const octave = gameState.playerColor === 'w' ? 8 - i : i + 1 return (
{rankIndex} (♪{octave})
) })}
{renderDraggedPiece()}
) }