From f9c2dc7bc9ab033e3851f8fec3e0a944c172f650 Mon Sep 17 00:00:00 2001 From: ISA Date: Wed, 19 Mar 2025 15:33:23 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20Redux-Thunk=20f=C3=BCr=20digitale=20Ein?= =?UTF-8?q?g=C3=A4nge=20integriert=20&=20UI=20mit=20zwei=20Tabellen=20umge?= =?UTF-8?q?setzt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `fetchDigitaleEingaengeThunk.ts` erstellt, um digitale Eingänge in Redux zu speichern. - `fetchDigitaleEingaenge.ts` erstellt, um API-Daten aus `de.js` zu laden. - `digitalInputsSlice.ts` hinzugefügt, um digitale Eingänge in Redux zu verwalten. - `DigitalInputs.tsx` überarbeitet: Zwei Tabellen für digitale Eingänge hinzugefügt. - Sicherstellung, dass Redux-Thunk nur im Client (`useEffect`) ausgeführt wird. - API-Calls werden nun alle 10 Sekunden aktualisiert. ✅ Jetzt läuft Redux-Thunk stabil & effizient für digitale Eingänge! --- .../main/einausgaenge/DigitalInputs.tsx | 28 ++++++---- config/webVersion.ts | 2 +- pages/_app.tsx | 17 +++++- redux/slices/digitalInputsSlice.ts | 17 ++---- redux/store.ts | 2 +- redux/thunks/fetchDigitaleEingaengeThunk.ts | 22 ++++++++ redux/thunks/fetchLoopChartDataThunk.ts | 56 ------------------- services/fetchDigitaleEingaenge.ts | 52 +++++++++++++++++ 8 files changed, 110 insertions(+), 86 deletions(-) create mode 100644 redux/thunks/fetchDigitaleEingaengeThunk.ts delete mode 100644 redux/thunks/fetchLoopChartDataThunk.ts create mode 100644 services/fetchDigitaleEingaenge.ts diff --git a/components/main/einausgaenge/DigitalInputs.tsx b/components/main/einausgaenge/DigitalInputs.tsx index 5d37538..5ebcfc9 100644 --- a/components/main/einausgaenge/DigitalInputs.tsx +++ b/components/main/einausgaenge/DigitalInputs.tsx @@ -1,15 +1,21 @@ "use client"; // components/main/einausgaenge/DigitalInputs.tsx - import React from "react"; +import { useSelector } from "react-redux"; +import { RootState } from "../../../redux/store"; import { Icon } from "@iconify/react"; -export default function DigitalInputs({ - inputsGroup1, - inputsGroup2, - openInputModal, -}) { +export default function DigitalInputs({ openInputModal }) { + const digitalInputs = useSelector( + (state: RootState) => state.digitalInputs.inputs + ); + + // **Gruppiere Eingänge in zwei Tabellen** + const midIndex = Math.ceil(digitalInputs.length / 2); + const inputsGroup1 = digitalInputs.slice(0, midIndex); + const inputsGroup2 = digitalInputs.slice(midIndex); + return ( -
+

