From 648f9db2306af7d0816c055bedac7cdae97b8750 Mon Sep 17 00:00:00 2001 From: Lukas May Date: Wed, 4 Feb 2026 21:52:08 +0100 Subject: [PATCH] feat(19-03): create QuestionForm component - Renders mixed question types from questions array - Submit disabled until all questions answered - onSubmit called with Record mapping questionId to answer --- packages/web/src/components/QuestionForm.tsx | 91 ++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 packages/web/src/components/QuestionForm.tsx diff --git a/packages/web/src/components/QuestionForm.tsx b/packages/web/src/components/QuestionForm.tsx new file mode 100644 index 0000000..f646585 --- /dev/null +++ b/packages/web/src/components/QuestionForm.tsx @@ -0,0 +1,91 @@ +import { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { OptionGroup } from "@/components/OptionGroup"; +import { FreeTextInput } from "@/components/FreeTextInput"; + +interface QuestionFormQuestion { + id: string; + question: string; + options?: Array<{ label: string; description?: string }>; + multiSelect?: boolean; +} + +interface QuestionFormProps { + questions: QuestionFormQuestion[]; + onSubmit: (answers: Record) => void; + onCancel: () => void; + isSubmitting?: boolean; +} + +export function QuestionForm({ + questions, + onSubmit, + onCancel, + isSubmitting = false, +}: QuestionFormProps) { + const [answers, setAnswers] = useState>(() => { + const initial: Record = {}; + for (const q of questions) { + initial[q.id] = ""; + } + return initial; + }); + + function handleAnswerChange(questionId: string, value: string) { + setAnswers((prev) => ({ ...prev, [questionId]: value })); + } + + const allAnswered = questions.every( + (q) => answers[q.id] !== undefined && answers[q.id].trim() !== "" + ); + + function handleSubmit() { + if (allAnswered) { + onSubmit(answers); + } + } + + return ( +
+ {questions.map((q, index) => ( +
+

+ Q{index + 1}: {q.question} +

+ + {q.options && q.options.length > 0 ? ( + handleAnswerChange(q.id, value)} + /> + ) : ( + handleAnswerChange(q.id, value)} + /> + )} +
+ ))} + +
+ + +
+
+ ); +}