"use client"; import { motion, useReducedMotion } from "framer-motion"; import { useState } from "react"; import { useI18n } from "@/lib/i18n"; import type { Activity } from "@/lib/schemas"; import { Button } from "@/components/ui"; import { ActivityHeader, FeedbackPanel, Hint, PromptCard, QuestionText, type ActivityComponentProps, } from "./shared"; type FlashcardActivity = Extract; export function Flashcard({ activity, onAnswered, onNext, isLast, nextLabel }: ActivityComponentProps) { const { t } = useI18n(); const reduceMotion = useReducedMotion(); const [flipped, setFlipped] = useState(false); const [result, setResult] = useState(null); /** * Which face is painted. The swap happens at the 90° edge-on moment instead * of relying on backface-visibility: a backdrop-filter layer (the card * glass) keeps rendering its backface on some GPU/compositing paths, which * showed the question mirrored over the answer. */ const [face, setFace] = useState<"front" | "back">("front"); const showFaceFor = (angle: number) => { const next = angle > 90 && angle < 270 ? "back" : "front"; setFace((current) => (current === next ? current : next)); }; const settle = (correct: boolean) => { if (result !== null) return; setResult(correct); onAnswered(correct); }; return ( <> {flipped ? t("flashcard.didYouKnow") : t("flashcard.tapToFlip")} {flipped && result === null ? (
) : null} {result !== null ? ( ) : null} ); }