diff --git a/frontend/src/features/quiz/QuestionCard.tsx b/frontend/src/features/quiz/QuestionCard.tsx
index 117079f..3f7213e 100644
--- a/frontend/src/features/quiz/QuestionCard.tsx
+++ b/frontend/src/features/quiz/QuestionCard.tsx
@@ -10,6 +10,7 @@ interface QuestionCardProps {
currentStep: number;
totalSteps: number;
explanation?: string;
+ isValidated: boolean; // New prop
}
export function QuestionCard({
@@ -20,24 +21,22 @@ export function QuestionCard({
onSelectOption,
currentStep,
totalSteps,
- explanation
+ explanation,
+ isValidated // Destructure new prop
}: QuestionCardProps) {
const [animation, setAnimation] = useState<'pop' | 'shake' | null>(null);
useEffect(() => {
- if (selectedOption !== null) {
+ if (isValidated && selectedOption !== null) {
if (selectedOption === correctAnswer) {
setAnimation('pop');
} else {
setAnimation('shake');
}
- // Removed auto-hide timer for animation to keep state clear,
- // but we might want to keep the effect.
- // The user wants "time to read", so we shouldn't auto-advance too fast in parent.
const timer = setTimeout(() => setAnimation(null), 500);
return () => clearTimeout(timer);
}
- }, [selectedOption, correctAnswer]);
+ }, [isValidated, selectedOption, correctAnswer]); // Trigger on validation
const isCorrect = selectedOption === correctAnswer;
@@ -60,42 +59,69 @@ export function QuestionCard({
{question}
- {options.map((option, index) => (
-
- ))}
+ {options.map((option, index) => {
+ // Logic for visual states
+ let borderClass = 'border-slate-100 dark:border-slate-700';
+ let bgClass = 'hover:bg-indigo-50/30 dark:hover:bg-indigo-900/20';
+ let textClass = '';
+ let opacityClass = '';
+
+ if (selectedOption === index) {
+ if (!isValidated) {
+ // Selected but not validated: Blue/Neutral
+ borderClass = 'border-indigo-500 dark:border-indigo-400';
+ bgClass = 'bg-indigo-50 dark:bg-indigo-900/20';
+ textClass = 'text-indigo-700 dark:text-indigo-300';
+ } else {
+ // Validated: Green or Red
+ if (index === correctAnswer) {
+ borderClass = 'border-green-500';
+ bgClass = 'bg-green-50 dark:bg-green-900/20';
+ textClass = 'text-green-700 dark:text-green-400';
+ } else {
+ borderClass = 'border-orange-400';
+ bgClass = 'bg-orange-50 dark:bg-orange-900/20';
+ textClass = 'text-orange-700 dark:text-orange-400';
+ }
+ }
+ } else if (isValidated && index === correctAnswer) {
+ // Show correct answer if user got it wrong
+ borderClass = 'border-green-500';
+ bgClass = 'bg-green-50/50 dark:bg-green-900/10';
+ textClass = 'text-green-700 dark:text-green-400';
+ } else if (isValidated) {
+ // Fade out other options when validated
+ opacityClass = 'opacity-50';
+ }
+
+ return (
+
+ );
+ })}
- {selectedOption !== null && (
+ {isValidated && selectedOption !== null && (
diff --git a/frontend/src/features/quiz/QuizPage.tsx b/frontend/src/features/quiz/QuizPage.tsx
index b3d9b2d..e11c586 100644
--- a/frontend/src/features/quiz/QuizPage.tsx
+++ b/frontend/src/features/quiz/QuizPage.tsx
@@ -37,6 +37,7 @@ export function QuizPage() {
const [quizData, setQuizData] = useState
(null);
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
const [selectedOption, setSelectedOption] = useState(null);
+ const [isValidated, setIsValidated] = useState(false); // New state for validation
const [score, setScore] = useState(0);
const [answers, setAnswers] = useState([]); // Track details
const [isFinished, setIsFinished] = useState(false);
@@ -129,19 +130,26 @@ export function QuizPage() {
if (currentQuestionIndex < (quizData?.questions.length || 0) - 1) {
setCurrentQuestionIndex(prev => prev + 1);
setSelectedOption(null);
+ setIsValidated(false); // Reset validation for next question
} else {
setIsFinished(true);
}
};
+ // Change: Selected option just updates state, doesn't lock yet
const handleOptionSelect = (index: number) => {
- if (selectedOption !== null) return; // Prevent changing answer
+ if (isValidated) return; // Prevent changing answer if already validated
setSelectedOption(index);
+ };
- if (!quizData) return;
+ // New: Validate the answer
+ const handleValidate = () => {
+ if (selectedOption === null || isValidated || !quizData) return;
+
+ setIsValidated(true);
const currentQ = quizData.questions[currentQuestionIndex];
- const isCorrect = index === currentQ.correct_answer;
+ const isCorrect = selectedOption === currentQ.correct_answer;
if (isCorrect) {
setScore(prev => prev + 1);
@@ -150,7 +158,7 @@ export function QuizPage() {
// Record answer details
setAnswers(prev => [...prev, {
question: currentQ.question,
- user_answer: currentQ.options[index],
+ user_answer: currentQ.options[selectedOption],
correct_answer: currentQ.options[currentQ.correct_answer],
is_correct: isCorrect,
original_content: null
@@ -311,13 +319,25 @@ export function QuizPage() {
currentStep={currentQuestionIndex + 1}
totalSteps={quizData.questions.length}
explanation={quizData.questions[currentQuestionIndex].explanation}
+ isValidated={isValidated} // Pass validation state
/>
- {/* NEXT BUTTON */}
- {selectedOption !== null && (
+ {/* VALIDATE BUTTON */}
+ {selectedOption !== null && !isValidated && (
+
+ )}
+
+ {/* NEXT BUTTON (Only show after validation) */}
+ {isValidated && (