Files
OPSV---Dashboard-de-Siniest…/src/hooks/useSiniestralidad.js
T

115 lines
3.8 KiB
JavaScript

/**
* useSiniestralidad.js — v2 CORREGIDO
*
* CAMBIO CRÍTICO: Persona e Involucrados se consultan por ano/mes directamente,
* NO por id_feu con .in(). Motivo: .in() con muchos IDs supera el límite de URL
* de PostgREST y devuelve array vacío sin error visible.
*
* El filtro de zona se aplica en memoria en Dashboard.jsx usando id_feu.
*
* Paginación: .range(0, 4999) para hasta 5000 filas por tabla.
* Si tu dataset tiene más, aumentá el límite.
*/
import { useState, useEffect } from 'react'
import { supabase } from '../lib/supabase'
// ── Nombres EXACTOS de tablas en Supabase (case-sensitive) ────
const T = {
siniestros: 'siniestros',
involucrados: 'Involucrados', // I mayúscula
personas: 'Personas', // P mayúscula
}
// ── Columnas seleccionadas ────────────────────────────────────
const SEL = {
sin: [
'id_feu','mes','ano','siniestro_hora','localidad','departamento',
'zona_ocurrencia','via_publica','tipo_siniestro_unico',
'fallecidos','heridos','ilesos','dia_semana','es_fin_semana',
'configuracion_de_la_via','luminosidad','latitud','longitud',
].join(','),
inv: [
'id_feu','tipo_involucrado','marca','modelo','color','ano','mes',
].join(','),
per: [
'id_feu','genero','edad','rol_persona_involucrada','ubicacion_vehiculo',
'estado_ocupante_inicio','estado_ocupante_final','categoria_siniestro',
'cinturon_seguridad','casco','airbag','prueba_alcohol',
'fuga','nacionalidad','ano','mes',
].join(','),
}
const MAX_ROWS = 4999 // ajustá si tu dataset es mayor
async function queryByAnoMes(tabla, select, año, mes) {
let q = supabase.from(tabla).select(select).eq('ano', año).range(0, MAX_ROWS)
if (mes > 0) q = q.eq('mes', mes)
const { data, error } = await q
return { data: data ?? [], error }
}
export function useSiniestralidad(año, mes) {
const [siniestros, setSiniestros] = useState([])
const [involucrados, setInvolucrados] = useState([])
const [personas, setPersonas] = useState([])
const [loading, setLoading] = useState(true)
const [debug, setDebug] = useState(null)
const [error, setError] = useState(null)
useEffect(() => {
let cancelled = false
async function cargar() {
setLoading(true)
// ── Las 3 consultas en PARALELO — cada una por ano/mes ─
const [resS, resI, resP] = await Promise.all([
queryByAnoMes(T.siniestros, SEL.sin, año, mes),
queryByAnoMes(T.involucrados, SEL.inv, año, mes),
queryByAnoMes(T.personas, SEL.per, año, mes),
])
const log = {
año_consultado: año,
mes_consultado: mes > 0 ? mes : 'todos',
siniestros: {
tabla: T.siniestros,
registros: resS.data.length,
error: resS.error?.message ?? null,
},
involucrados: {
tabla: T.involucrados,
registros: resI.data.length,
error: resI.error?.message ?? null,
},
personas: {
tabla: T.personas,
registros: resP.data.length,
error: resP.error?.message ?? null,
},
}
if (cancelled) return
const errorEntries = [resS.error, resI.error, resP.error].filter(Boolean)
const errorMessage = errorEntries.length
? errorEntries.map((err) => err?.message || String(err)).join(' | ')
: null
setSiniestros(resS.data)
setInvolucrados(resI.data)
setPersonas(resP.data)
setDebug(log)
setError(errorMessage)
setLoading(false)
}
cargar()
return () => { cancelled = true }
}, [año, mes])
return { siniestros, involucrados, personas, loading, debug, error }
}