generated from muhtadeetaron/nextjs-template
115 lines
3.6 KiB
TypeScript
115 lines
3.6 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
import { Question, Answer } from "@/types/exam";
|
|
import { Bookmark } from "lucide-react";
|
|
|
|
interface QuestionItemProps {
|
|
question: Question;
|
|
index: number;
|
|
selectedAnswer: Answer;
|
|
onSelect: (answer: Answer) => void;
|
|
userAnswer?: Answer; // new
|
|
correctAnswer?: Answer; // new
|
|
showResults?: boolean; // control whether to highlight or not
|
|
}
|
|
|
|
const letters = ["A", "B", "C", "D"]; // extend if needed
|
|
|
|
const QuestionItem: React.FC<QuestionItemProps> = ({
|
|
question,
|
|
index,
|
|
selectedAnswer,
|
|
onSelect,
|
|
userAnswer,
|
|
correctAnswer,
|
|
showResults = false,
|
|
}) => {
|
|
return (
|
|
<div className="border border-blue-100 p-6 bg-slate-100 rounded-3xl mb-6">
|
|
<p className="text-lg font-semibold mb-3">
|
|
{index + 1}. {question.question}
|
|
</p>
|
|
|
|
{!showResults && (
|
|
<div className="w-full flex justify-between">
|
|
<div></div>
|
|
<Bookmark size={24} />
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex flex-col gap-3">
|
|
{question.options.map((opt, optIdx) => {
|
|
const isSelected =
|
|
question.type === "Single"
|
|
? selectedAnswer === optIdx
|
|
: Array.isArray(selectedAnswer) &&
|
|
selectedAnswer.includes(optIdx);
|
|
|
|
// ✅ logic for coloring after results
|
|
let btnClasses = "bg-gray-100 text-gray-900 border-gray-400";
|
|
if (isSelected) {
|
|
btnClasses = "bg-blue-600 text-white border-blue-600";
|
|
}
|
|
|
|
if (showResults && correctAnswer !== undefined) {
|
|
if (question.type === "Single") {
|
|
if (userAnswer === optIdx && userAnswer !== correctAnswer) {
|
|
btnClasses = "bg-red-500 text-white border-red-600"; // wrong
|
|
}
|
|
if (correctAnswer === optIdx) {
|
|
btnClasses = "bg-green-500 text-white border-green-600"; // correct
|
|
}
|
|
} else {
|
|
// Multi-select case
|
|
const userSelected =
|
|
Array.isArray(userAnswer) && userAnswer.includes(optIdx);
|
|
const isCorrect =
|
|
Array.isArray(correctAnswer) && correctAnswer.includes(optIdx);
|
|
|
|
if (userSelected && !isCorrect) {
|
|
btnClasses = "bg-red-500 text-white border-red-600";
|
|
}
|
|
if (isCorrect) {
|
|
btnClasses = "bg-green-500 text-white border-green-600";
|
|
}
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div key={optIdx} className="flex items-center gap-3">
|
|
<button
|
|
onClick={() => {
|
|
if (showResults) return; // disable changes in results mode
|
|
if (question.type === "Single") {
|
|
onSelect(optIdx);
|
|
} else {
|
|
let newAnswers = Array.isArray(selectedAnswer)
|
|
? [...selectedAnswer]
|
|
: [];
|
|
if (newAnswers.includes(optIdx)) {
|
|
newAnswers = newAnswers.filter((a) => a !== optIdx);
|
|
} else {
|
|
newAnswers.push(optIdx);
|
|
}
|
|
onSelect(newAnswers);
|
|
}
|
|
}}
|
|
className={`w-7 h-7 rounded-full border font-bold
|
|
flex items-center justify-center
|
|
${btnClasses}
|
|
transition-colors`}
|
|
>
|
|
{letters[optIdx]}
|
|
</button>
|
|
<span className="text-gray-900">{opt}</span>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default QuestionItem;
|