diff --git a/src/components/forms/CheckBoxWithLabelForm.tsx b/src/components/forms/CheckBoxWithLabelForm.tsx index 6d155d6..a2af3ab 100644 --- a/src/components/forms/CheckBoxWithLabelForm.tsx +++ b/src/components/forms/CheckBoxWithLabelForm.tsx @@ -1,8 +1,9 @@ -import { useId } from "react"; +import { useCallback, useId, useMemo } from "react"; import { Checkbox } from "@/components/ui/checkbox"; import { FormState, Question } from "./FormRenderer"; +import { CheckedState } from "@radix-ui/react-checkbox"; // prettier-ignore export type CheckBoxWithLabelFormProps = @@ -10,47 +11,59 @@ export type CheckBoxWithLabelFormProps = FormState; export const CheckBoxWithLabelForm = ({ + questionId, questionText, options, formState, setFormState, }: CheckBoxWithLabelFormProps) => { const htmlFor = useId(); + const questionIndex = formState.questions.findIndex((q) => q.questionId === questionId); + + const handleCheckboxChange = useCallback( + (option: (typeof options)[number], checked: CheckedState) => { + const updatedQuestions = [...formState.questions]; + const updatedOptions = [...updatedQuestions[questionIndex].options]; + + if (checked) { + updatedOptions.push(option); + } else { + const optionIndex = updatedOptions.findIndex((opt) => opt.value === option.value); + if (optionIndex > -1) updatedOptions.splice(optionIndex, 1); + } + + updatedQuestions[questionIndex] = { + ...updatedQuestions[questionIndex], + options: updatedOptions, + }; + + setFormState({ + ...formState, + questions: updatedQuestions, + }); + }, + [formState, questionIndex, setFormState], + ); return (

{questionText}

{options.map((option, index) => { + const isChecked = formState.questions[questionIndex].options.some( + (selectedOption) => selectedOption.value === option.value, + ); + return (
state.value) - .includes(option.value)} - onCheckedChange={(isChecked) => { - if (isChecked) { - setFormState({ - ...formState, - [questionText]: [ - ...formState[questionText], - { value: option.value }, - ], - }); - } else { - setFormState({ - ...formState, - [questionText]: formState[questionText].filter( - (state) => state.value !== option.value, - ), - }); - } - }} + checked={isChecked} + onCheckedChange={(checked) => handleCheckboxChange(option, checked)} /> - +
); })} diff --git a/src/components/forms/DoubleSliderWithLabelForm.tsx b/src/components/forms/DoubleSliderWithLabelForm.tsx index 6d7ac88..4f2adec 100644 --- a/src/components/forms/DoubleSliderWithLabelForm.tsx +++ b/src/components/forms/DoubleSliderWithLabelForm.tsx @@ -1,47 +1,70 @@ -import { useEffect, useState } from "react"; +import { useState } from "react"; -import { DualRangeSlider, DualRangeSliderProps } from "../ui/slider"; +import { DualRangeSlider } from "../ui/slider"; import { FormState, Question } from "./FormRenderer"; // prettier-ignore export type DoubleSliderWithLabelFormProps = - Omit & + Omit & FormState; export const DoubleSliderWithLabelForm = ({ + questionId, questionText, options, formState, setFormState, }: DoubleSliderWithLabelFormProps) => { - const min = options[0]; - const max = options[options.length - 1]; - - const [value, setValue] = useState([min.value, max.value]); + const question = formState.questions.find((q) => q.questionId === questionId); return (

{questionText}

{ - setValue(value); + const updatedQuestions = formState.questions.map((q) => + q.questionId === questionId + ? { + ...q, + options: [ + { + label: options.find((opt) => opt.value === value[0]) + ?.label, + value: value[0], + }, + { + label: options.find((opt) => opt.value === value[1]) + ?.label, + value: value[1], + }, + ], + } + : q, + ); setFormState({ ...formState, - [questionText]: [{ value: value }], + questions: updatedQuestions, }); }} label={(value) => ( - + {options.find((option) => option.value === value)?.label} )} + labelPosition="bottom" />
diff --git a/src/components/forms/FormFactory.tsx b/src/components/forms/FormFactory.tsx index 145ca8f..d7bed67 100644 --- a/src/components/forms/FormFactory.tsx +++ b/src/components/forms/FormFactory.tsx @@ -1,6 +1,8 @@ import { CheckBoxWithLabelForm } from "./CheckBoxWithLabelForm"; +import { DoubleSliderWithLabelForm } from "./DoubleSliderWithLabelForm"; import { QuestionTypes } from "./FormRenderer"; import { SelectorWithLabelForm } from "./SelectorWithLabelForm"; +import { SliderWithLabelForm } from "./SliderWithLabelForm"; export interface FormFactoryProps { questionType: keyof typeof QuestionTypes; @@ -10,8 +12,8 @@ export const FormFactory = ({ questionType }: FormFactoryProps) => { const FormElements = { [QuestionTypes.selector]: SelectorWithLabelForm, [QuestionTypes.checkbox]: CheckBoxWithLabelForm, - // [QuestionTypes.slider]: SliderWithLabelForm, - // [QuestionTypes.doubleSlider]: DoubleSliderWithLabelForm, + [QuestionTypes.slider]: SliderWithLabelForm, + [QuestionTypes.doubleSlider]: DoubleSliderWithLabelForm, }; return FormElements[questionType]; diff --git a/src/components/forms/FormRenderer.tsx b/src/components/forms/FormRenderer.tsx index ff6b36c..45deff5 100644 --- a/src/components/forms/FormRenderer.tsx +++ b/src/components/forms/FormRenderer.tsx @@ -3,8 +3,8 @@ import { FormFactory } from "./FormFactory"; export const QuestionTypes = { checkbox: "checkbox", selector: "selector", - // slider: "slider", - // doubleSlider: "doubleSlider", + slider: "slider", + doubleSlider: "doubleSlider", } as const; export interface Option { @@ -13,6 +13,7 @@ export interface Option { } export interface Question { + questionId: number; questionText: string; questionType: keyof typeof QuestionTypes; dataType: string; @@ -20,19 +21,21 @@ export interface Question { } export interface FormProps { + _id: string; title: string; description: string; questions: Question[]; } export interface FormState { - formState: Record; - setFormState: React.Dispatch>>; + formState: FormProps; + setFormState: React.Dispatch>; } export type FormRendererProps = FormProps & FormState; export const FormRenderer = ({ + _id, title, description, questions, diff --git a/src/components/forms/SelectorWithLabelForm.tsx b/src/components/forms/SelectorWithLabelForm.tsx index 7778766..6b104bb 100644 --- a/src/components/forms/SelectorWithLabelForm.tsx +++ b/src/components/forms/SelectorWithLabelForm.tsx @@ -8,14 +8,19 @@ import { SelectValue, } from "@/components/ui/select"; -import { FormState, Question } from "./FormRenderer"; +import { FormProps, FormState, Question, Option } from "./FormRenderer"; // prettier-ignore -export type SelectorWithLabelFormProps = - Omit & - FormState +export type SelectorWithLabelFormProps = { + questionId: number; + questionText: string; + options: Option[]; + formState: FormProps; + setFormState: React.Dispatch>; +}; export const SelectorWithLabelForm = ({ + questionId, questionText, options, formState, @@ -23,19 +28,28 @@ export const SelectorWithLabelForm = ({ }: SelectorWithLabelFormProps) => { const htmlFor = useId(); + const questionIndex = formState.questions.findIndex((q) => q.questionId === questionId); + + const selectedValue = formState.questions[questionIndex].options[0]?.value || ""; + return (