Files
CPLv4.0/components/main/kabelueberwachung/kue705FO/Charts/IsoMeasurementChart/IsoChartActionBar.tsx

374 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
// /components/main/kabelueberwachung/kue705FO/Charts/IsoMeasurementChart/IsoChartActionBar.tsx
import React from "react";
import DateRangePicker from "@/components/common/DateRangePicker";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "@/redux/store";
import {
setIsoMeasurementCurveChartData,
setSelectedMode,
setChartOpen,
setLoading,
} from "@/redux/slices/kabelueberwachungChartSlice";
import { setBrushRange } from "@/redux/slices/brushSlice";
import { getMessagesThunk } from "@/redux/thunks/getMessagesThunk";
import { Listbox } from "@headlessui/react";
//-----------------------------------------------------------------------------------useIsoChartLoader
export const useIsoChartLoader = () => {
const dispatch = useDispatch();
const { vonDatum, bisDatum, selectedMode, slotNumber } = useSelector(
(state: RootState) => state.kabelueberwachungChartSlice
);
const hasShownNoDataAlert = React.useRef(false);
const formatDate = (dateString: string) => {
const [year, month, day] = dateString.split("-");
return `${year};${month};${day}`;
};
const getApiUrl = (mode: "DIA0" | "DIA1" | "DIA2", slotNumber: number) => {
const type = 3; // Fest auf Isolationswiderstand gesetzt
const typeFolder = "isolationswiderstand";
let url: string;
if (process.env.NODE_ENV === "development") {
url = `/api/cpl/slotDataAPIHandler?slot=${slotNumber}&messart=${typeFolder}&dia=${mode}&vonDatum=${vonDatum}&bisDatum=${bisDatum}`;
} else {
url = `${window.location.origin}/CPL?seite.ACP&${mode}=${formatDate(
vonDatum
)};${formatDate(bisDatum)};${slotNumber};${type};`;
}
console.log("API URL:", url);
return url;
};
const loadIsoChartData = async () => {
if (slotNumber === null) return;
dispatch(setLoading(true));
dispatch(setChartOpen(false));
dispatch(setIsoMeasurementCurveChartData([]));
const startTime = Date.now();
const MIN_LOADING_TIME_MS = 1000;
try {
const apiUrl = getApiUrl(selectedMode, slotNumber);
const response = await fetch(apiUrl);
const data = await response.json();
const waitTime = Math.max(
0,
MIN_LOADING_TIME_MS - (Date.now() - startTime)
);
await new Promise((res) => setTimeout(res, waitTime));
if (Array.isArray(data) && data.length > 0) {
dispatch(setIsoMeasurementCurveChartData(data));
dispatch(setChartOpen(true));
} else {
dispatch(setIsoMeasurementCurveChartData([]));
dispatch(setChartOpen(false));
if (!hasShownNoDataAlert.current) {
alert("⚠️ Keine Messdaten im gewählten Zeitraum gefunden");
hasShownNoDataAlert.current = true;
}
}
} catch (err) {
console.error("❌ Fehler beim Laden:", err);
alert("❌ Fehler beim Laden.");
} finally {
dispatch(setLoading(false));
}
};
return { loadIsoChartData };
};
//-----------------------------------------------------------------------------------useIsoDataLoader Hook
export const useIsoDataLoader = () => {
const dispatch = useDispatch();
const { vonDatum, bisDatum, selectedMode, slotNumber } = useSelector(
(state: RootState) => state.kabelueberwachungChartSlice
);
const formatDate = (dateString: string) => {
const [year, month, day] = dateString.split("-");
return `${year};${month};${day}`;
};
const getApiUrl = (mode: "DIA0" | "DIA1" | "DIA2", slotNumber: number) => {
const type = 3; // Fest auf Isolationswiderstand gesetzt
const typeFolder = "isolationswiderstand";
const baseUrl =
process.env.NODE_ENV === "development"
? `/api/cpl/slotDataAPIHandler?slot=${slotNumber}&messart=${typeFolder}&dia=${mode}&vonDatum=${vonDatum}&bisDatum=${bisDatum}`
: `${window.location.origin}/CPL?seite.ACP&${mode}=${formatDate(
vonDatum
)};${formatDate(bisDatum)};${slotNumber};${type};`;
return baseUrl;
};
const loadData = async () => {
if (slotNumber === null) {
console.log("⚠️ Kein Slot ausgewählt - automatisches Laden übersprungen");
return;
}
const apiUrl = getApiUrl(selectedMode, slotNumber);
if (!apiUrl) return;
dispatch(setLoading(true));
dispatch(setChartOpen(false));
dispatch(setIsoMeasurementCurveChartData([]));
const MIN_LOADING_TIME_MS = 1000;
const startTime = Date.now();
try {
const response = await fetch(apiUrl, {
method: "GET",
headers: { "Content-Type": "application/json" },
});
if (!response.ok) throw new Error(`Fehler: ${response.status}`);
const jsonData = await response.json();
const elapsedTime = Date.now() - startTime;
const waitTime = Math.max(0, MIN_LOADING_TIME_MS - elapsedTime);
await new Promise((resolve) => setTimeout(resolve, waitTime));
console.log("▶️ Automatisches Laden - Isolationswiderstand-Daten für:");
console.log(" Slot:", slotNumber);
console.log(" Modus:", selectedMode);
console.log(" Von:", vonDatum);
console.log(" Bis:", bisDatum);
if (Array.isArray(jsonData) && jsonData.length > 0) {
dispatch(setIsoMeasurementCurveChartData(jsonData));
dispatch(setChartOpen(true));
} else {
console.log(
"⚠️ Keine Messdaten im gewählten Zeitraum gefunden (automatisches Laden)"
);
dispatch(setIsoMeasurementCurveChartData([]));
dispatch(setChartOpen(false));
}
} catch (err) {
console.error("❌ Fehler beim automatischen Laden der Daten:", err);
} finally {
dispatch(setLoading(false));
}
};
return { loadData };
};
//-----------------------------------------------------------------------------------IsoChartActionBar
const IsoChartActionBar: React.FC = () => {
const dispatch = useDispatch();
const { vonDatum, bisDatum, selectedMode, slotNumber, chartTitle } =
useSelector((state: RootState) => state.kabelueberwachungChartSlice);
// Aus DateRangePicker-Slice kommen die Werte, die der User im UI wählt
const { vonDatum: pickerVonDatum, bisDatum: pickerBisDatum } = useSelector(
(state: RootState) => state.dateRangePicker
);
const formatDate = (dateString: string) => {
const [year, month, day] = dateString.split("-");
return `${year};${month};${day}`;
};
const getApiUrl = (
mode: "DIA0" | "DIA1" | "DIA2",
slotNumber: number,
fromDate: string,
toDate: string
) => {
const type = 3; // Fest auf Isolationswiderstand gesetzt
const typeFolder = "isolationswiderstand";
const baseUrl =
process.env.NODE_ENV === "development"
? `/api/cpl/slotDataAPIHandler?slot=${slotNumber}&messart=${typeFolder}&dia=${mode}&vonDatum=${fromDate}&bisDatum=${toDate}`
: `${window.location.origin}/CPL?seite.ACP&${mode}=${formatDate(
fromDate
)};${formatDate(toDate)};${slotNumber};${type};`;
console.log("baseUrl", baseUrl);
return baseUrl;
};
const handleFetchData = async () => {
if (slotNumber === null) {
alert("⚠️ Bitte zuerst einen KÜ auswählen!");
return;
}
// Wenn Meldungen-Ansicht aktiv ist, dann Meldungen laden
if (chartTitle === "Meldungen") {
try {
dispatch(setLoading(true));
const fromDate = pickerVonDatum ?? vonDatum;
const toDate = pickerBisDatum ?? bisDatum;
await dispatch(getMessagesThunk({ fromDate, toDate })).unwrap();
} catch (err) {
console.error("❌ Fehler beim Laden der Meldungen:", err);
alert("❌ Fehler beim Laden der Meldungen.");
} finally {
dispatch(setLoading(false));
}
return;
}
// Messkurve (ISO) laden
const fromDate = pickerVonDatum ?? vonDatum;
const toDate = pickerBisDatum ?? bisDatum;
const apiUrl = getApiUrl(selectedMode, slotNumber, fromDate, toDate);
if (!apiUrl) return;
dispatch(setLoading(true));
dispatch(setChartOpen(false));
dispatch(setIsoMeasurementCurveChartData([]));
const MIN_LOADING_TIME_MS = 1000;
const startTime = Date.now();
try {
const response = await fetch(apiUrl, {
method: "GET",
headers: { "Content-Type": "application/json" },
});
if (!response.ok) throw new Error(`Fehler: ${response.status}`);
const jsonData = await response.json();
const elapsedTime = Date.now() - startTime;
const waitTime = Math.max(0, MIN_LOADING_TIME_MS - elapsedTime);
await new Promise((resolve) => setTimeout(resolve, waitTime));
console.log("▶️ Lade Isolationswiderstand-Daten für:");
console.log(" Slot:", slotNumber);
console.log(" Modus:", selectedMode);
console.log(" Von:", fromDate);
console.log(" Bis:", toDate);
console.log(" URL:", apiUrl);
console.log(" Daten:", jsonData);
if (Array.isArray(jsonData) && jsonData.length > 0) {
dispatch(setIsoMeasurementCurveChartData(jsonData));
dispatch(setChartOpen(true));
} else {
alert("⚠️ Keine Messdaten im gewählten Zeitraum gefunden.");
dispatch(setIsoMeasurementCurveChartData([]));
dispatch(setChartOpen(false));
}
} catch (err) {
console.error("❌ Fehler beim Laden der Daten:", err);
alert("❌ Fehler beim Laden der Daten.");
} finally {
dispatch(setLoading(false));
}
};
return (
<div className="flex justify-between items-center p-2 bg-gray-100 rounded-lg space-x-2">
<div className="flex items-center">
<label className="text-sm font-semibold">
{slotNumber !== null ? slotNumber + 1 : "-"}
</label>
</div>
<div className="flex items-center space-x-2">
{/* DateRangePicker für beide Ansichten sichtbar, da Meldungen auch datumsabhängig sind */}
<div>
<DateRangePicker />
</div>
{/* DIA0-DIA2 Dropdown - Platz reservieren, aber ausblenden wenn Meldungen */}
<div
style={{
visibility: chartTitle === "Messkurve" ? "visible" : "hidden",
}}
>
<Listbox
value={selectedMode}
onChange={(value) => {
dispatch(setSelectedMode(value));
dispatch(setBrushRange({ startIndex: 0, endIndex: 0 }));
}}
>
<div className="relative w-48">
<Listbox.Button className="w-full border px-3 py-1 rounded text-left bg-white flex justify-between items-center text-sm">
<span>
{
{
DIA0: "Alle Messwerte",
DIA1: "Stündliche Werte",
DIA2: "Tägliche Werte",
}[selectedMode]
}
</span>
<svg
className="w-5 h-5 text-gray-400"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M5.23 7.21a.75.75 0 011.06.02L10 10.585l3.71-3.355a.75.75 0 111.02 1.1l-4.25 3.85a.75.75 0 01-1.02 0l-4.25-3.85a.75.75 0 01.02-1.06z"
clipRule="evenodd"
/>
</svg>
</Listbox.Button>
<Listbox.Options className="absolute z-50 mt-1 w-full border rounded bg-white shadow max-h-60 overflow-auto text-sm">
{["DIA0", "DIA1", "DIA2"].map((mode) => (
<Listbox.Option
key={mode}
value={mode}
className={({ selected, active }) =>
`px-4 py-1 cursor-pointer ${
selected
? "bg-littwin-blue text-white"
: active
? "bg-gray-200"
: ""
}`
}
>
{
{
DIA0: "Alle Messwerte",
DIA1: "Stündliche Werte",
DIA2: "Tägliche Werte",
}[mode]
}
</Listbox.Option>
))}
</Listbox.Options>
</div>
</Listbox>
</div>
{/* Dropdown für Auswahl zwischen "Messkurve" und "Meldungen" - immer anzeigen */}
{/* Dropdown für Auswahl zwischen "Messkurve" und "Meldungen" entfernt */}
{/* Daten laden Button lädt je nach Ansicht Messkurve oder Meldungen */}
<button
onClick={handleFetchData}
className="px-4 py-1 bg-littwin-blue text-white rounded text-sm"
>
Daten laden
</button>
</div>
</div>
);
};
export default IsoChartActionBar;