diff --git a/src/App.css b/src/App.css deleted file mode 100644 index e69de29..0000000 diff --git a/src/App.jsx b/src/App.jsx index ba7f19b..2b84eb6 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,6 +1,7 @@ import React from 'react'; import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; -import Dashboard from './Dashboard'; +import Dashboard from './screens/DashboardTerminacion'; +import DashboardCarnet from './screens/DashboardCarnet'; export default function App() { return ( @@ -8,6 +9,7 @@ export default function App() { } /> } /> + } /> + `${linkBase} ${isActive ? linkActive : linkInactive}`} + > + Encuesta Terminacion + + `${linkBase} ${isActive ? linkActive : linkInactive}`} + > + Carnets + + + ); +} diff --git a/src/screens/DashboardCarnet.jsx b/src/screens/DashboardCarnet.jsx new file mode 100644 index 0000000..be46272 --- /dev/null +++ b/src/screens/DashboardCarnet.jsx @@ -0,0 +1,208 @@ +import React, { useState, useEffect } from 'react'; +import { supabase } from '../services/supabaseClient'; +import { BarChart, Bar, Cell, XAxis, YAxis, Tooltip, Legend, ResponsiveContainer, CartesianGrid } from 'recharts'; +import NavBar from '../components/NavBar'; + +const CHART_PALETTE = ['#6CC24A', '#4F758B', '#A4D65E', '#5B7F95', '#C4D600', '#6B8FA3', '#3E6B8A', '#8FBF5A']; + +export default function DashboardCarnet() { + const [rawData, setRawData] = useState([]); + const [loading, setLoading] = useState(true); + const [clientes, setClientes] = useState([]); + const [filtroCliente, setFiltroCliente] = useState(''); + const [paginaActual, setPaginaActual] = useState(1); + + useEffect(() => { + fetchData(); + }, []); + + useEffect(() => { + setPaginaActual(1); + const uniqueClientes = [...new Set(rawData.map(item => item.cliente_proyecto).filter(Boolean))]; + setClientes(uniqueClientes); + }, [rawData]); + + const fetchData = async () => { + setLoading(true); + const { data, error } = await supabase + .from('carnet_empleados_creados_glm') + .select('*') + .order('created_at', { ascending: false }); + + if (error) { + console.error('Error fetching data:', error); + } else { + setRawData(data); + } + setLoading(false); + }; + + const datosFiltrados = filtroCliente + ? rawData.filter(item => item.cliente_proyecto === filtroCliente) + : rawData; + + const totalCarnets = datosFiltrados.length; + + const conteoPorCliente = rawData.reduce((acc, curr) => { + const cliente = curr.cliente_proyecto || 'Sin cliente'; + acc[cliente] = (acc[cliente] || 0) + 1; + return acc; + }, {}); + + const chartDataCliente = Object.keys(conteoPorCliente).map((cliente, index) => ({ + name: cliente, + value: conteoPorCliente[cliente], + fill: CHART_PALETTE[index % CHART_PALETTE.length] + })); + + const filasPorPagina = 20; + const totalPaginas = Math.ceil(datosFiltrados.length / filasPorPagina) || 1; + const indiceUltimoItem = paginaActual * filasPorPagina; + const indicePrimerItem = indiceUltimoItem - filasPorPagina; + + if (loading) return
Cargando datos...
; + + return ( +
+ + {/* HEADER GLM */} +
+
+ Logo GLM +
+
+

Dashboard de Carnets

+

Conteo de carnets creados por cliente / proyecto

+
+
+ + {/* NAVEGACIÓN GLM */} + + + {/* FILTRO GLM */} +
+
+ + +
+
+ +
+
+ + {/* KPI GLM */} +
+
+

Total Carnets Creados

+

{totalCarnets}

+
+
+

Clientes / Proyectos

+

{clientes.length}

+

distintos en el histórico

+
+
+ + {/* GRÁFICA GLM */} +
+

Carnets por Cliente / Proyecto

+
+ + + + + + + + + {chartDataCliente.map((entry, index) => ( + + ))} + + + +
+
+ + {/* TABLA GLM */} +
+
+

Detalle de Carnets

+
+
+ + + + + + + + + + {chartDataCliente.map((row, idx) => ( + + + + + ))} + +
FechaCliente / ProyectoCarnets
{row.name}{row.value}
+
+ + {/* Controles de Pagina */} +
+
+ {datosFiltrados.length > 0 + ? `Mostrando registros ${indicePrimerItem + 1} - ${Math.min(indiceUltimoItem, datosFiltrados.length)} de ${datosFiltrados.length}` + : 'No hay registros para mostrar' + } +
+
+ + + Página {paginaActual} de {totalPaginas} + + +
+
+
+
+ ); +} diff --git a/src/Dashboard.jsx b/src/screens/DashboardTerminacion.jsx similarity index 98% rename from src/Dashboard.jsx rename to src/screens/DashboardTerminacion.jsx index 31b4250..0339663 100644 --- a/src/Dashboard.jsx +++ b/src/screens/DashboardTerminacion.jsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; -import { supabase } from './services/supabaseClient'; +import { supabase } from '../services/supabaseClient'; import { PieChart, Pie, Cell, Tooltip, Legend, ResponsiveContainer } from 'recharts'; +import NavBar from '../components/NavBar'; const GLM_COLORS = { positivo: '#6CC24A', neutro: '#F0C75E', negativo: '#FF6A13' }; const CHART_PALETTE = ['#6CC24A', '#4F758B', '#A4D65E', '#5B7F95', '#C4D600', '#6B8FA3']; @@ -55,7 +56,7 @@ export default function Dashboard() { if (filtroPosicion) result = result.filter(item => item.posicion === filtroPosicion); if (filtroHomologacion) result = result.filter(item => item.homologacion_ia === filtroHomologacion); if (filtroPais) result = result.filter(item => item.pais === filtroPais); - + // Ordenar por fecha de más reciente a más vieja result = [...result].sort((a, b) => { const dateA = a.timestamp ? new Date(a.timestamp) : 0; @@ -107,6 +108,9 @@ export default function Dashboard() { + {/* NAVEGACIÓN GLM */} + + {/* FILTROS GLM */}
@@ -263,7 +267,7 @@ export default function Dashboard() { {/* Controles de Pagina */}
- {totalRegistros > 0 + {totalRegistros > 0 ? `Mostrando registros ${indicePrimerItem + 1} - ${Math.min(indiceUltimoItem, totalRegistros)} de ${totalRegistros}` : 'No hay registros para mostrar' }