import { useEffect, useMemo, useState } from 'preact/hooks'; import { MindforgeApiService, type FlashcardCard, type FlashcardLibrarySummary, } from '../services/MindforgeApiService'; import { Button } from './Button'; import './FlashcardReviewComponent.css'; function groupLibrariesBySubject(libraries: FlashcardLibrarySummary[]) { const grouped: Record = {}; libraries.forEach((library) => { const subject = library.subject || 'Geral'; if (!grouped[subject]) { grouped[subject] = []; } grouped[subject].push(library); }); return Object.entries(grouped).sort(([a], [b]) => a.localeCompare(b)); } function difficultyLabel(difficulty: string) { return difficulty === 'Hard' ? 'Dificil' : 'Facil'; } function shuffleCards(cards: FlashcardCard[]) { const shuffled = [...cards]; for (let i = shuffled.length - 1; i > 0; i--) { const randomIndex = Math.floor(Math.random() * (i + 1)); [shuffled[i], shuffled[randomIndex]] = [shuffled[randomIndex], shuffled[i]]; } return shuffled; } export function FlashcardReviewComponent() { const [libraries, setLibraries] = useState([]); const [selectedLibraryIds, setSelectedLibraryIds] = useState([]); const [loadingLibraries, setLoadingLibraries] = useState(true); const [loadingSession, setLoadingSession] = useState(false); const [error, setError] = useState(null); const [sessionCards, setSessionCards] = useState([]); const [currentIndex, setCurrentIndex] = useState(0); const [showAnswer, setShowAnswer] = useState(false); const [submittingAnswer, setSubmittingAnswer] = useState(false); useEffect(() => { let cancelled = false; async function loadLibraries() { setLoadingLibraries(true); setError(null); try { const result = await MindforgeApiService.getFlashcardLibraries(); if (!cancelled) { setLibraries(result); } } catch (err: any) { if (!cancelled) { setError(err?.message || 'Falha ao carregar bibliotecas de flashcards.'); } } finally { if (!cancelled) { setLoadingLibraries(false); } } } loadLibraries(); return () => { cancelled = true; }; }, []); const groupedLibraries = useMemo(() => groupLibrariesBySubject(libraries), [libraries]); const libraryById = useMemo(() => { return new Map(libraries.map((library) => [library.id, library])); }, [libraries]); const currentCard = sessionCards[currentIndex]; const progressPercent = sessionCards.length > 0 ? ((currentIndex + 1) / sessionCards.length) * 100 : 0; const toggleLibrary = (libraryId: number) => { if (selectedLibraryIds.includes(libraryId)) { setSelectedLibraryIds(selectedLibraryIds.filter((id) => id !== libraryId)); return; } setSelectedLibraryIds([...selectedLibraryIds, libraryId]); }; const startReviewSession = async () => { if (selectedLibraryIds.length === 0) { setError('Selecione ao menos uma biblioteca para iniciar a revisao.'); return; } setLoadingSession(true); setError(null); try { const response = await MindforgeApiService.createFlashcardReviewSession({ libraryIds: selectedLibraryIds, }); setSessionCards(shuffleCards(response.cards)); setCurrentIndex(0); setShowAnswer(false); } catch (err: any) { setError(err?.message || 'Falha ao iniciar sessao de revisao.'); } finally { setLoadingSession(false); } }; const endSession = () => { setSessionCards([]); setCurrentIndex(0); setShowAnswer(false); setSubmittingAnswer(false); }; const goToPrevious = () => { if (currentIndex === 0) { return; } setCurrentIndex(currentIndex - 1); setShowAnswer(false); }; const registerReviewAnswer = async (correct: boolean) => { if (!currentCard) { return; } setSubmittingAnswer(true); setError(null); try { await MindforgeApiService.recordFlashcardReviewAnswer({ cardId: currentCard.id, correct, }); if (currentIndex >= sessionCards.length - 1) { endSession(); return; } setCurrentIndex(currentIndex + 1); setShowAnswer(false); } catch (err: any) { setError(err?.message || 'Falha ao registrar resposta da revisao.'); } finally { setSubmittingAnswer(false); } }; return (

Revisao Flashcards

Escolha as bibliotecas para estudar e inicie uma sessao de revisao.

{error &&
{error}
} {sessionCards.length === 0 && (
{loadingLibraries &&

Carregando bibliotecas...

} {!loadingLibraries && libraries.length === 0 && (

Nenhuma biblioteca encontrada. Gere flashcards para comecar.

)} {!loadingLibraries && libraries.length > 0 && (
{groupedLibraries.map(([subject, subjectLibraries]) => (

{subject}

{subjectLibraries.map((library) => ( ))}
))}
)}
)} {sessionCards.length > 0 && currentCard && (
{currentIndex + 1} / {sessionCards.length}
{libraryById.get(currentCard.libraryId)?.fileName || 'Arquivo'} - {' '} {libraryById.get(currentCard.libraryId)?.subject || 'Geral'}

Frente

{currentCard.front}

{showAnswer && ( <>

Verso

{currentCard.back}

)}
{!showAnswer && ( )} {showAnswer && ( <> )}
)}
); }