Files
GRH/src/pages/concentrators/useConcentrators.ts
2026-02-01 18:30:28 -06:00

210 lines
5.6 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 type { ProjectCard, SampleView } from "./ConcentratorsPage";
type User = {
role: "SUPER_ADMIN" | "USER";
project?: string;
};
export function useConcentrators(currentUser: User) {
const [sampleView, setSampleView] = useState<SampleView>("GENERAL");
const [loadingProjects, setLoadingProjects] = useState(true);
const [loadingConcentrators, setLoadingConcentrators] = useState(true);
const [projects, setProjects] = useState<Project[]>([]);
const [allProjects, setAllProjects] = useState<string[]>([]);
const [selectedProject, setSelectedProject] = useState("");
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(
() =>
currentUser.role === "SUPER_ADMIN"
? allProjects
: currentUser.project
? [currentUser.project]
: [],
[allProjects, currentUser.role, currentUser.project]
);
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 (currentUser.role !== "SUPER_ADMIN" && currentUser.project) {
return currentUser.project;
}
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);
}
};
// init - load projects and concentrators
useEffect(() => {
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";
return visibleProjects.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]);
const projectsData: ProjectCard[] = useMemo(() => {
return projectsDataGeneral;
}, [projectsDataGeneral]);
return {
// view
sampleView,
setSampleView,
sampleViewLabel,
isGeneral,
// loading
loadingProjects,
loadingConcentrators,
// projects
allProjects,
visibleProjects,
projectsData,
selectedProject,
setSelectedProject,
// data
concentrators,
setConcentrators,
filteredConcentrators,
// actions
loadConcentrators,
};
}