Chess_Engine / web /src /components /ChessClock.tsx
electro-sb's picture
first commit
100a6dd
import * as React from 'react';
const { useState, useEffect, useRef } = React;
interface ChessClockProps {
isPlayerTurn: boolean;
playerColor: 'white' | 'black';
gameActive: boolean;
initialTimeMinutes?: number;
}
const ChessClock: React.FC<ChessClockProps> = ({
isPlayerTurn,
playerColor,
gameActive,
initialTimeMinutes = 10
}) => {
// Convert minutes to milliseconds
const initialTime = initialTimeMinutes * 60 * 1000;
// Store the initial time in a ref to access it for resets
const initialTimeRef = useRef<number>(initialTime);
const [whiteTime, setWhiteTime] = useState<number>(initialTime);
const [blackTime, setBlackTime] = useState<number>(initialTime);
const [activeClock, setActiveClock] = useState<'white' | 'black' | null>(null);
// Track previous turn state to detect changes
const prevTurnRef = useRef<boolean | null>(null);
const prevActiveClockRef = useRef<'white' | 'black' | null>(null);
const playerClockRef = useRef<'white' | 'black'>(playerColor);
const aiClockRef = useRef<'white' | 'black'>(playerColor === 'white' ? 'black' : 'white');
// Update player/AI clock references when player color changes
useEffect(() => {
playerClockRef.current = playerColor;
aiClockRef.current = playerColor === 'white' ? 'black' : 'white';
}, [playerColor]);
// Reset clocks when game becomes active (new game started)
useEffect(() => {
if (gameActive) {
setWhiteTime(initialTime);
setBlackTime(initialTime);
console.log('Clocks reset for new game');
}
}, [gameActive, initialTime]);
// Update active clock based on whose turn it is
useEffect(() => {
if (!gameActive) {
setActiveClock(null);
return;
}
// Determine whose turn it is based on the current player turn and player color
const currentActiveClock = isPlayerTurn ? playerColor : (playerColor === 'white' ? 'black' : 'white');
// Only update if the active clock has changed
if (currentActiveClock !== activeClock) {
setActiveClock(currentActiveClock);
console.log(`Clock switched to: ${currentActiveClock} (Player: ${playerColor}, PlayerTurn: ${isPlayerTurn})`);
}
}, [isPlayerTurn, playerColor, gameActive, activeClock]);
// Clock tick effect
useEffect(() => {
if (!gameActive || !activeClock) {
return;
}
const interval = setInterval(() => {
if (activeClock === 'white') {
setWhiteTime((prev) => Math.max(0, prev - 1000));
} else if (activeClock === 'black') {
setBlackTime((prev) => Math.max(0, prev - 1000));
}
}, 1000);
return () => clearInterval(interval);
}, [activeClock, gameActive]);
// Format time as mm:ss
const formatTime = (timeMs: number): string => {
const totalSeconds = Math.floor(timeMs / 1000);
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
};
return (
<div className="flex justify-between items-center w-full max-w-[800px] mb-4">
<div
className={`p-3 rounded-lg ${
activeClock === 'white'
? 'bg-gradio-card border-2 border-gradio-blue'
: 'bg-gradio-bg'
}`}
>
<div className="text-lg font-medium text-gradio-text">White</div>
<div className={`text-2xl font-bold ${whiteTime < 60000 ? 'text-gradio-red' : 'text-gradio-text'}`}>
{formatTime(whiteTime)}
</div>
</div>
{/* Title in the middle of the timers */}
<div className="bg-gradio-card py-3 px-6 rounded-lg shadow-lg">
<h2 className="text-3xl font-bold text-gradio-orange">Chess Engine</h2>
</div>
<div
className={`p-3 rounded-lg ${
activeClock === 'black'
? 'bg-gradio-card border-2 border-gradio-blue'
: 'bg-gradio-bg'
}`}
>
<div className="text-lg font-medium text-gradio-text">Black</div>
<div className={`text-2xl font-bold ${blackTime < 60000 ? 'text-gradio-red' : 'text-gradio-text'}`}>
{formatTime(blackTime)}
</div>
</div>
</div>
);
};
export default ChessClock;