Die Variable 'chartData' wurde in 'loopMeasurementCurveChartData' umbenannt, um den Inhalt und Zweck der Daten klarer zu definieren. Diese Änderung verbessert die Lesbarkeit und Wartbarkeit des Codes, indem sie die Bedeutung der Variablen präziser beschreibt.
464 lines
17 KiB
TypeScript
464 lines
17 KiB
TypeScript
"use client"; // components/modules/kue705FO/Kue705FO.tsx
|
|
import React, { useState, useEffect, useRef } from "react";
|
|
import ReactModal from "react-modal";
|
|
import Chart from "chart.js/auto";
|
|
import { useSelector } from "react-redux";
|
|
import KueModal from "./KueModal";
|
|
import "bootstrap-icons/font/bootstrap-icons.css"; // Import Bootstrap Icons
|
|
import { RootState } from "../../../../redux/store";
|
|
import { DataTDR } from "../../../../redux/types/chartDataTypesTDR";
|
|
import { useDispatch } from "react-redux";
|
|
import {
|
|
setSelectedChartData,
|
|
setSelectedFileName,
|
|
} from "../../../../redux/slices/variablesSlice";
|
|
import { createLoopChart, createTDRChart } from "../../../../utils/chartUtils";
|
|
import { getAlarmDisplayText } from "../../../../utils/alarmUtils";
|
|
import { goLoop } from "../../../../utils/goLoop";
|
|
import { goTDR } from "../../../../utils/goTDR";
|
|
import { loadTDRChartData } from "../../../../utils/loadTDRChartData";
|
|
import { loadLoopChartData } from "../../../../utils/loadLoopChartData";
|
|
import { Kue705FOProps } from "../../../../types/components/Kue705FOProps";
|
|
import ChartSwitcher from "./Charts/ChartSwitcher";
|
|
import { setActiveMode } from "../../../../redux/slices/chartDataSlice";
|
|
import LoopMeasurementChart from "./Charts/LoopMeasurementChart/LoopMeasurementChart";
|
|
import TDRChart from "./Charts/TDRChart/TDRChart";
|
|
import handleButtonClick from "./kue705FO-Funktionen/handleButtonClick";
|
|
import { setChartOpen } from "../../../../redux/slices/kabelueberwachungChartSlice";
|
|
import { setSlotNumber } from "../../../../redux/slices/kabelueberwachungChartSlice";
|
|
|
|
const Kue705FO: React.FC<Kue705FOProps> = ({
|
|
isolationswert,
|
|
schleifenwiderstand,
|
|
modulName,
|
|
kueOnline,
|
|
slotIndex,
|
|
tdrLocation,
|
|
alarmStatus,
|
|
}) => {
|
|
/* console.log(
|
|
`Rendering Kue705FO - SlotIndex: ${slotIndex}, ModulName: ${modulName}`
|
|
); */
|
|
const selectedChartData = useSelector(
|
|
(state: RootState) => state.variables.selectedChartData
|
|
);
|
|
const dispatch = useDispatch();
|
|
|
|
const chartRef = useRef(null);
|
|
const [zoomPlugin, setZoomPlugin] = useState<any>(null); // Plugin-Status für Chart.js
|
|
const [kueVersion, setKueVersion] = useState("V4.19");
|
|
const [currentAlarmStatus, setCurrentAlarmStatus] = useState(false);
|
|
const [currentModulName, setCurrentModulName] = useState(modulName);
|
|
const [activeButton, setActiveButton] = useState<"Schleife" | "TDR">(
|
|
"Schleife"
|
|
);
|
|
|
|
const [loopTitleText, setloopTitleText] = useState(
|
|
"Schleifenwiderstand [kOhm]"
|
|
);
|
|
const [loopDisplayValue, setLoopDisplayValue] = useState(schleifenwiderstand); // Initialisiere den loopDisplayValue mit schleifenwiderstand
|
|
|
|
const [isoDisplayText, setIsoDisplayText] = useState("Aderbruch");
|
|
const [groundFaultDisplayText, setGroundFaultDisplayText] =
|
|
useState("Erdschluss");
|
|
const [loopFaultDisplayText, setLoopFaultDisplayText] =
|
|
useState("Schleifenfehler");
|
|
const [isoFaultDisplayText, setIsoFaultDisplayText] =
|
|
useState("Isolationsfehler");
|
|
const [isoGreaterThan200, setIsoGreaterThan200] = useState(">200 MOhm");
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
const [isoDisplayValue, setIsoDisplayValue] = useState<
|
|
string | JSX.Element
|
|
>(); //Test erstmal leer ohne isolationswert
|
|
const [showModal, setShowModal] = useState(false);
|
|
const [showChartModal, setShowChartModal] = useState(false);
|
|
const [loopMeasurementCurveChartData, setLoopMeasurementCurveChartData] =
|
|
useState(null);
|
|
|
|
useEffect(() => {
|
|
if (loopMeasurementCurveChartData) {
|
|
dispatch(setSelectedChartData(loopMeasurementCurveChartData));
|
|
}
|
|
}, [loopMeasurementCurveChartData, dispatch]); // Führe dispatch nur aus, wenn loopMeasurementCurveChartData sich ändert
|
|
|
|
// Redux-Variablen abrufen
|
|
const {
|
|
kuePSTmMinus96V,
|
|
kueCableBreak,
|
|
kueGroundFault,
|
|
kueAlarm1,
|
|
kueAlarm2,
|
|
kueOverflow,
|
|
kueVersion: reduxKueVersion,
|
|
tdrActive,
|
|
} = useSelector((state: RootState) => state.variables);
|
|
|
|
const handleOpenModal = () => setShowModal(true);
|
|
const handleCloseModal = () => setShowModal(false);
|
|
|
|
const handleOpenChartModal = () => {
|
|
setShowChartModal(true);
|
|
dispatch(setChartOpen(true));
|
|
dispatch(setSlotNumber(slotIndex + 1)); // Slot-Nummer speichern
|
|
|
|
if (activeButton === "TDR") {
|
|
dispatch(setActiveMode("TDR"));
|
|
} else {
|
|
dispatch(setActiveMode("Schleife"));
|
|
}
|
|
};
|
|
|
|
// Funktion aufrufen in handleRefreshClick
|
|
const handleRefreshClick = () => {
|
|
if (activeButton === "Schleife") {
|
|
goLoop(slotIndex, setLoading);
|
|
} else if (activeButton === "TDR") {
|
|
goTDR(slotIndex, setLoading);
|
|
}
|
|
};
|
|
|
|
const handleCloseChartModal = () => {
|
|
if (chartInstance.current) {
|
|
console.log("Chart wird beim Schließen des Modals zerstört.");
|
|
chartInstance.current.destroy();
|
|
chartInstance.current = null;
|
|
}
|
|
setShowChartModal(false);
|
|
};
|
|
|
|
// Funktion zum Erstellen des TDR-Charts
|
|
|
|
const chartInstance = useRef<Chart | null>(null);
|
|
|
|
const selectedFileName = useSelector(
|
|
(state: RootState) => state.variables.selectedFileName
|
|
);
|
|
|
|
// Füge das Plugin zu Chart.js hinzu
|
|
useEffect(() => {
|
|
// Lade das Plugin nur, wenn `window` verfügbar ist
|
|
if (typeof window !== "undefined") {
|
|
import("chartjs-plugin-zoom").then((mod) => {
|
|
setZoomPlugin(mod.default); // Setze das Plugin
|
|
Chart.register(mod.default); // Plugin zur Chart.js-Instanz registrieren
|
|
});
|
|
}
|
|
}, []);
|
|
|
|
interface DataLoop {
|
|
t: number; // Zeit oder Index
|
|
m: number; // Isolationswiderstand
|
|
n: number; // Schleifenwiderstand
|
|
}
|
|
|
|
useEffect(() => {
|
|
const updateAlarmStatus = () => {
|
|
const alarmStatus =
|
|
(kueAlarm1 && kueAlarm1[slotIndex]) ||
|
|
(kueAlarm2 && kueAlarm2[slotIndex]) ||
|
|
(kueCableBreak && kueCableBreak[slotIndex]) ||
|
|
(kueGroundFault && kueGroundFault[slotIndex]);
|
|
|
|
setCurrentAlarmStatus(!!alarmStatus); // Wandelt string oder undefined in boolean um
|
|
};
|
|
|
|
updateAlarmStatus();
|
|
const interval = setInterval(updateAlarmStatus, 10000);
|
|
return () => clearInterval(interval);
|
|
}, [slotIndex, kueAlarm1, kueAlarm2, kueCableBreak, kueGroundFault]);
|
|
|
|
useEffect(() => {
|
|
if (reduxKueVersion?.[slotIndex]) {
|
|
setKueVersion("V" + Number(reduxKueVersion[slotIndex]) / 100);
|
|
}
|
|
}, [slotIndex, reduxKueVersion]);
|
|
//---------------------------------------------------
|
|
// Funktion zum Aktualisieren der Anzeige basierend auf dem Alarmstatus mit Icon und Blinken
|
|
// Funktion zum Aktualisieren der Anzeige basierend auf dem Alarmstatus mit Icon und Blinken
|
|
useEffect(() => {
|
|
setIsoDisplayValue(
|
|
getAlarmDisplayText(
|
|
slotIndex,
|
|
kuePSTmMinus96V,
|
|
kueCableBreak,
|
|
kueGroundFault,
|
|
kueAlarm1,
|
|
kueAlarm2,
|
|
kueOverflow ?? undefined,
|
|
isolationswert,
|
|
isoDisplayText,
|
|
groundFaultDisplayText,
|
|
isoFaultDisplayText,
|
|
loopFaultDisplayText,
|
|
isoGreaterThan200
|
|
)
|
|
);
|
|
}, [
|
|
slotIndex,
|
|
isolationswert,
|
|
isoDisplayText,
|
|
groundFaultDisplayText,
|
|
isoFaultDisplayText,
|
|
loopFaultDisplayText,
|
|
isoGreaterThan200,
|
|
kuePSTmMinus96V,
|
|
kueCableBreak,
|
|
kueGroundFault,
|
|
kueAlarm1,
|
|
kueAlarm2,
|
|
kueOverflow,
|
|
]);
|
|
//---------------------------------------------------
|
|
|
|
// Effekt, um Modulnamen zu aktualisieren, wenn sich der Prop ändert
|
|
useEffect(() => {
|
|
setCurrentModulName(modulName);
|
|
//console.log(`Modulname aktualisiert für Slot ${slotIndex}:`, modulName);
|
|
}, [modulName, slotIndex]);
|
|
//---------------------------------------------------
|
|
// Aktualisiert den Schleifenwiderstand, wenn sich der `schleifenwiderstand`-Prop ändert
|
|
useEffect(() => {
|
|
if (activeButton === "Schleife") {
|
|
setLoopDisplayValue(schleifenwiderstand);
|
|
}
|
|
}, [schleifenwiderstand, activeButton]);
|
|
//---------------------------------------------------
|
|
const noLetter = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
const input = e.currentTarget;
|
|
input.value = input.value.replace(/[^0-9]/g, "");
|
|
};
|
|
//---------------------------------------------------
|
|
//Auswahlmenü für Jahr, Monat und Sortierung
|
|
const [jahr, setJahr] = useState(new Date().getFullYear());
|
|
const [monat, setMonat] = useState(new Date().getMonth() + 1);
|
|
const [sortAscending, setSortAscending] = useState(true);
|
|
|
|
const handleSortToggle = () => {
|
|
setSortAscending(!sortAscending);
|
|
console.log(
|
|
"Sortierung umkehren:",
|
|
sortAscending ? "Absteigend" : "Aufsteigend"
|
|
);
|
|
};
|
|
|
|
const handleAktualisieren = () => {
|
|
console.log("Aktualisieren mit Jahr:", jahr, "Monat:", monat);
|
|
// Logik für die Aktualisierung hinzufügen
|
|
};
|
|
|
|
//---------------------------------------------------
|
|
|
|
//----------------------------------
|
|
useEffect(() => {
|
|
if (selectedChartData) {
|
|
createTDRChart(selectedChartData); // Neues Chart erstellen
|
|
}
|
|
|
|
return () => {
|
|
// Cleanup beim Komponentenwechsel
|
|
if (chartInstance.current) {
|
|
console.log("Chart wird beim Komponentenwechsel zerstört.");
|
|
chartInstance.current.destroy();
|
|
chartInstance.current = null;
|
|
}
|
|
};
|
|
}, [selectedChartData]);
|
|
|
|
//----------------------------------
|
|
|
|
return (
|
|
<div
|
|
className="relative bg-gray-300 w-[7.25rem] h-[24.375rem] border border-gray-400 transform laptop:-translate-y-12 2xl:-translate-y-0
|
|
scale-100 sm:scale-95 md:scale-100 lg:scale-105 xl:scale-90 2xl:scale-125 top-3
|
|
"
|
|
>
|
|
{kueOnline === 1 ? (
|
|
<>
|
|
<div className="relative w-[7.075rem] h-[15.156rem] bg-littwin-blue border-[0.094rem] border-gray-400 z-0">
|
|
<div className="flex items-start justify-between h-[1.875rem]">
|
|
<div className="relative w-[1.25rem] h-[1.25rem] bg-gray-800 flex items-center justify-center">
|
|
<span className="text-white text-[0.625rem]">
|
|
{slotIndex + 1}
|
|
</span>
|
|
</div>
|
|
|
|
<h3 className="text-white font-bold text-[0.563rem] mr-[1rem]">
|
|
KÜ705-FO
|
|
</h3>
|
|
|
|
<button
|
|
onClick={handleOpenModal}
|
|
className="w-[0.938rem] h-[0.938rem] bg-gray-400 flex items-center justify-center"
|
|
>
|
|
<span className="text-white text-[1.25rem]">⚙</span>
|
|
</button>
|
|
</div>
|
|
{}
|
|
<KueModal
|
|
showModal={showModal}
|
|
onClose={handleCloseModal}
|
|
slot={slotIndex}
|
|
onModulNameChange={setCurrentModulName}
|
|
/>
|
|
<div className="flex flex-col mt-[0.625rem] ml-[0.625rem]">
|
|
<div className="flex items-center space-x-[0.25rem] mt-[0.625rem]">
|
|
<div className="flex flex-col items-start space-y-[0.063rem] mr-[0.063rem]">
|
|
<span className="text-white text-[0.625rem]">Betrieb</span>
|
|
<span className="text-white text-[0.625rem]">Alarm</span>
|
|
</div>
|
|
<div className="flex flex-col items-center space-y-[0.188rem]">
|
|
<div className="w-[0.625rem] h-[0.625rem] bg-green-500 rounded-full"></div>
|
|
<div
|
|
className={`w-[0.625rem] h-[0.625rem] rounded-full ${
|
|
currentAlarmStatus ? "bg-red-500" : "bg-gray-300"
|
|
}`}
|
|
></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Anzeige des Isolation */}
|
|
<div className="relative mt-[3.125rem] mx-auto bg-black text-white w-[6.25rem] h-[2.5rem] flex items-center justify-center text-[1.125rem] z-10">
|
|
<div className="text-center">
|
|
<span
|
|
className={
|
|
Number(kuePSTmMinus96V?.[slotIndex]) === 1 ||
|
|
Number(kueCableBreak?.[slotIndex]) === 1 ||
|
|
Number(kueGroundFault?.[slotIndex]) === 1 ||
|
|
Number(kueAlarm1?.[slotIndex]) === 1 ||
|
|
Number(kueAlarm2?.[slotIndex]) === 1
|
|
? "text-red-500 text-[0.875rem]"
|
|
: Number(kueOverflow?.[slotIndex]) === 1
|
|
? "text-white text-[0.875rem]"
|
|
: ""
|
|
}
|
|
>
|
|
{isoDisplayValue}
|
|
</span>
|
|
|
|
{Number(kuePSTmMinus96V?.[slotIndex]) !== 1 &&
|
|
Number(kueCableBreak?.[slotIndex]) !== 1 &&
|
|
Number(kueGroundFault?.[slotIndex]) !== 1 &&
|
|
Number(kueAlarm1?.[slotIndex]) !== 1 &&
|
|
Number(kueAlarm2?.[slotIndex]) !== 1 &&
|
|
Number(kueOverflow?.[slotIndex]) !== 1 && (
|
|
<div className="text-[0.5rem]">ISO MOhm</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="absolute top-0 left-[4.688rem] w-[0.188rem] h-full bg-white z-0"></div>
|
|
<div className="absolute top-[2.5rem] left-[4.688rem] w-[2.5rem] h-[0.188rem] bg-white z-0"></div>
|
|
|
|
<div className="absolute bottom-[1.25rem] left-0 right-0 text-black text-[0.625rem] bg-gray-300 p-[0.063rem] text-center">
|
|
{currentModulName || `Modul ${slotIndex + 1}`}
|
|
</div>
|
|
|
|
<div className="absolute bottom-[0.063rem] right-[0.063rem] text-black text-[0.5rem]">
|
|
{kueVersion}
|
|
</div>
|
|
</div>
|
|
|
|
{/* loopDisplay: Zeigt Schleifenwiderstand oder TDR-Distanz an, je nach Modus */}
|
|
<div className="absolute bottom-[0.063rem] left-[0.068rem] w-[7.074rem] h-[8.125rem] bg-gray-300 border-[0.094rem] border-gray-400 p-[0.063rem]">
|
|
<span className="text-black text-[0.438rem] absolute top-[0.125rem] left-[0.063rem] mt-1">
|
|
{loopTitleText}
|
|
</span>
|
|
|
|
<div className="relative w-full h-[2.813rem] bg-gray-100 border border-gray-400 flex items-center justify-center mt-4">
|
|
<button
|
|
onClick={handleRefreshClick} // Dynamische Funktion basierend auf aktivem Button
|
|
className="absolute -top-[0.063rem] -right-[0.063rem] w-[1.25rem] h-[1.25rem] bg-gray-400 flex items-center justify-center"
|
|
disabled={loading} // Disable button while loading
|
|
>
|
|
<span className="text-white text-[1.125rem]">⟳</span>
|
|
</button>
|
|
|
|
<div className="absolute bottom-[0.313rem] left-1/2 transform -translate-x-1/2 w-[6.25rem] flex justify-center items-center">
|
|
<div className="text-center text-black text-[0.625rem]">
|
|
<p>
|
|
{loopDisplayValue +
|
|
(activeButton === "Schleife" ? " KOhm" : " Km")}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex mt-1 space-x-[0.063rem] ">
|
|
<button
|
|
onClick={() =>
|
|
handleButtonClick(
|
|
"Schleife",
|
|
setActiveButton,
|
|
setloopTitleText,
|
|
setLoopDisplayValue,
|
|
Number(schleifenwiderstand), // <- Stelle sicher, dass es eine Zahl ist
|
|
tdrLocation,
|
|
slotIndex,
|
|
dispatch
|
|
)
|
|
}
|
|
className={`w-[50%] h-[1.563rem] text-white text-[0.625rem] flex items-center justify-center ${
|
|
activeButton === "Schleife"
|
|
? "bg-littwin-blue"
|
|
: "bg-gray-400"
|
|
}`}
|
|
>
|
|
Schleife
|
|
</button>
|
|
<button
|
|
onClick={() =>
|
|
handleButtonClick(
|
|
"TDR",
|
|
setActiveButton,
|
|
setloopTitleText,
|
|
setLoopDisplayValue,
|
|
Number(schleifenwiderstand), // <- Stelle sicher, dass es eine Zahl ist
|
|
tdrLocation,
|
|
slotIndex,
|
|
dispatch
|
|
)
|
|
}
|
|
className={`w-[50%] h-[1.563rem] text-white text-[0.625rem] flex items-center justify-center ${
|
|
Array.isArray(tdrActive) && tdrActive[slotIndex] === 0
|
|
? "bg-gray-200 cursor-not-allowed" // Deaktiviert: Hellgrau
|
|
: activeButton === "TDR"
|
|
? "bg-littwin-blue" // Aktiviert: Littwin Blau
|
|
: "bg-gray-400" // Nicht geklickt: Dunkelgrau
|
|
}`}
|
|
disabled={
|
|
Array.isArray(tdrActive) && tdrActive[slotIndex] === 0
|
|
} // Button deaktiviert, wenn TDR für diesen Slot nicht aktiv ist
|
|
>
|
|
TDR
|
|
</button>
|
|
</div>
|
|
|
|
<button
|
|
onClick={handleOpenChartModal} // Öffnet das Chart-Modal
|
|
className="w-full h-[1.563rem] bg-littwin-blue text-white text-[0.625rem] flex items-center justify-center mt-[0.063rem]"
|
|
>
|
|
Messkurve
|
|
</button>
|
|
</div>
|
|
|
|
{/* Modal für Messkurve */}
|
|
{showChartModal && (
|
|
<ChartSwitcher
|
|
isOpen={showChartModal}
|
|
onClose={handleCloseChartModal}
|
|
/>
|
|
)}
|
|
</>
|
|
) : (
|
|
<div className="flex items-center justify-center h-full text-gray-500">
|
|
<p>Kein Modul im Slot {slotIndex + 1}</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Kue705FO;
|