import { useState, useEffect, useCallback, useRef } from 'react' import { pickChallenge, NOVICE_LETTERS, OPERATOR_WORDS } from '../lib/morse' import { useMorseAudio } from '../hooks/useMorseAudio' import { useProgress } from '../hooks/useProgress' import { ScoreBar } from '../components/ScoreBar' import { PracticeCard } from '../components/PracticeCard' type GamePageProps = { token: string onLogout: () => void } export function GamePage({ token, onLogout }: GamePageProps) { const audio = useMorseAudio() const { progress, letterStats, mnemonics, loading, recordAnswer } = useProgress(token) const [challenge, setChallenge] = useState(null) const [result, setResult] = useState<'correct' | 'incorrect' | null>(null) const [showLevelUp, setShowLevelUp] = useState(false) const recentHistoryRef = useRef([]) const incorrectRecordedRef = useRef(false) // Pick a new challenge based on current level const nextChallenge = useCallback(() => { const level = progress?.level ?? 1 const pool = level >= 2 ? OPERATOR_WORDS : NOVICE_LETTERS const c = pickChallenge(pool, letterStats, recentHistoryRef.current) recentHistoryRef.current = [...recentHistoryRef.current.slice(-4), c] setChallenge(c) setResult(null) incorrectRecordedRef.current = false audio.stop() }, [progress?.level, letterStats]) // Load first challenge after progress loads useEffect(() => { if (!loading && progress && !challenge) { nextChallenge() } }, [loading, progress]) async function handleAnswer(answer: string) { if (!challenge || result === 'correct') return const isCorrect = answer === challenge.toUpperCase() setResult(isCorrect ? 'correct' : 'incorrect') if (isCorrect) { const updated = await recordAnswer(challenge, true) // Level-up trigger: 10 consecutive correct if (updated.streak > 0 && updated.streak % 10 === 0) { setShowLevelUp(true) } } else if (!incorrectRecordedRef.current) { // Only record first incorrect attempt per challenge (allow re-tries without inflating stats) incorrectRecordedRef.current = true await recordAnswer(challenge, false) } } function playChallenge() { if (!challenge) return audio.play(challenge) } if (loading || !progress || !challenge) { return (

Loading quest...

) } return (
{result === 'correct' && (
)} {/* Level-up modal */} {showLevelUp && (

Quest Complete!

10 in a row! {progress.level < 2 ? "You've advanced to Operator level!" : 'Outstanding skill!'}

)} {/* Nav */}
) }