"use client"; // /components/main/kabelueberwachung/kue705FO/Charts/LoopMeasurementChart/LoopChartActionBar.tsx import React, { useEffect, useState, forwardRef, useImperativeHandle, } from "react"; import { useAppDispatch } from "@/redux/store"; import { getMessagesThunk } from "@/redux/thunks/getMessagesThunk"; import { RSL_DURATION_SECONDS, NODE_ENV } from "@/utils/env"; import DateRangePicker from "@/components/common/DateRangePicker"; import { useSelector } from "react-redux"; import { RootState } from "@/redux/store"; import { setLoopMeasurementCurveChartData, setSelectedMode, setChartOpen, setLoading, } from "@/redux/slices/kabelueberwachungChartSlice"; import { setBrushRange } from "@/redux/slices/brushSlice"; import { Listbox } from "@headlessui/react"; //-----------------------------------------------------------------------------------useLoopChartLoader export const useLoopChartLoader = () => { const dispatch = useAppDispatch(); const { vonDatum, bisDatum, selectedMode, selectedSlotType, 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", type: number, slotNumber: number ) => { const typeFolder = "schleifenwiderstand"; 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); // Hier wird die URL in der Konsole ausgegeben return url; }; const loadLoopChartData = async () => { const type = selectedSlotType === "schleifenwiderstand" ? 4 : 3; if (slotNumber === null) return; dispatch(setLoading(true)); dispatch(setChartOpen(false)); dispatch(setLoopMeasurementCurveChartData([])); const startTime = Date.now(); const MIN_LOADING_TIME_MS = 1000; try { const apiUrl = getApiUrl(selectedMode, type, 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(setLoopMeasurementCurveChartData(data)); dispatch(setChartOpen(true)); } else { dispatch(setLoopMeasurementCurveChartData([])); dispatch(setChartOpen(false)); if (!hasShownNoDataAlert.current) { alert("⚠️ Keine Messdaten im gewählten Zeitraum gefunden"); hasShownNoDataAlert.current = true; // ⬅️ Nur einmal zeigen } } } catch (err) { console.error("❌ Fehler beim Laden:", err); alert("❌ Fehler beim Laden."); } finally { dispatch(setLoading(false)); } }; return { loadLoopChartData }; }; //-----------------------------------------------------------------------------------LoopChartActionBar const LoopChartActionBar = forwardRef((_props, ref) => { const dispatch = useAppDispatch(); // RSL Progress State – Dauer konfigurierbar über NEXT_PUBLIC_RSL_DURATION_SECONDS const TOTAL_DURATION = RSL_DURATION_SECONDS; const [rslRunning, setRslRunning] = useState(false); const [rslProgress, setRslProgress] = useState(0); // Fortschritt aktualisieren useEffect(() => { if (!rslRunning) return; setRslProgress(0); const startedAt = Date.now(); const interval = setInterval(() => { const elapsed = Math.floor((Date.now() - startedAt) / 1000); if (elapsed >= TOTAL_DURATION) { setRslProgress(TOTAL_DURATION); setRslRunning(false); clearInterval(interval); // Optional automatische Daten-Nachladung anstoßen } else { setRslProgress(elapsed); } }, 1000); return () => clearInterval(interval); }, [rslRunning, TOTAL_DURATION]); const startRslProgress = () => { setRslRunning(true); setRslProgress(0); }; const { vonDatum, bisDatum, selectedMode, selectedSlotType, slotNumber, isLoading, } = useSelector((state: RootState) => state.kabelueberwachungChartSlice); const { chartTitle } = useSelector((state: RootState) => state.loopChartType); // Vom DateRangePicker-Slice (vom UI gewählte Werte) const { vonDatum: pickerVonDatum, bisDatum: pickerBisDatum } = useSelector( (state: RootState) => state.dateRangePicker ); const getApiUrl = ( mode: "DIA0" | "DIA1" | "DIA2", type: number, slotNumber: number, fromDate: string, toDate: string ) => { const typeFolder = "schleifenwiderstand"; 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 formatDate = (dateString: string) => { const [year, month, day] = dateString.split("-"); return `${year};${month};${day}`; }; const handleStartRSL = async () => { if (slotNumber === null) { alert("⚠️ Bitte zuerst einen KÜ auswählen!"); return; } const cgiUrl = `${window.location.origin}/CPL?kabelueberwachung.html&KS_${slotNumber}=1`; try { console.log("🚀 Starte RSL Messung für Slot:", slotNumber); console.log("📡 CGI URL:", cgiUrl); if (NODE_ENV === "development") { // DEV: externes Gerät mocken – sofort Erfolg simulieren await new Promise((r) => setTimeout(r, 200)); console.log("✅ [DEV] RSL Mock-Start ok für Slot", slotNumber); startRslProgress(); return; } const response = await fetch(cgiUrl); if (!response.ok) throw new Error(`CGI-Fehler: ${response.status}`); console.log("✅ RSL Messung gestartet für Slot", slotNumber); startRslProgress(); } catch (err) { console.error("❌ Fehler beim Starten der RSL Messung:", err); alert("❌ Fehler beim Starten der RSL Messung."); } }; const handleFetchData = async () => { const type = selectedSlotType === "schleifenwiderstand" ? 4 : 3; if (slotNumber === null) { alert("⚠️ Bitte zuerst einen KÜ auswählen!"); return; } // Meldungen laden, wenn Meldungen-Ansicht aktiv ist if (chartTitle === "Meldungen") { try { dispatch(setLoading(true)); const fromDate = pickerVonDatum ?? vonDatum; const toDate = pickerBisDatum ?? bisDatum; await dispatch(getMessagesThunk({ fromDate, toDate })).unwrap(); } catch (err) { const message = err instanceof Error ? err.message : String(err); console.error("❌ Fehler beim Laden der Meldungen:", message); alert("❌ Fehler beim Laden der Meldungen."); } finally { dispatch(setLoading(false)); } return; } const fromDate = pickerVonDatum ?? vonDatum; const toDate = pickerBisDatum ?? bisDatum; const apiUrl = getApiUrl(selectedMode, type, slotNumber, fromDate, toDate); if (!apiUrl) return; dispatch(setLoading(true)); dispatch(setChartOpen(false)); dispatch(setLoopMeasurementCurveChartData([])); 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 Daten für:"); console.log(" Slot:", slotNumber); console.log(" Typ:", selectedSlotType, "→", type); 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(setLoopMeasurementCurveChartData(jsonData)); dispatch(setChartOpen(true)); } else { alert("⚠️ Keine Messdaten im gewählten Zeitraum gefunden."); dispatch(setLoopMeasurementCurveChartData([])); dispatch(setChartOpen(false)); } } catch (err) { console.error("❌ Fehler beim Laden der Daten:", err); alert("❌ Fehler beim Laden der Daten."); } finally { dispatch(setLoading(false)); } }; useImperativeHandle(ref, () => ({ handleFetchData, })); // Sichtbarkeits-Flags const isMesskurve = chartTitle === "Messkurve"; return (
RSL Messung läuft
Bitte warten…{" "} {Math.min(100, Math.round((rslProgress / TOTAL_DURATION) * 100))}%