File size: 3,969 Bytes
9ac3b1c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { motion } from 'framer-motion';

export default function ChessBoard({ board, onSquareClick, selectedPos, validMoves, lastMove, turn }) {
  const files = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
  const ranks = ['8', '7', '6', '5', '4', '3', '2', '1'];

  return (
    <div className="relative">
      {/* Board Border Decoration */}
      <div className="absolute -inset-4 bg-black z-0 hidden sm:block" />
      
      <div className="grid grid-cols-8 grid-rows-8 border-4 border-black bg-black gap-0 relative z-10 shadow-piece">
        {board.map((row, rowIndex) => (
          row.map((piece, colIndex) => {
            const isBlackSquare = (rowIndex + colIndex) % 2 === 1;
            const isSelected = selectedPos?.r === rowIndex && selectedPos?.c === colIndex;
            const isValidMove = validMoves.some(m => m.r === rowIndex && m.c === colIndex);
            const isLastMoveFrom = lastMove?.from.r === rowIndex && lastMove?.from.c === colIndex;
            const isLastMoveTo = lastMove?.to.r === rowIndex && lastMove?.to.c === colIndex;
            const isCheck = false; // Simplified for this demo

            return (
              <div
                key={`${rowIndex}-${colIndex}`}
                onClick={() => onSquareClick(rowIndex, colIndex)}
                className={`
                  chess-square
                  ${isBlackSquare ? 'bg-[#769656]' : 'bg-[#eeeed2]'}
                  ${isSelected ? '!bg-comic-yellow ring-4 ring-inset ring-black z-20' : ''}
                  ${(isLastMoveFrom || isLastMoveTo) && !isSelected ? 'bg-comic-blue/40' : ''}
                `}
              >
                {/* Coordinate Labels */}
                {colIndex === 0 && (
                  <span className={`absolute top-0.5 left-1 text-[10px] font-bold ${isBlackSquare ? 'text-[#eeeed2]' : 'text-[#769656]'}`}>
                    {ranks[rowIndex]}
                  </span>
                )}
                {rowIndex === 7 && (
                  <span className={`absolute bottom-0 right-1 text-[10px] font-bold ${isBlackSquare ? 'text-[#eeeed2]' : 'text-[#769656]'}`}>
                    {files[colIndex]}
                  </span>
                )}

                {/* Valid Move Indicator */}
                {isValidMove && !piece && (
                  <div className="w-4 h-4 rounded-full bg-black/20" />
                )}
                {isValidMove && piece && (
                  <div className="absolute inset-0 ring-4 ring-inset ring-comic-red/50 rounded-none" />
                )}

                {/* Piece */}
                {piece && (
                  <motion.div
                    initial={{ scale: 0.8, opacity: 0 }}
                    animate={{ scale: 1, opacity: 1 }}
                    className={`
                      piece-3d 
                      ${isWhitePiece(piece) ? 'text-white drop-shadow-[2px_2px_0_rgba(0,0,0,1)]' : 'text-black drop-shadow-[1px_1px_0_rgba(255,255,255,0.5)]'}
                      ${turn === 'white' && isWhitePiece(piece) ? 'cursor-grab active:cursor-grabbing' : ''}
                      ${turn === 'black' && isBlackPiece(piece) ? 'cursor-grab active:cursor-grabbing' : ''}
                    `}
                    style={{ 
                      filter: isWhitePiece(piece) 
                        ? 'drop-shadow(2px 4px 6px rgba(0,0,0,0.4))' 
                        : 'drop-shadow(2px 4px 6px rgba(0,0,0,0.2))'

                  >
                    {getPieceSymbol(piece)}
                  </motion.div>
                )}
              </div>
            );
          })
        ))}
      </div>
    </div>
  );
}

const isWhitePiece = (p) => p === p.toUpperCase();
const isBlackPiece = (p) => p === p.toLowerCase();

const getPieceSymbol = (p) => {
  const map = {
    'K': 'β™”', 'Q': 'β™•', 'R': 'β™–', 'B': 'β™—', 'N': 'β™˜', 'P': 'β™™',
    'k': 'β™š', 'q': 'β™›', 'r': 'β™œ', 'b': '♝', 'n': 'β™ž', 'p': 'β™Ÿ',
  };
  return map[p] || '';
};