Files
GRH/src/pages/concentrators/useConcentrators.ts
2026-02-03 00:28:58 -06:00

257 lines
7.0 KiB
TypeScript

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<SampleView>("GENERAL");
const [loadingProjects, setLoadingProjects] = useState(true);
const [loadingConcentrators, setLoadingConcentrators] = useState(true);
const [loadingMeterTypes, setLoadingMeterTypes] = useState(true);
const [projects, setProjects] = useState<Project[]>([]);
const [allProjects, setAllProjects] = useState<string[]>([]);
const [selectedProject, setSelectedProject] = useState("");
const [meterTypes, setMeterTypes] = useState<MeterType[]>([]);
const [selectedMeterTypeId, setSelectedMeterTypeId] = useState<string>("");
const [concentrators, setConcentrators] = useState<Concentrator[]>([]);
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<Exclude<SampleView, "GENERAL">, ConcentratorType> = {
LORA: "LORA",
LORAWAN: "LORAWAN",
GRANDES: "GRANDES",
};
const targetType = typeMap[sampleView as Exclude<SampleView, "GENERAL">];
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<Exclude<SampleView, "GENERAL">, ConcentratorType> = {
LORA: "LORA",
LORAWAN: "LORAWAN",
GRANDES: "GRANDES",
};
const targetType = typeMap[sampleView as Exclude<SampleView, "GENERAL">];
concentratorsToCount = concentrators.filter((c) => c.type === targetType);
}
const counts = concentratorsToCount.reduce<Record<string, number>>((acc, c) => {
const project = c.projectId ?? "SIN PROYECTO";
acc[project] = (acc[project] ?? 0) + 1;
return acc;
}, {});
const projectNameMap = projects.reduce<Record<string, string>>((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,
};
}