117 lines
3.5 KiB
TypeScript
117 lines
3.5 KiB
TypeScript
'use client'
|
|
import type { FormAnswers, Question, QuestionOption, RatingOptions } from '@/lib/types'
|
|
import { isQuestionVisible } from '@/lib/conditional'
|
|
|
|
interface SummaryScreenProps {
|
|
surveyTitle: string
|
|
questions: Question[]
|
|
answers: FormAnswers
|
|
onStartOver: () => void
|
|
}
|
|
|
|
function formatAnswer(question: Question, raw: FormAnswers[string]): string {
|
|
if (raw === null || raw === undefined || raw === '') return '—'
|
|
|
|
const { type, options } = question
|
|
|
|
if ((type === 'single_choice') && Array.isArray(options)) {
|
|
const opt = (options as QuestionOption[]).find((o) => o.value === raw)
|
|
return opt?.label ?? String(raw)
|
|
}
|
|
|
|
if (type === 'multiple_choice' && Array.isArray(raw) && Array.isArray(options)) {
|
|
const opts = options as QuestionOption[]
|
|
const labels = (raw as string[]).map(
|
|
(v) => opts.find((o) => o.value === v)?.label ?? v
|
|
)
|
|
return labels.length > 0 ? labels.join(', ') : '—'
|
|
}
|
|
|
|
if (type === 'rating' && options && !Array.isArray(options)) {
|
|
const ro = options as RatingOptions
|
|
return `${raw} / ${ro.max} (${ro.min_label} → ${ro.max_label})`
|
|
}
|
|
|
|
return String(raw)
|
|
}
|
|
|
|
// Section titles by code prefix ('A', '1', '2', …)
|
|
const SECTION_TITLES: Record<string, string> = {
|
|
A: 'Datos Generales',
|
|
'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({
|
|
surveyTitle,
|
|
questions,
|
|
answers,
|
|
onStartOver,
|
|
}: SummaryScreenProps) {
|
|
const visibleQuestions = questions.filter((q) => isQuestionVisible(q, answers))
|
|
|
|
let lastSection = ''
|
|
|
|
return (
|
|
<div className="summary-container" role="main">
|
|
<div className="summary-header">
|
|
<h1 className="summary-title">Resumen de tus respuestas</h1>
|
|
<p className="summary-subtitle">
|
|
{surveyTitle} — revisá lo que respondiste antes de continuar al envío.
|
|
</p>
|
|
<p className="summary-note" role="note">
|
|
<strong>Nota:</strong> en esta etapa no se envía nada a la base de datos.
|
|
El envío definitivo (con consentimiento) será en el paso siguiente.
|
|
</p>
|
|
</div>
|
|
|
|
<dl className="summary-list">
|
|
{visibleQuestions.map((q) => {
|
|
const section = getSectionPrefix(q.code)
|
|
const showHeader = section !== lastSection
|
|
lastSection = section
|
|
|
|
return (
|
|
<div key={q.id}>
|
|
{showHeader && (
|
|
<h2 className="summary-section-heading">
|
|
{SECTION_TITLES[section] ?? section}
|
|
</h2>
|
|
)}
|
|
<div className="summary-item">
|
|
<dt className="summary-question">
|
|
<span className="summary-code">{q.code}</span> {q.prompt}
|
|
</dt>
|
|
<dd className="summary-answer">
|
|
{formatAnswer(q, answers[q.code] ?? null)}
|
|
</dd>
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</dl>
|
|
|
|
<div className="summary-actions">
|
|
<button
|
|
type="button"
|
|
onClick={onStartOver}
|
|
className="btn btn-secondary"
|
|
>
|
|
Volver a la encuesta
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|