All files / components/domain VocabularyApp.tsx

100% Statements 27/27
100% Branches 14/14
100% Functions 2/2
100% Lines 27/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93    1x   1x 1x 1x 1x 1x                   8x 20x 20x 20x                     20x   20x 6x 6x   6x 6x 4x   4x 2x     2x 2x   4x   6x       20x       16x                 15x                     14x                          
'use client'
 
import { useState, useCallback } from 'react'
import { VocabularyItem } from '@/core/domain/VocabularyItem'
import { useQuiz } from '@/hooks/useQuiz'
import { MemorizationPhase } from './MemorizationPhase'
import { QuizPhase } from './QuizPhase'
import { ResultsPhase } from './ResultsPhase'
import { LoadingSpinner, ErrorMessage } from '@/components/ui'
 
interface VocabularyAppProps {
  initialVocabulary: VocabularyItem[]
}
 
/**
 * VocabularyApp Component
 * Main application component managing the vocabulary learning flow.
 */
export function VocabularyApp({ initialVocabulary }: VocabularyAppProps) {
  const [vocabulary, setVocabulary] = useState(initialVocabulary)
  const [isLoading, setIsLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
 
  const {
    phase,
    session,
    currentQuestion,
    shuffledOptions,
    resultMessage,
    startQuiz,
    submitAnswer,
    resetQuiz,
  } = useQuiz(vocabulary)
 
  const handleTryAgain = useCallback(async () => {
    setIsLoading(true)
    setError(null)
 
    try {
      const response = await fetch('/api/vocabulary')
      const data = await response.json()
 
      if (!response.ok) {
        throw new Error(data.error || 'Failed to fetch vocabulary')
      }
 
      setVocabulary(data.data)
      resetQuiz()
    } catch (err) {
      setError(err instanceof Error ? err.message : 'An error occurred')
    } finally {
      setIsLoading(false)
    }
  }, [resetQuiz])
 
  if (error) {
    return <ErrorMessage message={error} onRetry={handleTryAgain} />
  }
 
  if (phase === 'memorization') {
    return (
      <MemorizationPhase
        vocabularyItems={vocabulary}
        onStartQuiz={startQuiz}
      />
    )
  }
 
  if (phase === 'quiz' && session && currentQuestion) {
    return (
      <QuizPhase
        session={session}
        currentQuestion={currentQuestion}
        shuffledOptions={shuffledOptions}
        onAnswer={submitAnswer}
      />
    )
  }
 
  if (phase === 'results' && session) {
    return (
      <ResultsPhase
        session={session}
        resultMessage={resultMessage}
        onTryAgain={handleTryAgain}
        isLoading={isLoading}
      />
    )
  }
 
  return <LoadingSpinner message="Loading quiz..." />
}