Digitale Eingänge @@ -39,15 +45,13 @@ export default function DigitalInputs({ - {input.status === "active" ? "●" : "⨉"} + {input.status ? "●" : "⨉"} - {input.description} + {input.label} clearInterval(intervalId); } }, []); - + //--------------------------------------------------------- useEffect(() => { if (typeof window !== "undefined") { dispatch(fetchAnalogeEingaengeThunk()); @@ -105,7 +106,17 @@ function AppContent({ Component, pageProps }: AppProps) { return () => clearInterval(interval); } }, [dispatch]); - + //--------------------------------------------------------- + useEffect(() => { + if (typeof window !== "undefined") { + dispatch(fetchDigitaleEingaengeThunk()); + const interval = setInterval(() => { + dispatch(fetchDigitaleEingaengeThunk()); + }, 10000); + return () => clearInterval(interval); + } + }, [dispatch]); + //--------------------------------------------------------- return (
diff --git a/redux/slices/digitalInputsSlice.ts b/redux/slices/digitalInputsSlice.ts index 566b381..72a46a8 100644 --- a/redux/slices/digitalInputsSlice.ts +++ b/redux/slices/digitalInputsSlice.ts @@ -5,6 +5,8 @@ interface DigitalInput { id: number; label: string; status: boolean; + counter: number; + flutter: number; } interface DigitalInputsState { @@ -12,7 +14,7 @@ interface DigitalInputsState { } const initialState: DigitalInputsState = { - inputs: [], // Initial leerer Zustand + inputs: [], }; const digitalInputsSlice = createSlice({ @@ -32,19 +34,8 @@ const digitalInputsSlice = createSlice({ input.status = status; } }, - updateInputLabel: ( - state, - action: PayloadAction<{ id: number; label: string }> - ) => { - const { id, label } = action.payload; - const input = state.inputs.find((input) => input.id === id); - if (input) { - input.label = label; - } - }, }, }); -export const { setInputs, updateInputStatus, updateInputLabel } = - digitalInputsSlice.actions; +export const { setInputs, updateInputStatus } = digitalInputsSlice.actions; export default digitalInputsSlice.reducer; diff --git a/redux/store.ts b/redux/store.ts index a49e0e1..b80acff 100644 --- a/redux/store.ts +++ b/redux/store.ts @@ -5,7 +5,6 @@ import authReducer from "./slices/authSlice"; import variablesReducer from "./slices/variablesSlice"; import kueChartModeReducer from "./slices/kueChartModeSlice"; import webVersionReducer from "./slices/webVersionSlice"; -import digitalInputsReducer from "./slices/digitalInputsSlice"; import kabelueberwachungChartReducer from "./slices/kabelueberwachungChartSlice"; import dashboardReducer from "./slices/dashboardSlice"; import systemSettingsReducer from "./slices/systemSettingsSlice"; @@ -14,6 +13,7 @@ import digitalOutputsReducer from "./slices/digitalOutputsSlice"; import brushReducer from "./slices/brushSlice"; import tdrChartReducer from "./slices/tdrChartSlice"; import analogeEingaengeReducer from "./slices/analogeEingaengeSlice"; +import digitalInputsReducer from "./slices/digitalInputsSlice"; const store = configureStore({ reducer: { diff --git a/redux/thunks/fetchDigitaleEingaengeThunk.ts b/redux/thunks/fetchDigitaleEingaengeThunk.ts new file mode 100644 index 0000000..5b9b5e6 --- /dev/null +++ b/redux/thunks/fetchDigitaleEingaengeThunk.ts @@ -0,0 +1,22 @@ +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { fetchDigitaleEingaenge } from "../../services/fetchDigitaleEingaenge"; +import { setInputs } from "../slices/digitalInputsSlice"; + +/** + * Holt digitale Eingänge von der API und speichert sie in Redux. + */ +export const fetchDigitaleEingaengeThunk = createAsyncThunk( + "digitalInputs/fetchDigitaleEingaenge", + async (_, { dispatch }) => { + if (typeof window === "undefined") return; + + try { + const data = await fetchDigitaleEingaenge(); + if (data) { + dispatch(setInputs(data)); // ✅ Redux mit API-Daten füllen + } + } catch (error) { + console.error("❌ Fehler beim Laden der digitalen Eingänge:", error); + } + } +); diff --git a/redux/thunks/fetchLoopChartDataThunk.ts b/redux/thunks/fetchLoopChartDataThunk.ts deleted file mode 100644 index 382a832..0000000 --- a/redux/thunks/fetchLoopChartDataThunk.ts +++ /dev/null @@ -1,56 +0,0 @@ -// /redux/thunks/fetchLoopChartDataThunk.ts -import { createAsyncThunk } from "@reduxjs/toolkit"; -import { fetchLoopChartData } from "../../services/fetchLoopChartData"; -import { setLoopMeasurementCurveChartData } from "../slices/kabelueberwachungChartSlice"; - -/** - * Holt die neuesten Daten von der API und speichert sie in Redux. - */ -export const fetchLoopChartDataThunk = createAsyncThunk( - "kabelueberwachungChart/fetchLoopChartData", - async ( - { - mode, - type, - slotNumber, - vonDatum, - bisDatum, - }: { - mode: "DIA0" | "DIA1" | "DIA2"; - type: number; - slotNumber: number; - vonDatum: string; - bisDatum: string; - }, - { dispatch } - ) => { - const data = await fetchLoopChartData( - mode, - type, - slotNumber, - vonDatum, - bisDatum - ); - if (data) { - dispatch(setLoopMeasurementCurveChartData(data)); - } - } -); - -/** - * Starte automatisches Polling (alle 10 Sekunden). - */ -export const startLoopChartDataPolling = () => (dispatch: any) => { - setInterval(() => { - console.log("🔄 Daten werden aktualisiert..."); - dispatch( - fetchLoopChartDataThunk({ - mode: "DIA0", - type: 4, - slotNumber: 6, - vonDatum: "2024-02-01", - bisDatum: "2024-02-10", - }) - ); - }, 10000); -}; diff --git a/services/fetchDigitaleEingaenge.ts b/services/fetchDigitaleEingaenge.ts new file mode 100644 index 0000000..5fbfccb --- /dev/null +++ b/services/fetchDigitaleEingaenge.ts @@ -0,0 +1,52 @@ +/** + * Bestimmt die richtige API-URL für digitale Eingänge basierend auf Umgebung. + */ +const getApiUrl = () => { + if (typeof window === "undefined") { + console.error("❌ `window` ist nicht verfügbar (Server-Side Rendering)"); + return null; + } + + return process.env.NODE_ENV === "development" + ? `${window.location.origin}/CPLmockData/SERVICE/de.js` + : `${window.location.origin}/CPL/SERVICE/de.js`; +}; + +/** + * Holt die digitalen Eingänge und formatiert die Daten für Redux. + */ +export const fetchDigitaleEingaenge = async () => { + try { + const apiUrl = getApiUrl(); + if (!apiUrl) return null; + + console.log(`📡 API-Request an: ${apiUrl}`); + const response = await fetch(apiUrl); + if (!response.ok) { + throw new Error(`❌ Fehler: ${response.status} ${response.statusText}`); + } + + const rawData = await response.text(); + console.log("✅ Rohdaten erfolgreich geladen:", rawData); + + // **JavaScript-Variablen als Skript einfügen** + const script = document.createElement("script"); + script.innerHTML = rawData; + document.body.appendChild(script); + + // **Daten ins Redux-Format umwandeln** + const formattedData = win_de_state.map((status, index) => ({ + id: index + 1, + label: win_de_label[index] || `DE${index + 1}`, + status: status === 1, + counter: win_counter[index] || 0, + flutter: win_flutter[index] || 0, + })); + + console.log("✅ Formatierte Daten:", formattedData); + return formattedData; + } catch (error) { + console.error("❌ Fehler beim Laden der digitalen Eingänge:", error); + return null; + } +};