import { useEffect, useMemo, useState } from "react"; import { fetchConcentrators, type Concentrator, type ConcentratorType, } from "../../api/concentrators"; import { fetchProjects, type Project } from "../../api/projects"; import { fetchMeterTypes, type MeterType } from "../../api/meterTypes"; import { getCurrentUserRole, getCurrentUserProjectId } from "../../api/auth"; import type { ProjectCard, SampleView } from "./ConcentratorsPage"; export function useConcentrators() { const userRole = getCurrentUserRole(); const userProjectId = getCurrentUserProjectId(); const isAdmin = userRole?.toUpperCase() === 'ADMIN'; const [sampleView, setSampleView] = useState("GENERAL"); const [loadingProjects, setLoadingProjects] = useState(true); const [loadingConcentrators, setLoadingConcentrators] = useState(true); const [loadingMeterTypes, setLoadingMeterTypes] = useState(true); const [projects, setProjects] = useState([]); const [allProjects, setAllProjects] = useState([]); const [selectedProject, setSelectedProject] = useState(""); const [meterTypes, setMeterTypes] = useState([]); const [selectedMeterTypeId, setSelectedMeterTypeId] = useState(""); const [concentrators, setConcentrators] = useState([]); const [filteredConcentrators, setFilteredConcentrators] = useState< Concentrator[] >([]); const isGeneral = sampleView === "GENERAL"; const sampleViewLabel = useMemo(() => { switch (sampleView) { case "GENERAL": return "General"; case "LORA": return "LoRa"; case "LORAWAN": return "LoRaWAN"; case "GRANDES": return "Grandes consumidores"; default: return "General"; } }, [sampleView]); const visibleProjects = useMemo( () => isAdmin ? allProjects : userProjectId ? [userProjectId] : [], [allProjects, isAdmin, userProjectId] ); const loadMeterTypes = async () => { setLoadingMeterTypes(true); try { const meterTypesData = await fetchMeterTypes(); setMeterTypes(meterTypesData); } catch (err) { console.error("Error loading meter types:", err); setMeterTypes([]); } finally { setLoadingMeterTypes(false); } }; const loadProjects = async () => { setLoadingProjects(true); try { const projectsData = await fetchProjects(); setProjects(projectsData); const projectIds = projectsData.map((p) => p.id); setAllProjects(projectIds); setSelectedProject((prev) => { if (prev) return prev; if (!isAdmin && userProjectId) { return userProjectId; } return projectIds[0] ?? ""; }); } catch (err) { console.error("Error loading projects:", err); setProjects([]); setAllProjects([]); } finally { setLoadingProjects(false); } }; const loadConcentrators = async () => { setLoadingConcentrators(true); try { const data = await fetchConcentrators(); setConcentrators(data); } catch (err) { console.error("Error loading concentrators:", err); setConcentrators([]); } finally { setLoadingConcentrators(false); } }; useEffect(() => { loadMeterTypes(); loadProjects(); loadConcentrators(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // view changes useEffect(() => { loadProjects(); loadConcentrators(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [sampleView]); // auto select single visible project useEffect(() => { if (!isGeneral) return; if (!selectedProject && visibleProjects.length === 1) { setSelectedProject(visibleProjects[0]); } }, [visibleProjects, selectedProject, isGeneral]); useEffect(() => { let filtered = concentrators; if (selectedProject) { filtered = filtered.filter((c) => c.projectId === selectedProject); } if (!isGeneral) { const typeMap: Record, ConcentratorType> = { LORA: "LORA", LORAWAN: "LORAWAN", GRANDES: "GRANDES", }; const targetType = typeMap[sampleView as Exclude]; filtered = filtered.filter((c) => c.type === targetType); } setFilteredConcentrators(filtered); }, [selectedProject, concentrators, isGeneral, sampleView]); // sidebar cards (general) const projectsDataGeneral: ProjectCard[] = useMemo(() => { let concentratorsToCount = concentrators; if (!isGeneral) { const typeMap: Record, ConcentratorType> = { LORA: "LORA", LORAWAN: "LORAWAN", GRANDES: "GRANDES", }; const targetType = typeMap[sampleView as Exclude]; concentratorsToCount = concentrators.filter((c) => c.type === targetType); } const counts = concentratorsToCount.reduce>((acc, c) => { const project = c.projectId ?? "SIN PROYECTO"; acc[project] = (acc[project] ?? 0) + 1; return acc; }, {}); const projectNameMap = projects.reduce>((acc, p) => { acc[p.id] = p.name; return acc; }, {}); const baseRegion = "Baja California"; const baseContact = "Operaciones"; const baseLastSync = "Hace 1 h"; let filteredProjects = visibleProjects; if (selectedMeterTypeId) { filteredProjects = filteredProjects.filter((projectId) => { const project = projects.find((p) => p.id === projectId); return project?.meterTypeId === selectedMeterTypeId; }); } return filteredProjects.map((projectId) => ({ id: projectId, name: projectNameMap[projectId] ?? projectId, region: baseRegion, projects: 1, concentrators: counts[projectId] ?? 0, activeAlerts: 0, lastSync: baseLastSync, contact: baseContact, status: "ACTIVO" as const, })); }, [concentrators, visibleProjects, projects, isGeneral, sampleView, selectedMeterTypeId]); const projectsData: ProjectCard[] = useMemo(() => { return projectsDataGeneral; }, [projectsDataGeneral]); useEffect(() => { if (projectsData.length > 0) { const firstProject = projectsData[0]; const currentProjectExists = projectsData.find((p) => p.id === selectedProject); if (!selectedProject || !currentProjectExists) { setSelectedProject(firstProject.id); } } else { if (selectedProject) { setSelectedProject(""); } } }, [projectsData]); return { // view sampleView, setSampleView, sampleViewLabel, isGeneral, // loading loadingProjects, loadingConcentrators, loadingMeterTypes, // projects allProjects, visibleProjects, projectsData, selectedProject, setSelectedProject, meterTypes, selectedMeterTypeId, setSelectedMeterTypeId, // data concentrators, setConcentrators, filteredConcentrators, // actions loadConcentrators, }; }