103 lines
4.0 KiB
TypeScript
103 lines
4.0 KiB
TypeScript
import { createClient } from '@/lib/supabase'
|
|
import type { BrandConfig, Survey } from '@/lib/types'
|
|
import type { FormSchema, Question as EngineQuestion } from '@/lib/form-engine.types'
|
|
import { buildFormSchema } from '@/lib/form-engine'
|
|
import { WizardForm } from '@/components/wizard-form'
|
|
|
|
// Preguntas de consentimiento (S1, 1.1, 1.2): las resuelve ConsentScreen, no el
|
|
// motor de flujo — su texto legal (ADR-003) no vive en el hint de estas filas
|
|
// todavía. Se excluyen del FormSchema para que el wizard arranque en S2.
|
|
const CONSENT_CODES = new Set(['S1', '1.1', '1.2'])
|
|
|
|
// Force dynamic rendering — page fetches from Supabase at request time.
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
// In Next.js 15, searchParams is a Promise and must be awaited.
|
|
interface PageProps {
|
|
searchParams: Promise<{ s?: string }>
|
|
}
|
|
|
|
export default async function Page({ searchParams }: PageProps) {
|
|
const { s: surveyId } = await searchParams
|
|
const supabase = createClient()
|
|
|
|
// 1. Fetch survey — by ?s=UUID if provided, otherwise first live survey
|
|
const surveyQuery = supabase
|
|
.from('surveys')
|
|
.select('id, org_id, title, status, is_anonymous, k_threshold, consent_version_id, brand_config')
|
|
|
|
const { data: surveyRow, error: surveyError } = surveyId
|
|
? await surveyQuery.eq('id', surveyId).maybeSingle()
|
|
: await surveyQuery.eq('status', 'live').maybeSingle()
|
|
|
|
if (surveyError) {
|
|
return (
|
|
<div className="no-survey" role="main">
|
|
<h1 className="no-survey-title">Error al cargar la encuesta</h1>
|
|
<p>No fue posible conectarse a la base de datos. Revisá las variables de entorno.</p>
|
|
<pre className="no-survey-hint">{surveyError.message}</pre>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (!surveyRow) {
|
|
return (
|
|
<div className="no-survey" role="main">
|
|
<h1 className="no-survey-title">No hay encuesta activa</h1>
|
|
<p>
|
|
Para ver el formulario, la encuesta debe estar en estado <code>live</code>,
|
|
o pasá el UUID por parámetro: <code>?s=UUID</code>.
|
|
</p>
|
|
<pre className="no-survey-hint">
|
|
{`-- Activar en Supabase Cloud:\nUPDATE surveys SET status = 'live'\nWHERE id = '30000000-0000-0000-0000-000000000001';`}
|
|
</pre>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// 2. Fetch questions ordered by position — incluye hint/instance_generator/instance_of (4D)
|
|
const { data: questionRows, error: questionsError } = await supabase
|
|
.from('questions')
|
|
.select(
|
|
'id, survey_id, code, type, prompt, position, is_sensitive, required, hint, ' +
|
|
'max_select, options, conditional_rules, instance_generator, instance_of'
|
|
)
|
|
.eq('survey_id', surveyRow.id)
|
|
.order('position', { ascending: true })
|
|
|
|
if (questionsError || !questionRows) {
|
|
return (
|
|
<div className="no-survey" role="main">
|
|
<h1 className="no-survey-title">Error al cargar las preguntas</h1>
|
|
<p>{questionsError?.message ?? 'Respuesta vacía del servidor.'}</p>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// Cast en dos pasos: el cliente Supabase no tiene un Database genérico configurado
|
|
// (lib/supabase.ts), así que el tipo de fila que infiere para .select() no solapa
|
|
// directamente con EngineQuestion. Las columnas pedidas arriba sí coinciden 1:1.
|
|
const engineQuestions = questionRows as unknown as EngineQuestion[]
|
|
|
|
console.log(`[4D] Survey loaded: id=${surveyRow.id} | questions=${engineQuestions.length}`)
|
|
|
|
const survey: Survey = {
|
|
id: surveyRow.id,
|
|
org_id: surveyRow.org_id,
|
|
title: surveyRow.title,
|
|
status: surveyRow.status,
|
|
is_anonymous: surveyRow.is_anonymous,
|
|
k_threshold: surveyRow.k_threshold,
|
|
consent_version_id: surveyRow.consent_version_id,
|
|
brand_config: (surveyRow.brand_config as BrandConfig) ?? null,
|
|
questions: [],
|
|
}
|
|
|
|
// El consentimiento (S1, 1.1, 1.2) lo resuelve ConsentScreen, no el motor — ver nota arriba.
|
|
const schema: FormSchema = buildFormSchema(
|
|
engineQuestions.filter((q) => !CONSENT_CODES.has(q.code))
|
|
)
|
|
|
|
return <WizardForm survey={survey} schema={schema} />
|
|
}
|