diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 391e496..69c63f2 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -12,6 +12,8 @@ import { import { fetchMeters, type Meter } from "../api/meters"; import { getAuditLogs, type AuditLog } from "../api/audit"; import { fetchNotifications, type Notification } from "../api/notifications"; +import { getAllUsers, type User } from "../api/users"; +import { fetchProjects, type Project } from "../api/projects"; import { getCurrentUserRole } from "../api/auth"; import type { Page } from "../App"; import grhWatermark from "../assets/images/grhWatermark.png"; @@ -21,6 +23,7 @@ import grhWatermark from "../assets/images/grhWatermark.png"; type OrganismStatus = "ACTIVO" | "INACTIVO"; type Organism = { + id: string; name: string; region: string; projects: number; @@ -29,6 +32,7 @@ type Organism = { lastSync: string; contact: string; status: OrganismStatus; + projectId: string | null; }; type AlertItem = { company: string; type: string; time: string }; @@ -52,47 +56,7 @@ export default function Home({ const userRole = useMemo(() => getCurrentUserRole(), []); const isOperator = userRole?.toUpperCase() === 'OPERATOR'; - - /* ================= ORGANISMS (MOCK) ================= */ - - const organismsData: Organism[] = [ - { - name: "CESPT TIJUANA", - region: "Tijuana, BC", - projects: 6, - meters: 128, - activeAlerts: 0, - lastSync: "Hace 12 min", - contact: "Operaciones CESPT", - status: "ACTIVO", - }, - { - name: "CESPT TECATE", - region: "Tecate, BC", - projects: 3, - meters: 54, - activeAlerts: 1, - lastSync: "Hace 40 min", - contact: "Mantenimiento", - status: "ACTIVO", - }, - { - name: "CESPT MEXICALI", - region: "Mexicali, BC", - projects: 4, - meters: 92, - activeAlerts: 0, - lastSync: "Hace 1 h", - contact: "Supervisión", - status: "ACTIVO", - }, - ]; - - const [selectedOrganism, setSelectedOrganism] = useState( - organismsData[0]?.name ?? "CESPT TIJUANA" - ); - const [showOrganisms, setShowOrganisms] = useState(false); - const [organismQuery, setOrganismQuery] = useState(""); + const isAdmin = userRole?.toUpperCase() === 'ADMIN'; /* ================= METERS ================= */ @@ -112,12 +76,72 @@ export default function Home({ loadMeters(); }, []); - // TODO: Reemplazar cuando el backend mande el organismo real (ej: meter.organismName) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const getOrganismFromMeter = (_m: Meter): string => { - return "CESPT TIJUANA"; + const [projects, setProjects] = useState([]); + + const loadProjects = async () => { + try { + const data = await fetchProjects(); + setProjects(data); + } catch (err) { + console.error("Error loading projects:", err); + setProjects([]); + } }; + useEffect(() => { + loadProjects(); + }, []); + + const [users, setUsers] = useState([]); + const [loadingUsers, setLoadingUsers] = useState(false); + const [selectedOrganism, setSelectedOrganism] = useState("Todos"); + const [showOrganisms, setShowOrganisms] = useState(false); + const [organismQuery, setOrganismQuery] = useState(""); + + const loadUsers = async () => { + setLoadingUsers(true); + try { + const response = await getAllUsers({ is_active: true }); + setUsers(response.data); + + } catch (err) { + console.error("Error loading users:", err); + setUsers([]); + } finally { + setLoadingUsers(false); + } + }; + + useEffect(() => { + if (!isOperator) { + loadUsers(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const organismsData: Organism[] = useMemo(() => { + return users.map(user => { + const userMeters = user.project_id + ? meters.filter(m => m.projectId === user.project_id).length + : 0; + + const userProjects = user.project_id ? 1 : 0; + + return { + id: user.id, + name: user.name, + region: user.email, + projects: userProjects, + meters: userMeters, + activeAlerts: 0, + lastSync: user.last_login ? `Último acceso: ${new Date(user.last_login).toLocaleDateString()}` : "Nunca", + contact: user.role?.name || "N/A", + status: user.is_active ? "ACTIVO" : "INACTIVO", + projectId: user.project_id, + }; + }); + }, [users, meters]); + const [auditLogs, setAuditLogs] = useState([]); const [loadingAuditLogs, setLoadingAuditLogs] = useState(false); @@ -141,25 +165,53 @@ export default function Home({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const filteredMeters = useMemo( - () => meters.filter((m) => getOrganismFromMeter(m) === selectedOrganism), - [meters, selectedOrganism] - ); + const filteredMeters = useMemo(() => { + if (selectedOrganism === "Todos") { + return meters; + } + + const selectedUser = users.find(u => u.id === selectedOrganism); + if (!selectedUser || !selectedUser.project_id) { + return []; + } + + return meters.filter((m) => m.projectId === selectedUser.project_id); + }, [meters, selectedOrganism, users]); const filteredProjects = useMemo( () => [...new Set(filteredMeters.map((m) => m.projectName))].filter(Boolean) as string[], [filteredMeters] ); - const chartData = useMemo( - () => - filteredProjects.map((projectName) => ({ + const selectedUserProjectName = useMemo(() => { + if (selectedOrganism === "Todos") return null; + + const selectedUser = users.find(u => u.id === selectedOrganism); + if (!selectedUser || !selectedUser.project_id) return null; + + const project = projects.find(p => p.id === selectedUser.project_id); + return project?.name || null; + }, [selectedOrganism, users, projects]); + + const chartData = useMemo(() => { + if (selectedOrganism === "Todos") { + return filteredProjects.map((projectName) => ({ name: projectName, - meterCount: filteredMeters.filter((m) => m.projectName === projectName) - .length, - })), - [filteredProjects, filteredMeters] - ); + meterCount: filteredMeters.filter((m) => m.projectName === projectName).length, + })); + } + + if (selectedUserProjectName) { + const meterCount = filteredMeters.length; + + return [{ + name: selectedUserProjectName, + meterCount: meterCount, + }]; + } + + return []; + }, [selectedOrganism, filteredProjects, filteredMeters, selectedUserProjectName]); // eslint-disable-next-line @typescript-eslint/no-explicit-any const handleBarClick = (data: any) => { @@ -174,7 +226,7 @@ export default function Home({ const q = organismQuery.trim().toLowerCase(); if (!q) return organismsData; return organismsData.filter((o) => o.name.toLowerCase().includes(q)); - }, [organismQuery]); + }, [organismQuery, organismsData]); const [notifications, setNotifications] = useState([]); const [loadingNotifications, setLoadingNotifications] = useState(false); @@ -362,28 +414,32 @@ export default function Home({ - {/* Organismos Operadores */} -
-
-
-

Organismos Operadores

-

- Seleccionado:{" "} - {selectedOrganism} -

+ {isAdmin && ( +
+
+
+

Organismos Operadores

+

+ Seleccionado:{" "} + + {selectedOrganism === "Todos" + ? "Todos" + : organismsData.find(o => o.id === selectedOrganism)?.name || "Ninguno"} + +

+
+ +
- -
- - {showOrganisms && ( -
+ {showOrganisms && ( +
{/* Overlay */}
{/* Panel */} -
+
{/* Header */}
@@ -402,8 +458,7 @@ export default function Home({ Organismos Operadores

- Selecciona un organismo para filtrar la información del - dashboard. + Selecciona un organismo para filtrar la información del dashboard

@@ -431,12 +486,59 @@ export default function Home({ {/* List */}
- {filteredOrganisms.map((o) => { - const active = o.name === selectedOrganism; + {loadingUsers ? ( +
+
+
+ ) : ( + <> +
+
+
+

+ Todos los Organismos +

+

Ver todos los datos del sistema

+
+ + + TODOS + +
+ +
+ +
+
+ + {filteredOrganisms.map((o) => { + const active = o.id === selectedOrganism; return (
-
+
+
+ Rol + + {o.contact} + +
+ +
+ Email + + {o.region} + +
+
Proyectos @@ -480,25 +596,11 @@ export default function Home({
- Alertas activas - - {o.activeAlerts} - -
- -
- Última sync + Último acceso {o.lastSync}
- -
- Responsable - - {o.contact} - -
@@ -511,7 +613,7 @@ export default function Home({ : "bg-gray-900 text-white hover:bg-gray-800", ].join(" ")} onClick={() => { - setSelectedOrganism(o.name); + setSelectedOrganism(o.id); setShowOrganisms(false); setOrganismQuery(""); }} @@ -522,8 +624,10 @@ export default function Home({
); })} + + )} - {filteredOrganisms.length === 0 && ( + {!loadingUsers && filteredOrganisms.length === 0 && (
No se encontraron organismos.
@@ -532,13 +636,13 @@ export default function Home({ {/* Footer */}
- Nota: Las propiedades están en modo demostración hasta integrar - backend. + Mostrando {filteredOrganisms.length} organismo{filteredOrganisms.length !== 1 ? 's' : ''} de {users.length} total{users.length !== 1 ? 'es' : ''}
)} -
+
+ )}
{/* Gráfica */} @@ -552,21 +656,57 @@ export default function Home({
-
- - - - - - - - - -
+ {chartData.length === 0 && selectedOrganism !== "Todos" ? ( +
+

+ {selectedUserProjectName + ? "Este organismo no tiene medidores registrados" + : "Este organismo no tiene un proyecto asignado"} +

+ {selectedUserProjectName && ( +

+ Proyecto asignado: {selectedUserProjectName} +

+ )} +
+ ) : chartData.length === 0 ? ( +
+

No hay datos disponibles

+
+ ) : ( + <> +
+ + + + + + + + + +
+ + {selectedOrganism !== "Todos" && selectedUserProjectName && ( +
+
+
+ Proyecto del organismo: + {selectedUserProjectName} +
+
+ Total de medidores: + {filteredMeters.length} +
+
+
+ )} + + )}
{!isOperator && (