"use client" import { useState, useEffect, useCallback } from "react" import { useParams, useRouter } from "next/navigation" import { startLearningSession, submitAnswer, endSession } from "@/actions/learning" interface Card { hanziId: string simplified: string options: string[] correctPinyin: string meaning: string } interface SessionSummary { totalCards: number correctCount: number incorrectCount: number accuracyPercent: number durationMinutes: number } export default function LearnPage() { const params = useParams() const router = useRouter() const collectionId = params.collectionId as string // Session state const [sessionId, setSessionId] = useState(null) const [cards, setCards] = useState([]) const [currentIndex, setCurrentIndex] = useState(0) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) // Card state const [selectedOption, setSelectedOption] = useState(null) const [showFeedback, setShowFeedback] = useState(false) const [isCorrect, setIsCorrect] = useState(false) const [answerStartTime, setAnswerStartTime] = useState(Date.now()) // Summary state const [showSummary, setShowSummary] = useState(false) const [summary, setSummary] = useState(null) const currentCard = cards[currentIndex] const progress = ((currentIndex / cards.length) * 100) || 0 // Start learning session useEffect(() => { const startSession = async () => { setLoading(true) setError(null) const collectionIdParam = collectionId === "all" ? undefined : collectionId const result = await startLearningSession(collectionIdParam) if (result.success && result.data) { setSessionId(result.data.sessionId) setCards(result.data.cards) setAnswerStartTime(Date.now()) } else { setError(result.message || "Failed to start learning session") } setLoading(false) } startSession() }, [collectionId]) // Handle answer selection const handleSelectAnswer = useCallback((index: number) => { if (showFeedback) return // Prevent changing answer after submission setSelectedOption(index) }, [showFeedback]) // Submit answer const handleSubmitAnswer = useCallback(async () => { if (selectedOption === null || !currentCard || !sessionId) return if (showFeedback) return // Already submitted const selectedPinyin = currentCard.options[selectedOption] const correct = selectedPinyin === currentCard.correctPinyin const timeSpentMs = Date.now() - answerStartTime setIsCorrect(correct) setShowFeedback(true) // Submit to backend await submitAnswer( sessionId, currentCard.hanziId, selectedPinyin, correct, timeSpentMs ) }, [selectedOption, currentCard, sessionId, showFeedback, answerStartTime]) // Continue to next card or end session const handleContinue = useCallback(async () => { if (currentIndex < cards.length - 1) { setCurrentIndex(prev => prev + 1) setSelectedOption(null) setShowFeedback(false) setAnswerStartTime(Date.now()) } else { // End session and show summary if (sessionId) { const result = await endSession(sessionId) if (result.success && result.data) { setSummary(result.data) } } setShowSummary(true) } }, [currentIndex, cards.length, sessionId]) // Keyboard shortcuts useEffect(() => { const handleKeyPress = (e: KeyboardEvent) => { // Numbers 1-4 for answer selection if (["1", "2", "3", "4"].includes(e.key)) { const index = parseInt(e.key) - 1 if (index < currentCard?.options.length) { if (!showFeedback) { handleSelectAnswer(index) // Auto-submit after selection setTimeout(() => { handleSubmitAnswer() }, 100) } } } // Space to continue if (e.key === " " && showFeedback) { e.preventDefault() handleContinue() } } window.addEventListener("keydown", handleKeyPress) return () => window.removeEventListener("keydown", handleKeyPress) }, [currentCard, showFeedback, handleSelectAnswer, handleSubmitAnswer, handleContinue]) // Loading state if (loading) { return (

Loading cards...

) } // Error state if (error) { return (

No Cards Available

{error}

) } // Summary screen if (showSummary && summary) { return (
🎉

Session Complete!

Great work!

Total Cards {summary.totalCards}
Correct {summary.correctCount}
Incorrect {summary.incorrectCount}
Accuracy {summary.accuracyPercent}%
Duration {summary.durationMinutes} min
) } // Learning card screen if (!currentCard) { return
No cards available
} return (
{/* Progress bar */}
Card {currentIndex + 1} of {cards.length} {Math.round(progress)}%
{/* Main card area */}
{/* Feedback overlay */} {showFeedback && (
{isCorrect ? "✓" : "✗"}

{isCorrect ? "Correct!" : "Incorrect"}

{!isCorrect && (

Correct answer: {currentCard.correctPinyin}

)} {currentCard.meaning && (

{currentCard.meaning}

)}
)} {/* Hanzi display */}
{currentCard.simplified}

Select the correct pinyin

{/* Answer options in 2x2 grid */}
{currentCard.options.map((option, index) => ( ))}
{/* Keyboard shortcuts hint */}

Press 1-4 to select • Space to continue

) }