refactor: code review improvements

- Add 30s timeout to Stockfish evaluation to prevent hanging promises
- Add FEN validation and depth cap (max 30) to Stockfish API route
- Create ErrorBoundary component with specialized fallbacks for chess game and tutor
- Extract useChessSounds hook for better audio management
- Add React.memo to EvaluationBar and CapturedPieces for performance
- Add useMemo to CapturedPieces for sorted pieces calculation
- Improve tacticDetection to return empty array instead of "none" type
- Add filterMeaningfulTactics and hasTactics helper functions
- Translate hardcoded UI strings (stockfishLevel, download, evalChange)
- Update translations for EN, DE, FR, IT, PL
- Add uuid to Jest transformIgnorePatterns for ESM compatibility
- Update tests to use new filterMeaningfulTactics function
This commit is contained in:
Claude
2025-12-10 21:30:28 +00:00
parent 014781e2d0
commit 47c37487b3
17 changed files with 385 additions and 61 deletions
+14 -6
View File
@@ -1,4 +1,4 @@
import React from 'react';
import React, { memo, useMemo } from 'react';
interface CapturedPiecesProps {
captured: string[]; // Array of piece types, e.g., ['p', 'n', 'q']
@@ -15,10 +15,18 @@ const PIECE_ICONS: Record<string, string> = {
'k': '♚', // King is never captured, but for completeness
};
export const CapturedPieces: React.FC<CapturedPiecesProps> = ({ captured, color, score }) => {
// Sort pieces by value for better display: Q, R, B, N, P
const sortOrder = ['q', 'r', 'b', 'n', 'p'];
const sortedPieces = [...captured].sort((a, b) => sortOrder.indexOf(a) - sortOrder.indexOf(b));
const sortOrder = ['q', 'r', 'b', 'n', 'p'];
/**
* Displays captured pieces with optional material advantage score.
* Memoized to prevent unnecessary re-renders.
*/
export const CapturedPieces = memo(function CapturedPieces({ captured, color, score }: CapturedPiecesProps) {
// Memoize sorted pieces to prevent recalculation on every render
const sortedPieces = useMemo(
() => [...captured].sort((a, b) => sortOrder.indexOf(a) - sortOrder.indexOf(b)),
[captured]
);
return (
<div className="flex items-center h-8 gap-2 text-gray-600 dark:text-gray-300">
@@ -36,4 +44,4 @@ export const CapturedPieces: React.FC<CapturedPiecesProps> = ({ captured, color,
)}
</div>
);
};
});