feat(card-sorting): add auto-submit countdown for perfect sequences

When the card sequence is correct, a countdown timer now starts:
- Shows 3, 2, 1 in the submit button (1.5s per number)
- Auto-submits the solution when countdown reaches 0
- Countdown resets if sequence becomes imperfect
- Countdown disabled for spectators

This provides:
- Visual feedback that the sequence is correct
- Automatic submission without requiring a click
- Time for players to review before submission
- Smooth game flow when solving perfectly

Implementation:
- perfectCountdown state tracks current number (3, 2, 1, or null)
- First useEffect starts/resets countdown based on isSequenceCorrect
- Second useEffect decrements countdown every 1.5s and auto-submits at 0
- Button displays countdown number when active, otherwise shows checkmark

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock
2025-10-23 21:23:52 -05:00
parent 829c741e55
commit 780a7161bc

View File

@@ -867,6 +867,9 @@ export function PlayingPhaseDrag() {
const [activityFeed, setActivityFeed] = useState<ActivityNotification[]>([])
const activityIdCounter = useRef(0)
// Perfect sequence countdown (auto-submit after 3-2-1)
const [perfectCountdown, setPerfectCountdown] = useState<number | null>(null)
const containerRef = useRef<HTMLDivElement>(null)
const dragStateRef = useRef<{
cardId: string
@@ -1312,6 +1315,36 @@ export function PlayingPhaseDrag() {
return correctCard && card.id === correctCard.id
})
// Start countdown when sequence is perfect
useEffect(() => {
if (isSequenceCorrect && !isSpectating) {
// Start countdown from 3
setPerfectCountdown(3)
} else {
// Reset countdown if sequence is no longer perfect
setPerfectCountdown(null)
}
}, [isSequenceCorrect, isSpectating])
// Countdown timer effect
useEffect(() => {
if (perfectCountdown === null) return
if (perfectCountdown <= 0) {
// Auto-submit when countdown reaches 0
handleCheckSolution()
setPerfectCountdown(null)
return
}
// Decrement every 1.5 seconds
const timer = setTimeout(() => {
setPerfectCountdown((prev) => (prev !== null ? prev - 1 : null))
}, 1500)
return () => clearTimeout(timer)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [perfectCountdown])
// Watch for server confirmations and insert next card or check solution
useEffect(() => {
if (!waitingToCheck) return
@@ -1722,7 +1755,7 @@ export function PlayingPhaseDrag() {
animationName: isSequenceCorrect ? 'celebrate' : undefined,
}}
>
{perfectCountdown !== null && perfectCountdown > 0 ? perfectCountdown : '✓'}
</button>
<div
className={css({