1
0
mirror of https://github.com/kamranahmedse/developer-roadmap.git synced 2025-09-01 13:22:38 +02:00
This commit is contained in:
Arik Chakma
2025-07-01 21:57:29 +06:00
parent 38c9a67a2a
commit 0f9d3af6ae
2 changed files with 110 additions and 8 deletions

View File

@@ -1,4 +1,7 @@
import type { QuizQuestion } from '../../queries/ai-quiz';
import { useState } from 'react';
import { cn } from '../../lib/classname';
import { CheckIcon, XIcon, InfoIcon } from 'lucide-react';
type AIMCQQuestionProps = {
question: QuizQuestion;
@@ -6,16 +9,115 @@ type AIMCQQuestionProps = {
export function AIMCQQuestion(props: AIMCQQuestionProps) {
const { question } = props;
const { title: questionText, options } = question;
const { title: questionText, options, answerExplanation } = question;
const [selectedOptions, setSelectedOptions] = useState<number[]>([]);
const [isSubmitted, setIsSubmitted] = useState(false);
const canSubmitMultipleAnswers =
options.filter((option) => option.isCorrect).length > 1;
const handleSelectOption = (index: number) => {
if (!canSubmitMultipleAnswers) {
setSelectedOptions((prev) => (prev.includes(index) ? [] : [index]));
return;
}
setSelectedOptions((prev) => {
if (prev.includes(index)) {
return prev.filter((id) => id !== index);
}
return [...prev, index];
});
};
const handleSubmit = () => {
setIsSubmitted(true);
};
const canSubmit = selectedOptions.length > 0;
return (
<div>
<h3 className="text-3xl font-medium">{questionText}</h3>
<div className="mt-4">
{options.map((option) => (
<div key={option.id}>{option.title}</div>
))}
<h3 className="text-4xl font-medium">{questionText}</h3>
<div className="mt-6 space-y-3">
{options.map((option, index) => {
const isSelected = selectedOptions.includes(index);
const showCorrectness = isSubmitted && isSelected;
const isCorrectOption = option.isCorrect;
const isSelectedAndCorrect =
isSubmitted && isSelected && isCorrectOption;
const isSelectedAndIncorrect =
isSubmitted && isSelected && !isCorrectOption;
const isNotSelectedAndCorrect =
isSubmitted && !isSelected && isCorrectOption;
return (
<button
key={option.id}
className={cn(
'flex w-full items-start gap-2 rounded-xl border border-gray-200 p-2 text-lg hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50',
isSelected && !isSubmitted && 'border-gray-400 bg-gray-50',
isSubmitted &&
isSelectedAndCorrect &&
'border-green-500 bg-green-50',
isSubmitted &&
isSelectedAndIncorrect &&
'border-red-500 bg-red-50',
isSubmitted &&
isNotSelectedAndCorrect &&
'border-green-500 bg-green-50',
)}
onClick={() => handleSelectOption(index)}
disabled={isSubmitted && !isSelected && !isCorrectOption}
>
<div
className={cn(
'flex size-7 shrink-0 items-center justify-center rounded-lg border border-gray-200',
isSelected &&
!isSubmitted &&
'border-black bg-black text-white',
isSelectedAndCorrect &&
'border-green-500 bg-green-500 text-white',
isSelectedAndIncorrect &&
'border-red-500 bg-red-500 text-white',
isNotSelectedAndCorrect &&
'border-green-500 bg-green-500 text-white',
)}
>
{isSelected && !isSubmitted && <CheckIcon className="size-4" />}
{isSelectedAndCorrect && <CheckIcon className="size-4" />}
{isSelectedAndIncorrect && <XIcon className="size-4" />}
{isNotSelectedAndCorrect && <CheckIcon className="size-4" />}
</div>
<p className="text-left">{option.title}</p>
</button>
);
})}
</div>
{isSubmitted && (
<div className="mt-4 rounded-xl bg-gray-100 p-4">
<p className="flex items-center gap-2 text-lg text-gray-600">
<InfoIcon className="size-4" />
Explanation
</p>
<p className="mt-1">{answerExplanation}</p>
</div>
)}
<button
className={cn(
'mt-4 rounded-xl bg-black px-4 py-2 text-white hover:bg-gray-900 disabled:opacity-70',
)}
onClick={handleSubmit}
disabled={!canSubmit}
>
Submit Answer
</button>
</div>
);
}

View File

@@ -22,8 +22,8 @@ export function AIQuizContent(props: AIQuizContentProps) {
const hasPreviousQuestions = activeQuestionIndex > 0;
return (
<div className="py-10">
<div className="mb-4 flex items-center gap-3">
<div className="mx-auto w-full max-w-lg py-10">
<div className="mb-10 flex items-center gap-3">
<NavigationButton
disabled={!hasPreviousQuestions}
onClick={() => setActiveQuestionIndex(activeQuestionIndex - 1)}