feat(dashboard): selector de empresa + flag p_all en _dash_responses
This commit is contained in:
@@ -14,6 +14,14 @@ import { FilterSidebar } from '@/components/dashboard/filter-sidebar'
|
|||||||
import type { DashboardFilters } from '@/lib/dashboard-types'
|
import type { DashboardFilters } from '@/lib/dashboard-types'
|
||||||
|
|
||||||
// El survey_id se pasa como query param: /dashboard?survey_id=UUID
|
// El survey_id se pasa como query param: /dashboard?survey_id=UUID
|
||||||
|
// '00000000-0000-0000-0000-000000000000' = flag p_all (vista agregada de todos los surveys)
|
||||||
|
const SURVEY_OPTIONS = [
|
||||||
|
{ label: 'Todos', id: '00000000-0000-0000-0000-000000000000' },
|
||||||
|
{ 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' },
|
||||||
|
]
|
||||||
|
|
||||||
export default function DashboardPage() {
|
export default function DashboardPage() {
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
const surveyId = searchParams.get('survey_id') ?? '30000000-0000-0000-0000-000000000001'
|
const surveyId = searchParams.get('survey_id') ?? '30000000-0000-0000-0000-000000000001'
|
||||||
@@ -40,6 +48,22 @@ export default function DashboardPage() {
|
|||||||
Datos agregados · k-anonimato k≥5 · Encuesta Mapeo de Cuidadores 2026
|
Datos agregados · k-anonimato k≥5 · Encuesta Mapeo de Cuidadores 2026
|
||||||
{filters.depto && <span className="db-active-filter"> · Filtro: {filters.depto}</span>}
|
{filters.depto && <span className="db-active-filter"> · Filtro: {filters.depto}</span>}
|
||||||
</p>
|
</p>
|
||||||
|
<nav className="db-survey-nav" aria-label="Selección de empresa">
|
||||||
|
{SURVEY_OPTIONS.map((opt) => (
|
||||||
|
<a
|
||||||
|
key={opt.id}
|
||||||
|
href={`/dashboard?survey_id=${opt.id}`}
|
||||||
|
className={
|
||||||
|
opt.id === surveyId
|
||||||
|
? 'db-survey-link db-survey-link-active'
|
||||||
|
: 'db-survey-link'
|
||||||
|
}
|
||||||
|
aria-current={opt.id === surveyId ? 'page' : undefined}
|
||||||
|
>
|
||||||
|
{opt.label}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{/* Fila 1: KPIs (span 12) */}
|
{/* Fila 1: KPIs (span 12) */}
|
||||||
|
|||||||
@@ -559,6 +559,14 @@ body {
|
|||||||
.db-page-title { font-size: 1.375rem; font-weight: 700; color: #fff; margin: 0 0 4px; }
|
.db-page-title { font-size: 1.375rem; font-weight: 700; color: #fff; margin: 0 0 4px; }
|
||||||
.db-page-subtitle { font-size: 0.8125rem; color: #9ca3af; margin: 0; }
|
.db-page-subtitle { font-size: 0.8125rem; color: #9ca3af; margin: 0; }
|
||||||
.db-active-filter { color: var(--color-re-teal); font-weight: 600; }
|
.db-active-filter { color: var(--color-re-teal); font-weight: 600; }
|
||||||
|
.db-survey-nav { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
|
||||||
|
.db-survey-link {
|
||||||
|
font-size: 0.75rem; font-weight: 600; padding: 4px 12px; border-radius: 999px;
|
||||||
|
border: 1px solid rgba(67,187,200,0.3); color: #9ca3af; text-decoration: none;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
.db-survey-link:hover { color: #E7E6E5; border-color: var(--color-re-teal); }
|
||||||
|
.db-survey-link-active { background: var(--color-re-teal); color: #0F1923; border-color: var(--color-re-teal); }
|
||||||
.db-section { margin-bottom: 16px; }
|
.db-section { margin-bottom: 16px; }
|
||||||
.db-grid {
|
.db-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|||||||
33
supabase/migrations/20260611000001_dash_responses_all.sql
Normal file
33
supabase/migrations/20260611000001_dash_responses_all.sql
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
-- Migración: agregar flag p_all a _dash_responses
|
||||||
|
-- UUID especial '00000000-0000-0000-0000-000000000000' = todos los surveys
|
||||||
|
CREATE OR REPLACE FUNCTION public._dash_responses(
|
||||||
|
p_survey_id uuid,
|
||||||
|
p_depto text DEFAULT NULL,
|
||||||
|
p_genero text[] DEFAULT NULL,
|
||||||
|
p_etario text[] DEFAULT NULL,
|
||||||
|
p_modalidad text[] DEFAULT NULL
|
||||||
|
)
|
||||||
|
RETURNS TABLE(response_id uuid)
|
||||||
|
LANGUAGE sql STABLE SECURITY DEFINER
|
||||||
|
SET search_path = public
|
||||||
|
AS $$
|
||||||
|
SELECT r.id
|
||||||
|
FROM public.responses r
|
||||||
|
WHERE (p_survey_id = '00000000-0000-0000-0000-000000000000'
|
||||||
|
OR r.survey_id = p_survey_id)
|
||||||
|
AND (p_depto IS NULL OR r.qi_zone = p_depto)
|
||||||
|
AND (p_genero IS NULL OR cardinality(p_genero) = 0 OR EXISTS (
|
||||||
|
SELECT 1 FROM public.answers a
|
||||||
|
JOIN public.questions q ON q.id = a.question_id
|
||||||
|
WHERE a.response_id = r.id AND q.code = 'A6'
|
||||||
|
AND a.value #>> '{}' = ANY(p_genero)
|
||||||
|
))
|
||||||
|
AND (p_etario IS NULL OR cardinality(p_etario) = 0
|
||||||
|
OR r.qi_age_bucket = ANY(p_etario))
|
||||||
|
AND (p_modalidad IS NULL OR cardinality(p_modalidad) = 0 OR EXISTS (
|
||||||
|
SELECT 1 FROM public.answers a
|
||||||
|
JOIN public.questions q ON q.id = a.question_id
|
||||||
|
WHERE a.response_id = r.id AND q.code = 'A7'
|
||||||
|
AND a.value #>> '{}' = ANY(p_modalidad)
|
||||||
|
));
|
||||||
|
$$;
|
||||||
Reference in New Issue
Block a user