"use client"; // Report.tsx import React, { useState, useEffect, useCallback, useMemo } from "react"; import { useSelector, useDispatch } from "react-redux"; import { RootState, AppDispatch } from "@/redux/store"; import { getMessagesThunk } from "@/redux/thunks/getMessagesThunk"; // Gleiche Datenstruktur wie MeldungenView type Meldung = { t: string; // timestamp s: number; // status/priority c: string; // color m: string; // message i: string; // source/info v: string; // value/status text }; type ModuleType = "ISO" | "TDR" | "RSL" | "KVZ"; interface ReportProps { moduleType: ModuleType; autoLoad?: boolean; } const Report: React.FC = ({ moduleType, autoLoad = true }) => { const dispatch = useDispatch(); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [filteredMessages, setFilteredMessages] = useState([]); const { vonDatum, bisDatum, slotNumber } = useSelector( (state: RootState) => state.kabelueberwachungChartSlice ); // Nachrichten aus dem globalen Store const messages = useSelector((state: RootState) => state.messages.data); // Nachrichten für den aktuellen Slot filtern const filterMessagesForSlot = useCallback( (allMessages: Meldung[], slot: number) => { if (slot === null) return []; // Primärer Filter: Exakte CableLineX Übereinstimmung (X = slot + 1) const primaryIdentifier = `CableLine${slot + 1}`; console.log( `🔍 Filtere Nachrichten für Slot ${slot} (${primaryIdentifier}):` ); console.log(`📥 Gesamt Nachrichten: ${allMessages.length}`); // Debug: Zeige alle verfügbaren Quellen const allSources = [...new Set(allMessages.map((msg) => msg.i))]; console.log(`📋 Alle verfügbaren Quellen:`, allSources); // Filter basierend auf der Quelle (i-Feld) - EXAKTE Übereinstimmung const filtered = allMessages.filter((msg: Meldung) => { // Exakte Übereinstimmung: msg.i sollte genau "CableLineX" sein const isExactMatch = msg.i === primaryIdentifier; // Fallback: Falls die Quelle mehr Informationen enthält (z.B. "CableLine1_Sensor") const isPartialMatch = msg.i.startsWith(primaryIdentifier) && (msg.i === primaryIdentifier || msg.i.charAt(primaryIdentifier.length).match(/[^0-9]/)); const isMatch = isExactMatch || isPartialMatch; if (isMatch) { console.log(`✅ Gefunden: "${msg.i}" -> ${msg.m}`); } return isMatch; }); console.log( `📤 Gefilterte Nachrichten für ${primaryIdentifier}: ${filtered.length}` ); // Falls keine Nachrichten mit CableLineX gefunden, versuche alternative Identifikatoren if (filtered.length === 0) { console.log( `⚠️ Keine Nachrichten für ${primaryIdentifier} gefunden. Versuche alternative Identifikatoren...` ); const alternativeIdentifiers = [ `Slot${slot + 1}`, `KÜ${slot + 1}`, `Kue${slot + 1}`, `Cable${slot + 1}`, `Line${slot + 1}`, ]; const alternativeFiltered = allMessages.filter((msg: Meldung) => { return alternativeIdentifiers.some((identifier) => { const isExactMatch = msg.i === identifier; const isPartialMatch = msg.i.startsWith(identifier) && (msg.i === identifier || msg.i.charAt(identifier.length).match(/[^0-9]/)); const isMatch = isExactMatch || isPartialMatch; if (isMatch) { console.log(`🔄 Alternative gefunden: "${msg.i}" -> ${msg.m}`); } return isMatch; }); }); console.log( `📤 Alternative gefilterte Nachrichten: ${alternativeFiltered.length}` ); return alternativeFiltered; } return filtered; }, [] ); // Modul-spezifische Schlüsselwörter (alle lowercase, ö => oe normalisiert) const moduleKeywordMap = useMemo>( () => ({ ISO: [ "modul online", "aderbruch", "erdschluss", "isofehler", "iso fehler", "iso-fehler", "isolationsfehler", "isolationfehler", "isolation fehler", ], TDR: ["modul online", "tdr aktiv", "tdr entfernung"], RSL: ["modul online", "aderbruch", "schleifenfehler"], KVZ: ["modul online", "aderbruch", "kvz störung", "kvz stoerung"], }), [] ); const normalize = (text: string) => text .toLowerCase() .replace(/ö/g, "oe") .replace(/ä/g, "ae") .replace(/ü/g, "ue"); // Daten laden const loadMessages = useCallback(async () => { if (slotNumber === null) return; setLoading(true); setError(null); try { // Redux Thunk verwenden (wie in MeldungenView) await dispatch( getMessagesThunk({ fromDate: vonDatum, toDate: bisDatum, }) ).unwrap(); } catch (err) { console.error("Fehler beim Laden der Berichte:", err); setError("Fehler beim Laden der Meldungen."); } finally { setLoading(false); } }, [dispatch, vonDatum, bisDatum, slotNumber]); // Filter anwenden wenn sich Nachrichten oder Slot ändern useEffect(() => { if (slotNumber !== null && messages.length > 0) { const slotFiltered = filterMessagesForSlot(messages, slotNumber); // Modul-Filter anwenden const keywords = moduleKeywordMap[moduleType].map(normalize); const moduleFiltered = slotFiltered.filter((m) => { const msgNorm = normalize(m.m); return keywords.some((kw) => msgNorm.includes(kw)); }); // Fallback: Wenn keine Keyword-Treffer, zeige Slot-Filter-Ergebnis setFilteredMessages( moduleFiltered.length > 0 ? moduleFiltered : slotFiltered ); } else { setFilteredMessages([]); } }, [ messages, slotNumber, filterMessagesForSlot, moduleType, moduleKeywordMap, ]); // Automatisches Laden beim Mount und bei Änderungen (optional) useEffect(() => { if (!autoLoad) return; if (slotNumber !== null) { loadMessages(); } }, [loadMessages, slotNumber, autoLoad]); if (loading) { return (
Lade Meldungen...
); } if (error) { return
{error}
; } return (
{filteredMessages.length === 0 ? (
Keine Meldungen für CableLine {slotNumber !== null ? slotNumber + 1 : "-"} (Filter: {moduleType}) im gewählten Zeitraum gefunden.
) : (
{filteredMessages.map((msg, index) => ( ))}
Prio Zeitstempel Quelle Meldung Status
{new Date(msg.t).toLocaleString("de-DE", { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit", })} {msg.i} {msg.m} {msg.v}
)} {/*
{filteredMessages.length} Meldung(en) (Filter: {moduleType}) gefunden
*/}
); }; export default Report;