257 lines
7.0 KiB
TypeScript
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,
|
|
};
|
|
}
|