feat(admin): vista respuestas mejorada + vista detallada [admin]
/admin/responses: filtro survey dinámico (select, no hardcodeado), paginación 50/página, link a vista detallada, conteos consistentes con el filtro de preguntas permitidas (evita página fantasma al final). /admin/responses/[id]: respuestas agrupadas por sección (derivado de type='section', igual que el wizard — no existen section_number/ section_title, ver TECH-DEBT-011), instancias bajo "Familiar N". RLS y exclusión de sensibles intactos en ambas vistas. Fixes de revisión antes de cerrar: toggle expandir/colapsar movido a un <button> real (evita anidar el link "Ver" dentro de un role=button), formatDate/renderValue unificados en admin-format.ts, queries independientes en paralelo (Promise.all).
This commit is contained in:
58
TECH_DEBT.md
58
TECH_DEBT.md
@@ -111,3 +111,61 @@
|
||||
- **Trigger:** evaluar si la Mirada País/Humana también necesitan segmentar por
|
||||
modalidad con frecuencia — si varias RPCs repiten el mismo JOIN, conviene
|
||||
promoverla de una vez en lugar de cada RPC reimplementando el JOIN.
|
||||
|
||||
---
|
||||
|
||||
## [TECH-DEBT-011] Sección de pregunta inferida por posición, no modelada como dato
|
||||
|
||||
- **Estado:** ABIERTO — decisión consciente, no un descuido. Surgió en
|
||||
ETAPA_ADMIN (vista detallada `/admin/responses/[id]`, 27 jun 2026): el prompt
|
||||
de etapa asumía columnas `questions.section_number`/`section_title` que NO
|
||||
existen. Verificado contra el esquema real (`supabase/migrations/
|
||||
20260531000001_create_tables.sql` — única definición de `questions`,
|
||||
`20260620000002_form_schema_v3.sql` solo agrega comentarios, ninguna
|
||||
migración agrega esas columnas).
|
||||
- **Descripción:** hoy `questions` no tiene ningún campo que declare "esta
|
||||
pregunta pertenece a la sección X". La sección es una fila más en la misma
|
||||
tabla, con `type='section'`, intercalada por `position` entre las preguntas
|
||||
reales — el código (`lib/form-engine.ts:146-148` en el wizard, y la vista
|
||||
detallada de admin) infiere el agrupamiento recorriendo las filas en orden
|
||||
de `position` y "abriendo" una sección nueva cada vez que encuentra una fila
|
||||
`type='section'`. El título de la sección es el `prompt` de esa fila — no
|
||||
hay un campo `title` separado.
|
||||
- **Por qué es deuda, no solo una curiosidad de modelado:** el motor está
|
||||
pensado para ser un "motor de formularios de encuestas" genérico — no toda
|
||||
encuesta futura va a tener secciones, y las que las tengan no necesariamente
|
||||
van a querer modelarlas como filas-marcador en la misma tabla que las
|
||||
preguntas. Hoy CUALQUIER consumidor que necesite agrupar por sección
|
||||
(wizard, admin, y a futuro cualquier export/reporte) tiene que reimplementar
|
||||
el mismo recorrido secuencial con el mismo supuesto implícito ("la fila
|
||||
`type='section'` más cercana hacia atrás en `position` es la sección de esta
|
||||
pregunta"). Si esa lógica se necesita en un tercer lugar, ya es momento de
|
||||
promoverla a una función compartida — y si el motor crece a encuestas con
|
||||
estructuras más ricas (subsecciones, secciones condicionales, secciones que
|
||||
no son "preguntas" en absoluto), el modelo actual no escala sin reescribir
|
||||
cada consumidor.
|
||||
- **Alternativa más genérica y escalable (no implementada, propuesta para
|
||||
evaluar cuando se priorice):** sacar la sección de `questions.type` y
|
||||
modelarla como entidad propia — opción simple: `questions.section_id uuid
|
||||
NULL REFERENCES sections(id)` + tabla `sections(id, survey_id, title,
|
||||
position)`; opción más liviana sin tabla nueva: `questions.section_title
|
||||
text NULL` + `questions.section_position int NULL` poblados directamente en
|
||||
cada pregunta (denormalizado, sin fila-marcador `type='section'` separada).
|
||||
Cualquiera de las dos deja "pertenece a la sección X" como un hecho
|
||||
consultable con una columna, no como un cálculo derivado de recorrer
|
||||
`position` — y ninguna asume que toda encuesta tiene secciones (el campo es
|
||||
nullable). Migrar implicaría: (1) nueva(s) columna(s)/tabla, (2) backfill
|
||||
desde las filas `type='section'` existentes, (3) actualizar
|
||||
`lib/form-engine.ts` y la vista detallada de admin para leer el dato en vez
|
||||
de inferirlo, (4) decidir si `type='section'` se deprecia o convive.
|
||||
- **Acción tomada mientras tanto:** la vista detallada de admin
|
||||
(`app/admin/responses/[id]/page.tsx`) replica la misma lógica de
|
||||
`lib/form-engine.ts` (recorrido secuencial por `position`, abre sección en
|
||||
cada `type='section'`) — no inventa columnas nuevas, no diverge del modelo
|
||||
actual.
|
||||
- **Trigger:** si una tercera feature necesita el mismo agrupamiento, extraer
|
||||
la lógica a un helper compartido en `lib/` en vez de triplicarla. Si el
|
||||
producto efectivamente evoluciona a soportar surveys con estructuras de
|
||||
sección más complejas que el caso actual, evaluar la migración a columna/
|
||||
tabla explícita antes de seguir apilando consumidores sobre el supuesto
|
||||
implícito.
|
||||
|
||||
Reference in New Issue
Block a user