import React, { useState, useEffect, useMemo } from 'react'; import { supabaseData } from '../services/supabaseClient'; import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, CartesianGrid, Cell } from 'recharts'; import NavBar from '../components/NavBar'; const CHART_PALETTE = ['#6CC24A', '#4F758B', '#A4D65E', '#5B7F95', '#C4D600', '#6B8FA3', '#3E6B8A', '#8FBF5A']; export default function DashboardGLMWAY() { const [rawData, setRawData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [filtroAnio, setFiltroAnio] = useState(''); const [filtroMes, setFiltroMes] = useState(''); const [filtroPais, setFiltroPais] = useState(''); const [filtroDivision, setFiltroDivision] = useState(''); const [filtroCoordinador, setFiltroCoordinador] = useState(''); const [filtroFacilitador, setFiltroFacilitador] = useState(''); const [evaluaciones, setEvaluaciones] = useState([]); useEffect(() => { fetchData(); }, []); const fetchData = async () => { setLoading(true); setError(null); console.log('[DashboardGLMWAY] Iniciando fetch...'); const [inscritosResult, evaluacionesResult] = await Promise.all([ supabaseData .from('inscritos_glmway') .select('*') .order('fecha_ingreso', { ascending: false }), supabaseData .from('glmway_evaluacion_kpi') .select('evaluaciones_enviadas, evaluaciones_resueltas'), ]); if (inscritosResult.error) { console.error('[DashboardGLMWAY] Error de Supabase:', { message: inscritosResult.error.message, details: inscritosResult.error.details, hint: inscritosResult.error.hint, code: inscritosResult.error.code, }); setError(inscritosResult.error.message || 'Error al cargar los datos de empleados.'); } else { console.log('[DashboardGLMWAY] Datos recibidos:', inscritosResult.data?.length ?? 0, 'registros'); setRawData(inscritosResult.data ?? []); } if (evaluacionesResult.error) { console.error('[DashboardGLMWAY] Error evaluaciones:', evaluacionesResult.error); } else { setEvaluaciones(evaluacionesResult.data ?? []); } setLoading(false); }; const aniosDisponibles = useMemo(() => { const anios = new Set(); rawData.forEach(item => { if (item.fecha_ingreso) { const anio = item.fecha_ingreso.substring(0, 4); anios.add(anio); } }); return Array.from(anios).sort((a, b) => b - a); }, [rawData]); const mesesDisponibles = useMemo(() => { let datosFiltrados = rawData; if (filtroAnio) { datosFiltrados = datosFiltrados.filter(item => item.fecha_ingreso?.startsWith(filtroAnio)); } const meses = new Set(); datosFiltrados.forEach(item => { if (item.fecha_ingreso) { const mes = item.fecha_ingreso.substring(5, 7); meses.add(mes); } }); return Array.from(meses).sort(); }, [rawData, filtroAnio]); const paisesDisponibles = useMemo(() => { const paises = new Set(); rawData.forEach(item => { if (item.pais) paises.add(item.pais); }); return Array.from(paises).sort(); }, [rawData]); const divisionesDisponibles = useMemo(() => { const divisiones = new Set(); rawData.forEach(item => { if (item.division) divisiones.add(item.division); }); return Array.from(divisiones).sort(); }, [rawData]); const coordinadoresDisponibles = useMemo(() => { const coordinadores = new Set(); rawData.forEach(item => { if (item.coordinador_rrhh) coordinadores.add(item.coordinador_rrhh); }); return Array.from(coordinadores).sort(); }, [rawData]); const facilitadoresDisponibles = useMemo(() => { const facilitadores = new Set(); rawData.forEach(item => { if (item.instructor) facilitadores.add(item.instructor); }); return Array.from(facilitadores).sort(); }, [rawData]); const datosFiltrados = useMemo(() => { return rawData.filter(item => { if (!item.fecha_ingreso) return false; if (filtroAnio && !item.fecha_ingreso.startsWith(filtroAnio)) return false; if (filtroMes && !item.fecha_ingreso.substring(5, 7).startsWith(filtroMes)) return false; if (filtroPais && item.pais !== filtroPais) return false; if (filtroDivision && item.division !== filtroDivision) return false; if (filtroCoordinador && item.coordinador_rrhh !== filtroCoordinador) return false; if (filtroFacilitador && item.instructor !== filtroFacilitador) return false; return true; }); }, [rawData, filtroAnio, filtroMes, filtroPais, filtroDivision, filtroCoordinador, filtroFacilitador]); const mesesNombres = { '01': 'Enero', '02': 'Febrero', '03': 'Marzo', '04': 'Abril', '05': 'Mayo', '06': 'Junio', '07': 'Julio', '08': 'Agosto', '09': 'Septiembre', '10': 'Octubre', '11': 'Noviembre', '12': 'Diciembre' }; const totalEmpleados = datosFiltrados.length; const totalParticipantes = useMemo(() => { return datosFiltrados.filter(item => item.asistio_evento_glmway === true).length; }, [datosFiltrados]); const totalEvaluacionesEnviadas = useMemo(() => { return evaluaciones.reduce((sum, item) => sum + (item.evaluaciones_enviadas || 0), 0); }, [evaluaciones]); const totalEvaluacionesResueltas = useMemo(() => { return evaluaciones.reduce((sum, item) => sum + (item.evaluaciones_resueltas || 0), 0); }, [evaluaciones]); const rankingCoordinadores = useMemo(() => { const conteo = {}; datosFiltrados.forEach(item => { if (item.coordinador_rrhh && item.asistio_evento_glmway === true) { conteo[item.coordinador_rrhh] = (conteo[item.coordinador_rrhh] || 0) + 1; } }); return Object.entries(conteo) .map(([name, value]) => ({ name, value })) .sort((a, b) => b.value - a.value); }, [datosFiltrados]); if (loading) return (

Cargando datos...

); if (error) return (
⚠️

Error al cargar datos

{error}

Revisa la consola del navegador (F12) para más detalles.

); return (
{/* HEADER GLM */}
Logo GLM

Dashboard GLMWAY

Fecha de ingreso de empleados

{/* NAVEGACIÓN GLM */} {/* FILTROS GLM */}
{/* KPI GLM */}

Total Empleados

{totalEmpleados}

Participaron en Sesiones

{totalEmpleados > 0 ? Math.round((totalParticipantes / totalEmpleados) * 100) : 0}%

{totalParticipantes} de {totalEmpleados} inscritos

Evaluaciones Enviadas

{totalEvaluacionesEnviadas}

Evaluaciones Completadas

{totalEvaluacionesResueltas}

{/* RANKING COORDINADORES RH */}

Ranking de Coordinadores RH

[value, 'Empleados']} /> {rankingCoordinadores.map((entry, index) => ( ))}
); }