import { useState } from "react"; import { CheckCircle2, RotateCcw, ChevronRight } from "lucide-react"; export interface VocabOption { id: string; definition: string; isCorrect: boolean; elimReason: string; // why wrong (for eliminated options) or why right (for correct option) } export interface VocabExercise { sentence: string; word: string; // the target word — will be highlighted question: string; options: VocabOption[]; } interface ContextEliminationWidgetProps { exercises: VocabExercise[]; accentColor?: string; } export default function ContextEliminationWidget({ exercises, accentColor = "rose", }: ContextEliminationWidgetProps) { const [activeEx, setActiveEx] = useState(0); const [eliminated, setEliminated] = useState>(new Set()); const [revealed, setRevealed] = useState(false); const [triedCorrect, setTriedCorrect] = useState(false); const exercise = exercises[activeEx]; const wrongIds = exercise.options .filter((o) => !o.isCorrect) .map((o) => o.id); const eliminate = (id: string) => { const opt = exercise.options.find((o) => o.id === id)!; if (opt.isCorrect) { setTriedCorrect(true); setTimeout(() => setTriedCorrect(false), 1500); } else { const newElim = new Set([...eliminated, id]); setEliminated(newElim); if (wrongIds.every((wid) => newElim.has(wid))) { setRevealed(true); } } }; const reset = () => { setEliminated(new Set()); setRevealed(false); setTriedCorrect(false); }; const switchEx = (i: number) => { setActiveEx(i); setEliminated(new Set()); setRevealed(false); setTriedCorrect(false); }; // Highlight the target word in the sentence const renderSentence = () => { const idx = exercise.sentence .toLowerCase() .indexOf(exercise.word.toLowerCase()); if (idx === -1) return <>{exercise.sentence}; return ( <> {exercise.sentence.slice(0, idx)} {exercise.sentence.slice(idx, idx + exercise.word.length)} {exercise.sentence.slice(idx + exercise.word.length)} ); }; return (
{/* Tab strip */} {exercises.length > 1 && (
{exercises.map((_, i) => ( ))}
)} {/* Sentence in context */}

Sentence in Context

{renderSentence()}

{/* Question + instruction */}

{exercise.question}

{revealed ? "You found it! The correct definition is highlighted." : 'Click "Eliminate" on definitions that don\'t fit the context. Work by elimination.'}

{/* Tried to eliminate correct option flash */} {triedCorrect && (
Can't eliminate that one — it fits the context too well!
)} {/* Options */}
{exercise.options.map((opt) => { const isElim = eliminated.has(opt.id); const isAnswer = opt.isCorrect && revealed; let wrapCls = "border-gray-200 bg-white"; if (isAnswer) wrapCls = "border-green-400 bg-green-50"; else if (isElim) wrapCls = "border-gray-100 bg-gray-50"; return (
{opt.id}.

{opt.definition}

{isElim && (

{opt.elimReason}

)} {isAnswer && (

✓ {opt.elimReason}

)}
{isAnswer && ( )} {!isElim && !isAnswer && !revealed && ( )}
); })}
{revealed && activeEx < exercises.length - 1 && ( )}
); }