'use client'; import { useEffect, useState, useMemo } from 'react'; import { useParams, useRouter } from 'next/navigation'; import { ArrowLeft } from 'lucide-react'; import Header from '@/components/Header'; import { useTranslation } from '@/lib/i18n/useTranslation'; import { SupportedLanguage } from '@/lib/i18n/translations'; import { OpeningMetadata } from '@/lib/openings'; import { OpeningTrainingProvider } from '@/contexts/OpeningTrainingContext'; import OpeningTrainer from '@/components/OpeningTrainer/OpeningTrainer'; import { OpeningTrainerErrorBoundary } from '@/components/OpeningTrainer/ErrorBoundary'; import { getOpeningsByFamily } from '@/lib/openingTrainer/openingLoader'; import { buildVariationTree, VariationTree } from '@/lib/openingTrainer/gameLogic'; import { Personality, PERSONALITIES } from '@/lib/personalities'; /** * Family Training Page * * This page enables training on an entire opening family (e.g., "Italian Game") * instead of a single specific variation. Users can play any moves that exist * in any variation, and the tutor will guide them through the repertoire. */ export default function FamilyTrainingPage() { const params = useParams(); const router = useRouter(); const familyName = decodeURIComponent(params.familyName as string); const [language, setLanguage] = useState('en'); const [mounted, setMounted] = useState(false); const [variations, setVariations] = useState([]); const [variationTree, setVariationTree] = useState(null); const [isLoading, setIsLoading] = useState(true); const [selectedPersonality, setSelectedPersonality] = useState(PERSONALITIES[0]); const [apiKey, setApiKey] = useState(''); useEffect(() => { const storedLang = localStorage.getItem('chess_tutor_language'); if (storedLang) setLanguage(storedLang as SupportedLanguage); // Load API key const storedApiKey = localStorage.getItem('gemini_api_key'); if (storedApiKey) setApiKey(storedApiKey); // Load personality const storedPersonalityId = localStorage.getItem('chess_tutor_personality'); if (storedPersonalityId) { const personality = PERSONALITIES.find(p => p.id === storedPersonalityId); if (personality) setSelectedPersonality(personality); } setMounted(true); }, []); const t = useTranslation(language); useEffect(() => { if (mounted) { loadFamilyVariations(); } }, [familyName, mounted]); const loadFamilyVariations = () => { setIsLoading(true); // Get all variations for this family const familyVariations = getOpeningsByFamily(familyName); if (familyVariations.length === 0) { // No variations found - redirect back to selection router.push('/learning/openings'); return; } setVariations(familyVariations); // Build the variation tree for efficient lookup const tree = buildVariationTree(familyVariations, familyName); setVariationTree(tree); setIsLoading(false); }; // Create a "representative" opening for the family // Uses the first ECO code and combines info from all variations const familyOpening: OpeningMetadata | null = useMemo(() => { if (variations.length === 0) return null; // Get all unique ECO codes const ecoCodes = [...new Set(variations.map((v: OpeningMetadata) => v.eco))].sort(); const ecoRange = ecoCodes.length === 1 ? ecoCodes[0] : `${ecoCodes[0]}-${ecoCodes[ecoCodes.length - 1]}`; // Find the variation with the most moves (for the initial repertoire display) const longestVariation = variations[0]; // Already sorted by move count // Create a combined opening metadata return { eco: longestVariation.eco, name: familyName, moves: longestVariation.moves, // Use longest for display, but tree handles all src: 'family', isEcoRoot: true, wikipediaSlug: longestVariation.wikipediaSlug, }; }, [variations, familyName]); if (!mounted) return null; if (isLoading) { return ( <>

{t.learning.openingTrainer.loadingSession}

); } if (!familyOpening || !variationTree) { return ( <>

{t.learning.openingTrainer.openingNotFound}

No variations found for "{familyName}"

); } return ( <>
{/* Header */}

{familyName}

{variations.length} variation{variations.length !== 1 ? 's' : ''} available

); }