Con las mejoras visuales
This commit is contained in:
@@ -1,93 +1,69 @@
|
||||
'use client'
|
||||
import type { FormAnswers, Question, QuestionOption, RatingOptions } from '@/lib/types'
|
||||
import type { AnswerValue, Question, QuestionOption } from '@/lib/form-engine.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'
|
||||
import { TextShortField } from './widgets/text-short-field'
|
||||
import { GeoSelectWidget } from './widgets/geo-select-widget'
|
||||
|
||||
interface QuestionRendererProps {
|
||||
question: Question
|
||||
answers: FormAnswers
|
||||
onChange: (code: string, value: FormAnswers[string]) => void
|
||||
errors: Record<string, string>
|
||||
value: AnswerValue
|
||||
onChange: (value: AnswerValue) => void
|
||||
error?: string
|
||||
}
|
||||
|
||||
function isArrayOptions(opts: unknown): opts is QuestionOption[] {
|
||||
return Array.isArray(opts)
|
||||
}
|
||||
const YES_NO_OPTIONS: QuestionOption[] = [
|
||||
{ value: 'true', label: 'Sí' },
|
||||
{ value: 'false', label: 'No' },
|
||||
]
|
||||
|
||||
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) {
|
||||
export function QuestionRenderer({ question, value, onChange, error }: QuestionRendererProps) {
|
||||
const { code, type, prompt, required, max_select, options } = question
|
||||
const error = errors[code]
|
||||
const legend = (
|
||||
<>
|
||||
<span className="q-code">{code} ·</span> {prompt}
|
||||
</>
|
||||
)
|
||||
|
||||
// A1 (Departamento) renders a combined geo widget that also handles A2 (Ciudad)
|
||||
// Code badges for A1/A2 are rendered inside GeoSelectWidget.
|
||||
if (code === 'A1') {
|
||||
return (
|
||||
<GeoSelectWidget
|
||||
departmentValue={(answers['A1'] as string) ?? ''}
|
||||
cityValue={(answers['A2'] as string) ?? ''}
|
||||
onDepartmentChange={(v) => onChange('A1', v)}
|
||||
onCityChange={(v) => onChange('A2', v)}
|
||||
departmentError={errors['A1']}
|
||||
cityError={errors['A2']}
|
||||
/>
|
||||
)
|
||||
}
|
||||
// A2 is rendered inside the GeoSelectWidget above — skip here to avoid duplication
|
||||
if (code === 'A2') return null
|
||||
|
||||
const legend = <><span className="q-code">{code} ·</span> {prompt}</>
|
||||
|
||||
if (type === 'single_choice' && isArrayOptions(options)) {
|
||||
if (type === 'single_choice' && options) {
|
||||
return (
|
||||
<RadioGroup
|
||||
name={code}
|
||||
legend={legend}
|
||||
options={options}
|
||||
value={answers[code] as string | undefined}
|
||||
value={(value as string) ?? undefined}
|
||||
required={required}
|
||||
onChange={(v) => onChange(code, v)}
|
||||
onChange={onChange}
|
||||
error={error}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
if (type === 'multiple_choice' && isArrayOptions(options)) {
|
||||
if (type === 'multiple_choice' && options) {
|
||||
return (
|
||||
<CheckboxGroup
|
||||
name={code}
|
||||
legend={legend}
|
||||
options={options}
|
||||
value={(answers[code] as string[]) ?? []}
|
||||
value={(value as string[]) ?? []}
|
||||
maxSelect={max_select}
|
||||
required={required}
|
||||
onChange={(v) => onChange(code, v)}
|
||||
onChange={onChange}
|
||||
error={error}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
if (type === 'rating' && isRatingOptions(options)) {
|
||||
// yes_no resuelto con el RadioGroup existente — dos opciones fijas, sin widget nuevo.
|
||||
if (type === 'yes_no') {
|
||||
return (
|
||||
<RatingScale
|
||||
<RadioGroup
|
||||
name={code}
|
||||
legend={legend}
|
||||
ratingOptions={options}
|
||||
value={answers[code] as number | undefined}
|
||||
options={YES_NO_OPTIONS}
|
||||
value={(value as string) ?? undefined}
|
||||
required={required}
|
||||
onChange={(v) => onChange(code, v)}
|
||||
onChange={onChange}
|
||||
error={error}
|
||||
/>
|
||||
)
|
||||
@@ -98,9 +74,9 @@ export function QuestionRenderer({
|
||||
<TextShortField
|
||||
name={code}
|
||||
label={legend}
|
||||
value={(answers[code] as string) ?? ''}
|
||||
value={(value as string) ?? ''}
|
||||
required={required}
|
||||
onChange={(v) => onChange(code, v)}
|
||||
onChange={onChange}
|
||||
error={error}
|
||||
/>
|
||||
)
|
||||
@@ -111,9 +87,9 @@ export function QuestionRenderer({
|
||||
<TextAreaField
|
||||
name={code}
|
||||
label={legend}
|
||||
value={(answers[code] as string) ?? ''}
|
||||
value={(value as string) ?? ''}
|
||||
required={required}
|
||||
onChange={(v) => onChange(code, v)}
|
||||
onChange={onChange}
|
||||
error={error}
|
||||
/>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user