sto-k-odnomu/admin/src/components/TestQuestionsManager.tsx
2026-01-06 23:12:36 +03:00

183 lines
6 KiB
TypeScript

import { useState } from 'react'
import type { Question } from '@/types/questions'
import { QuestionType, isInputButtonsQuestion } from '@/types/questions'
import { Card, CardContent } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Edit, Trash2, FileText, Type } from 'lucide-react'
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog'
interface TestQuestionsManagerProps {
questions: Question[]
onChange: (questions: Question[]) => void
onEdit: (question: Question, index: number) => void
disabled?: boolean
}
export function TestQuestionsManager({
questions,
onChange,
onEdit,
disabled = false,
}: TestQuestionsManagerProps) {
const [questionToDelete, setQuestionToDelete] = useState<{
question: Question
index: number
} | null>(null)
const handleDelete = (question: Question, index: number) => {
setQuestionToDelete({ question, index })
}
const confirmDelete = () => {
if (questionToDelete) {
const newQuestions = questions.filter((_, i) => i !== questionToDelete.index)
onChange(newQuestions)
setQuestionToDelete(null)
}
}
const getQuestionPreview = (question: Question): string => {
if (question.text) return question.text
if (question.image) return '📷 Image question'
return `Word: ${question.word}`
}
const getQuestionTypeLabel = (type: QuestionType): string => {
switch (type) {
case QuestionType.SIMPLE:
return 'Simple'
case QuestionType.INPUT_BUTTONS:
return 'Input Buttons'
default:
return type
}
}
const getQuestionTypeColor = (type: QuestionType): string => {
switch (type) {
case QuestionType.SIMPLE:
return 'bg-blue-500'
case QuestionType.INPUT_BUTTONS:
return 'bg-green-500'
default:
return 'bg-gray-500'
}
}
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<h3 className="text-lg font-semibold">Questions</h3>
<p className="text-sm text-muted-foreground">
{questions.length} question{questions.length !== 1 ? 's' : ''} in this test
</p>
</div>
</div>
{questions.length === 0 ? (
<Card>
<CardContent className="pt-6">
<div className="text-center py-8">
<FileText className="mx-auto h-12 w-12 text-muted-foreground mb-4" />
<p className="text-sm text-muted-foreground">
No questions yet. Add your first question to get started.
</p>
</div>
</CardContent>
</Card>
) : (
<div className="space-y-3">
{questions.map((question, index) => (
<Card key={question.id || index}>
<CardContent className="pt-6">
<div className="flex items-start justify-between">
<div className="flex-1 space-y-2">
<div className="flex items-center gap-2">
<Badge
className={`${getQuestionTypeColor(
question.questionType,
)} text-white border-transparent`}
>
<Type className="h-3 w-3 mr-1" />
{getQuestionTypeLabel(question.questionType)}
</Badge>
<span className="text-sm text-muted-foreground">
#{index + 1}
</span>
</div>
<div>
<p className="font-medium">{question.word}</p>
<p className="text-sm text-muted-foreground">
{getQuestionPreview(question)}
</p>
</div>
<div className="flex items-center gap-2 text-xs text-muted-foreground">
<span>{question.options.length} option(s)</span>
{isInputButtonsQuestion(question) && (
<span> Template: {question.template}</span>
)}
</div>
</div>
<div className="flex items-center gap-2 ml-4">
<Button
variant="ghost"
size="sm"
onClick={() => onEdit(question, index)}
disabled={disabled}
>
<Edit className="h-4 w-4" />
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => handleDelete(question, index)}
disabled={disabled}
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</div>
</CardContent>
</Card>
))}
</div>
)}
{/* Delete Confirmation Dialog */}
<AlertDialog
open={questionToDelete !== null}
onOpenChange={(open) => !open && setQuestionToDelete(null)}
>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete Question</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete this question? This action cannot be
undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={confirmDelete}
className="bg-red-600 hover:bg-red-700"
>
Delete
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
)
}