Control de respuestas
No fue posible conectarse a la base de datos.
{questionsError.message}
import { createServerClient } from '@supabase/ssr' import { cookies } from 'next/headers' import { ResponsesTable, type DisplayRow } from './responses-table' import { SignOutButton } from '../sign-out-button' export const dynamic = 'force-dynamic' const MAX_SUBMISSIONS = 500 const PROMPT_MAX_LEN = 60 const SURVEY_OPTIONS = [ { label: 'Todos', id: null }, { label: 'InQuality', id: '30000000-0000-0000-0000-000000000002' }, { label: 'Fundación Solidaridad', id: '30000000-0000-0000-0000-000000000003' }, { label: 'Demo', id: '30000000-0000-0000-0000-000000000001' }, ] as const interface AllowedQuestion { id: string code: string prompt: string type: string position: number } interface AnswerRow { value: unknown question_id: string } interface ResponseRow { id: string submitted_at: string qi_zone: string | null qi_sector: string | null answers: AnswerRow[] } async function getSupabaseSession() { const cookieStore = await cookies() return createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { getAll() { return cookieStore.getAll() }, setAll(cookiesToSet) { try { cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options) ) } catch { // Server Component — no puede mutar cookies, se ignora } }, }, } ) } function formatDate(iso: string): string { const d = new Date(iso) const pad = (n: number) => String(n).padStart(2, '0') return `${pad(d.getDate())}/${pad(d.getMonth() + 1)}/${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}` } function truncate(text: string, max = PROMPT_MAX_LEN): string { return text.length > max ? `${text.slice(0, max)}...` : text } // Spec 4.3 — null/undefined → null (renderizado como badge "sin dato") function renderValue(value: unknown, type: string): string | null { if (value === null || value === undefined) return null switch (type) { case 'single_choice': case 'text_short': return String(value).replace(/^"|"$/g, '') case 'multiple_choice': if (Array.isArray(value)) return value.join(', ') return String(value) case 'rating': return String(value) default: return String(value) } } export default async function AdminResponsesPage({ searchParams, }: { searchParams: Promise<{ survey_id?: string }> }) { const { survey_id: surveyId } = await searchParams const supabase = await getSupabaseSession() // 1. Preguntas permitidas — text_long e is_sensitive=true se excluyen ACÁ, // antes de tocar la tabla answers. Sus valores nunca se consultan. const { data: questionsData, error: questionsError } = await supabase .from('questions') .select('id, code, prompt, type, position') .eq('is_sensitive', false) .neq('type', 'text_long') .order('position', { ascending: true }) if (questionsError) { return (
No fue posible conectarse a la base de datos.
{questionsError.message}
No fue posible conectarse a la base de datos.
{responsesError.message}
{totalSubmissions ?? 0} submissions · {totalAnswers ?? 0} respuestas individuales · actualizado {formatDate(new Date().toISOString())}
Sin respuestas registradas todavía.
)}