Instrumento v2: 44 preguntas + widget text_short
This commit is contained in:
@@ -4,6 +4,7 @@ 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'
|
||||
|
||||
interface QuestionRendererProps {
|
||||
question: Question
|
||||
@@ -72,7 +73,20 @@ export function QuestionRenderer({
|
||||
)
|
||||
}
|
||||
|
||||
if (type === 'text_long' || type === 'text_short') {
|
||||
if (type === 'text_short') {
|
||||
return (
|
||||
<TextShortField
|
||||
name={code}
|
||||
label={prompt}
|
||||
value={(answers[code] as string) ?? ''}
|
||||
required={required}
|
||||
onChange={(v) => onChange(code, v)}
|
||||
error={error}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
if (type === 'text_long') {
|
||||
return (
|
||||
<TextAreaField
|
||||
name={code}
|
||||
|
||||
@@ -35,16 +35,22 @@ function formatAnswer(question: Question, raw: FormAnswers[string]): string {
|
||||
return String(raw)
|
||||
}
|
||||
|
||||
// Section titles by first question code prefix
|
||||
// Section titles by code prefix ('A', '1', '2', …)
|
||||
const SECTION_TITLES: Record<string, string> = {
|
||||
A: 'Datos Generales',
|
||||
B: '¿Vivís con discapacidad?',
|
||||
C: 'Familiares con Discapacidad',
|
||||
D: 'Adultos Mayores a Cargo',
|
||||
E: 'Tu Rol como Cuidador/a',
|
||||
F: 'Impacto Económico',
|
||||
G: 'Bienestar y Descanso',
|
||||
H: 'Necesidades',
|
||||
'1': 'Prevalencia: cuidado y discapacidad',
|
||||
'2': 'Intensidad y rol del cuidado',
|
||||
'3': 'Impacto económico del cuidado',
|
||||
'4': 'Tiempo y descanso',
|
||||
'5': 'Impacto en el trabajo',
|
||||
'6': 'Conciencia organizacional',
|
||||
'7': 'Para cerrar',
|
||||
}
|
||||
|
||||
// 'A1' → 'A', '1.1' → '1', '6.4' → '6', '7.1' → '7'
|
||||
function getSectionPrefix(code: string): string {
|
||||
const m = code.match(/^([A-Za-z]+|\d+)/)
|
||||
return m ? m[1] : code
|
||||
}
|
||||
|
||||
export function SummaryScreen({
|
||||
@@ -72,7 +78,7 @@ export function SummaryScreen({
|
||||
|
||||
<dl className="summary-list">
|
||||
{visibleQuestions.map((q) => {
|
||||
const section = q.code.replace(/\d+$/, '')
|
||||
const section = getSectionPrefix(q.code)
|
||||
const showHeader = section !== lastSection
|
||||
lastSection = section
|
||||
|
||||
|
||||
@@ -8,19 +8,23 @@ import { QuestionRenderer } from './question-renderer'
|
||||
import { SummaryScreen } from './summary-screen'
|
||||
|
||||
// Section metadata (code prefix → display title)
|
||||
// Prefixes: 'A' for A1-A7, '1' for 1.1-1.16, '2' for 2.1-2.5, etc.
|
||||
const SECTIONS: { prefix: string; title: string; sensitive?: boolean }[] = [
|
||||
{ prefix: 'A', title: 'Datos Generales' },
|
||||
{ prefix: 'B', title: '¿Vivís con discapacidad?', sensitive: true },
|
||||
{ prefix: 'C', title: 'Familiares con Discapacidad', sensitive: true },
|
||||
{ prefix: 'D', title: 'Adultos Mayores a Cargo', sensitive: true },
|
||||
{ prefix: 'E', title: 'Tu Rol como Cuidador/a' },
|
||||
{ prefix: 'F', title: 'Impacto Económico' },
|
||||
{ prefix: 'G', title: 'Bienestar y Descanso' },
|
||||
{ prefix: 'H', title: 'Necesidades' },
|
||||
{ prefix: '1', title: 'Prevalencia: cuidado y discapacidad', sensitive: true },
|
||||
{ prefix: '2', title: 'Intensidad y rol del cuidado' },
|
||||
{ prefix: '3', title: 'Impacto económico del cuidado' },
|
||||
{ prefix: '4', title: 'Tiempo y descanso' },
|
||||
{ prefix: '5', title: 'Impacto en el trabajo' },
|
||||
{ prefix: '6', title: 'Conciencia organizacional' },
|
||||
{ prefix: '7', title: 'Para cerrar' },
|
||||
]
|
||||
|
||||
function getSectionPrefix(code: string) {
|
||||
return code.replace(/\d+$/, '')
|
||||
// Extracts the leading alpha or numeric segment from a question code.
|
||||
// 'A1' → 'A', '1.1' → '1', '1.16' → '1', '6.4' → '6', '7.1' → '7'
|
||||
function getSectionPrefix(code: string): string {
|
||||
const m = code.match(/^([A-Za-z]+|\d+)/)
|
||||
return m ? m[1] : code
|
||||
}
|
||||
|
||||
interface SurveyFormProps {
|
||||
|
||||
50
components/widgets/text-short-field.tsx
Normal file
50
components/widgets/text-short-field.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
'use client'
|
||||
|
||||
interface TextShortFieldProps {
|
||||
name: string
|
||||
label: string
|
||||
value: string
|
||||
required: boolean
|
||||
placeholder?: string
|
||||
onChange: (value: string) => void
|
||||
error?: string
|
||||
}
|
||||
|
||||
export function TextShortField({
|
||||
name,
|
||||
label,
|
||||
value,
|
||||
required,
|
||||
placeholder = '',
|
||||
onChange,
|
||||
error,
|
||||
}: TextShortFieldProps) {
|
||||
return (
|
||||
<div className="question-fieldset">
|
||||
<label className="question-legend" htmlFor={name}>
|
||||
{label}
|
||||
{required && <span className="required-mark" aria-hidden="true"> *</span>}
|
||||
{required && <span className="sr-only"> (obligatorio)</span>}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id={name}
|
||||
name={name}
|
||||
value={value}
|
||||
required={required}
|
||||
aria-required={required}
|
||||
aria-describedby={error ? `${name}-error` : undefined}
|
||||
aria-invalid={!!error}
|
||||
placeholder={placeholder}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
className="text-short-input"
|
||||
autoComplete="off"
|
||||
/>
|
||||
{error && (
|
||||
<p role="alert" className="field-error" id={`${name}-error`}>
|
||||
{error}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user