Files
motor-de-encuestas/components/question-renderer.tsx
2026-06-02 10:27:52 -03:00

90 lines
2.2 KiB
TypeScript

'use client'
import type { FormAnswers, Question, QuestionOption, RatingOptions } from '@/lib/types'
import { RadioGroup } from './widgets/radio-group'
import { CheckboxGroup } from './widgets/checkbox-group'
import { RatingScale } from './widgets/rating-scale'
import { TextAreaField } from './widgets/text-area-field'
interface QuestionRendererProps {
question: Question
answers: FormAnswers
onChange: (code: string, value: FormAnswers[string]) => void
errors: Record<string, string>
}
function isArrayOptions(opts: unknown): opts is QuestionOption[] {
return Array.isArray(opts)
}
function isRatingOptions(opts: unknown): opts is RatingOptions {
return typeof opts === 'object' && opts !== null && 'min' in opts && 'max' in opts
}
export function QuestionRenderer({
question,
answers,
onChange,
errors,
}: QuestionRendererProps) {
const { code, type, prompt, required, max_select, options } = question
const error = errors[code]
if (type === 'single_choice' && isArrayOptions(options)) {
return (
<RadioGroup
name={code}
legend={prompt}
options={options}
value={answers[code] as string | undefined}
required={required}
onChange={(v) => onChange(code, v)}
error={error}
/>
)
}
if (type === 'multiple_choice' && isArrayOptions(options)) {
return (
<CheckboxGroup
name={code}
legend={prompt}
options={options}
value={(answers[code] as string[]) ?? []}
maxSelect={max_select}
required={required}
onChange={(v) => onChange(code, v)}
error={error}
/>
)
}
if (type === 'rating' && isRatingOptions(options)) {
return (
<RatingScale
name={code}
legend={prompt}
ratingOptions={options}
value={answers[code] as number | undefined}
required={required}
onChange={(v) => onChange(code, v)}
error={error}
/>
)
}
if (type === 'text_long' || type === 'text_short') {
return (
<TextAreaField
name={code}
label={prompt}
value={(answers[code] as string) ?? ''}
required={required}
onChange={(v) => onChange(code, v)}
error={error}
/>
)
}
return null
}