"use client"; import { closestCenter, DndContext, type DragEndEvent, DragOverlay, type DragStartEvent, KeyboardSensor, PointerSensor, useSensor, useSensors, } from "@dnd-kit/core"; import { arrayMove, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy, } from "@dnd-kit/sortable"; import { Button, Card, CardContent, CardHeader, Input, Textarea, } from "@mdxui/primitives"; import { cn } from "@mdxui/primitives/lib/utils"; import { Plus, Settings } from "lucide-react"; import * as React from "react"; import { QuestionItem } from "./question-item"; import { QuestionTypeSelector } from "./question-type-selector"; import type { QuestionType, Survey, SurveyBuilderProps, SurveyQuestion, } from "./types"; export function SurveyBuilder({ survey: initialSurvey, onChange, onQuestionSelect, readOnly = false, className, }: SurveyBuilderProps) { const [survey, setSurvey] = React.useState( initialSurvey || { id: crypto.randomUUID(), title: "Untitled Survey", description: "", questions: [], settings: { showProgressBar: true, allowBack: true, randomizeQuestions: false, }, }, ); const [activeQuestion, setActiveQuestion] = React.useState(null); React.useEffect(() => { if (initialSurvey) { setSurvey(initialSurvey); } }, [initialSurvey]); React.useEffect(() => { onChange?.(survey); }, [survey, onChange]); const sensors = useSensors( useSensor(PointerSensor, { activationConstraint: { distance: 8, }, }), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates, }), ); const handleDragStart = (event: DragStartEvent) => { const { active } = event; const question = survey.questions.find((q) => q.id === active.id); if (question) { setActiveQuestion(question); } }; const handleDragEnd = (event: DragEndEvent) => { const { active, over } = event; setActiveQuestion(null); if (!over || active.id === over.id) return; setSurvey((prev) => { const oldIndex = prev.questions.findIndex((q) => q.id === active.id); const newIndex = prev.questions.findIndex((q) => q.id === over.id); return { ...prev, questions: arrayMove(prev.questions, oldIndex, newIndex), }; }); }; const handleAddQuestion = (type: QuestionType) => { const newQuestion: SurveyQuestion = { id: crypto.randomUUID(), type, title: "Untitled Question", description: "", required: false, ...(type === "single-choice" || type === "multiple-choice" ? { options: [ { id: crypto.randomUUID(), label: "Option 1", value: "option-1" }, { id: crypto.randomUUID(), label: "Option 2", value: "option-2" }, ], } : {}), }; setSurvey((prev) => ({ ...prev, questions: [...prev.questions, newQuestion], })); }; const handleUpdateQuestion = ( questionId: string, updates: Partial, ) => { setSurvey((prev) => ({ ...prev, questions: prev.questions.map((q) => q.id === questionId ? { ...q, ...updates } : q, ), })); }; const handleDeleteQuestion = (questionId: string) => { setSurvey((prev) => ({ ...prev, questions: prev.questions.filter((q) => q.id !== questionId), })); }; const handleDuplicateQuestion = (questionId: string) => { const question = survey.questions.find((q) => q.id === questionId); if (!question) return; const duplicated: SurveyQuestion = { ...question, id: crypto.randomUUID(), title: `${question.title} (Copy)`, options: question.options?.map((opt) => ({ ...opt, id: crypto.randomUUID(), })), }; setSurvey((prev) => ({ ...prev, questions: [...prev.questions, duplicated], })); }; const handleTitleChange = (title: string) => { setSurvey((prev) => ({ ...prev, title })); }; const handleDescriptionChange = (description: string) => { setSurvey((prev) => ({ ...prev, description })); }; return (
handleTitleChange(e.target.value)} placeholder="Survey Title" className="text-2xl font-bold" disabled={readOnly} />