- BarrioAutocompleteField: carga JSON estático, filtra por depto/ciudad (2.1/2.2), mín 2 chars, máx 10 sugerencias, texto libre permitido, teclado (↑↓ Enter Escape), ARIA listbox - QuestionRenderer: branch code === '2.3' → BarrioAutocompleteField; prop answers? pasado desde WizardForm para contexto depto/ciudad - globals.css: clases .barrio-autocomplete-* (wrapper, list, item, item--active) - Incluye public/data/geo_paraguay_full.json (202 KB, sin commitear hasta ahora) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
116 lines
2.8 KiB
TypeScript
116 lines
2.8 KiB
TypeScript
'use client'
|
|
import type { AnswerValue, FormAnswers, Question, QuestionOption } from '@/lib/form-engine.types'
|
|
import { RadioGroup } from './widgets/radio-group'
|
|
import { CheckboxGroup } from './widgets/checkbox-group'
|
|
import { TextAreaField } from './widgets/text-area-field'
|
|
import { TextShortField } from './widgets/text-short-field'
|
|
import { BarrioAutocompleteField } from './widgets/barrio-autocomplete-field'
|
|
|
|
interface QuestionRendererProps {
|
|
question: Question
|
|
value: AnswerValue
|
|
onChange: (value: AnswerValue) => void
|
|
error?: string
|
|
answers?: FormAnswers
|
|
}
|
|
|
|
const YES_NO_OPTIONS: QuestionOption[] = [
|
|
{ value: 'true', label: 'Sí' },
|
|
{ value: 'false', label: 'No' },
|
|
]
|
|
|
|
export function QuestionRenderer({ question, value, onChange, error, answers }: QuestionRendererProps) {
|
|
const { code, type, prompt, required, max_select, options } = question
|
|
const legend = (
|
|
<>
|
|
<span className="q-code">{code} ·</span> {prompt}
|
|
</>
|
|
)
|
|
|
|
if (type === 'single_choice' && options) {
|
|
return (
|
|
<RadioGroup
|
|
name={code}
|
|
legend={legend}
|
|
options={options}
|
|
value={(value as string) ?? undefined}
|
|
required={required}
|
|
onChange={onChange}
|
|
error={error}
|
|
/>
|
|
)
|
|
}
|
|
|
|
if (type === 'multiple_choice' && options) {
|
|
return (
|
|
<CheckboxGroup
|
|
name={code}
|
|
legend={legend}
|
|
options={options}
|
|
value={(value as string[]) ?? []}
|
|
maxSelect={max_select}
|
|
required={required}
|
|
onChange={onChange}
|
|
error={error}
|
|
/>
|
|
)
|
|
}
|
|
|
|
// yes_no resuelto con el RadioGroup existente — dos opciones fijas, sin widget nuevo.
|
|
if (type === 'yes_no') {
|
|
return (
|
|
<RadioGroup
|
|
name={code}
|
|
legend={legend}
|
|
options={YES_NO_OPTIONS}
|
|
value={(value as string) ?? undefined}
|
|
required={required}
|
|
onChange={onChange}
|
|
error={error}
|
|
/>
|
|
)
|
|
}
|
|
|
|
if (type === 'text_short') {
|
|
if (code === '2.3') {
|
|
return (
|
|
<BarrioAutocompleteField
|
|
name={code}
|
|
label={legend}
|
|
value={(value as string) ?? ''}
|
|
required={required}
|
|
departamento={(answers?.['2.1:default'] as string) ?? null}
|
|
ciudad={(answers?.['2.2:default'] as string) ?? null}
|
|
onChange={onChange}
|
|
error={error}
|
|
/>
|
|
)
|
|
}
|
|
return (
|
|
<TextShortField
|
|
name={code}
|
|
label={legend}
|
|
value={(value as string) ?? ''}
|
|
required={required}
|
|
onChange={onChange}
|
|
error={error}
|
|
/>
|
|
)
|
|
}
|
|
|
|
if (type === 'text_long') {
|
|
return (
|
|
<TextAreaField
|
|
name={code}
|
|
label={legend}
|
|
value={(value as string) ?? ''}
|
|
required={required}
|
|
onChange={onChange}
|
|
error={error}
|
|
/>
|
|
)
|
|
}
|
|
|
|
return null
|
|
}
|