84 lines
3.2 KiB
TypeScript
84 lines
3.2 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import type { QuizContent } from '@/lib/types/stage';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Button } from '@/components/ui/button';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
interface QuizRendererProps {
|
|
readonly content: QuizContent;
|
|
readonly mode: 'autonomous' | 'playback';
|
|
readonly sceneId: string;
|
|
}
|
|
|
|
export function QuizRenderer({ content, mode, sceneId: _sceneId }: QuizRendererProps) {
|
|
const [answers, setAnswers] = useState<Record<string, string>>({});
|
|
|
|
const handleAnswerChange = (questionId: string, answer: string) => {
|
|
setAnswers((prev) => ({ ...prev, [questionId]: answer }));
|
|
};
|
|
|
|
return (
|
|
<div className="w-full h-full overflow-y-auto p-8">
|
|
<div className="max-w-3xl mx-auto space-y-6">
|
|
<h1 className="text-3xl font-bold">Quiz</h1>
|
|
{content.questions.map((question) => (
|
|
<Card key={question.id}>
|
|
<CardHeader>
|
|
<CardTitle>{question.question}</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{question.type === 'single' && question.options && (
|
|
<div className="space-y-2">
|
|
{question.options.map((option, optIndex) => {
|
|
// Normalize: options may be QuizOption objects or plain strings from AI
|
|
const optionValue = typeof option === 'string' ? option : option.value;
|
|
const optionLabel = typeof option === 'string' ? option : option.label;
|
|
const letterPrefix = String.fromCharCode(65 + optIndex); // A, B, C, D...
|
|
|
|
return (
|
|
<label
|
|
key={`${question.id}-opt-${optIndex}`}
|
|
className={cn(
|
|
'flex items-center space-x-2 p-2 rounded cursor-pointer hover:bg-muted',
|
|
answers[question.id] === (optionValue || letterPrefix) && 'bg-muted',
|
|
)}
|
|
>
|
|
<input
|
|
type="radio"
|
|
name={question.id}
|
|
value={optionValue || letterPrefix}
|
|
checked={answers[question.id] === (optionValue || letterPrefix)}
|
|
onChange={(e) => handleAnswerChange(question.id, e.target.value)}
|
|
className="size-4"
|
|
/>
|
|
<span>
|
|
{letterPrefix}. {optionLabel}
|
|
</span>
|
|
</label>
|
|
);
|
|
})}
|
|
</div>
|
|
)}
|
|
{question.type === 'short_answer' && (
|
|
<textarea
|
|
className="w-full min-h-24 p-2 border rounded"
|
|
placeholder="Enter your answer..."
|
|
value={answers[question.id] || ''}
|
|
onChange={(e) => handleAnswerChange(question.id, e.target.value)}
|
|
/>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
{mode === 'autonomous' && (
|
|
<div className="flex justify-end">
|
|
<Button>Submit Answers</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|