Files
flashcards/packages/frontend/src/pages/Practice.tsx

76 lines
2.5 KiB
TypeScript

import { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import type { Card } from '@flashcard/shared';
import { cardsApi } from '../api/cards.js';
import { sessionsApi } from '../api/sessions.js';
import { useSession } from '../stores/sessionStore.js';
import { Flashcard } from '../components/Flashcard.js';
export function PracticePage() {
const { lessonId } = useParams();
const { session, current, done, showAnswer, reveal, answer, end } = useSession();
const navigate = useNavigate();
const [card, setCard] = useState<Card | null>(null);
useEffect(() => {
if (useSession.getState().session) return;
(async () => {
const active = await sessionsApi.active();
if (!active || String(active.lessonId) !== lessonId) return;
const nx = await sessionsApi.next(active.id);
useSession.setState({
session: active,
current: nx.done ? null : nx.item,
done: nx.done,
showAnswer: false,
shownAt: Date.now(),
});
})();
}, [lessonId]);
useEffect(() => {
if (session) return;
const t = setTimeout(async () => {
if (useSession.getState().session) return;
const active = await sessionsApi.active();
if (!active || String(active.lessonId) !== lessonId) {
navigate(`/practice/${lessonId}/setup`);
}
}, 50);
return () => clearTimeout(t);
}, [session, lessonId, navigate]);
useEffect(() => {
let cancel = false;
(async () => {
if (!current) { setCard(null); return; }
const c = await cardsApi.get(current.cardId);
if (!cancel) setCard(c);
})();
return () => { cancel = true; };
}, [current]);
useEffect(() => {
if (done && session) { (async () => { await end(); navigate(`/practice/${lessonId}/done`); })(); }
}, [done, session, end, navigate, lessonId]);
if (!current || !card) return <div className="p-6 text-center">Laden...</div>;
const isReverse = current.direction === 'backward';
return (
<div className="flex h-full flex-col">
<div className="mx-auto w-full max-w-2xl p-6">
<div className="mb-2 text-xs text-slate-500">{session?.cardsShown ?? 0} kaarten behandeld</div>
<Flashcard
question={isReverse ? card.answer : card.question}
answer={isReverse ? card.question : card.answer}
hint={card.hint}
showAnswer={showAnswer}
onReveal={reveal}
onAnswer={(r) => answer(r)}
/>
</div>
</div>
);
}