From a9ccdfc9ab0ca287918db2d0bc146f79a1609fe9 Mon Sep 17 00:00:00 2001 From: ISA Date: Wed, 3 Sep 2025 13:38:05 +0200 Subject: [PATCH] feat: Messverlauf bei Systemwerten (Temperatur und Spannungen) mit Datumsauswahl --- .env.development | 2 +- .env.production | 2 +- CHANGELOG.md | 5 + components/main/system/DetailModal.tsx | 133 +++++++----------- .../main/system/SystemChartActionBar.tsx | 96 +++++++++++++ package-lock.json | 4 +- package.json | 2 +- 7 files changed, 156 insertions(+), 88 deletions(-) create mode 100644 components/main/system/SystemChartActionBar.tsx diff --git a/.env.development b/.env.development index e856967..bb13e2a 100644 --- a/.env.development +++ b/.env.development @@ -6,6 +6,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false NEXT_PUBLIC_EXPORT_STATIC=false NEXT_PUBLIC_USE_CGI=false # App-Versionsnummer -NEXT_PUBLIC_APP_VERSION=1.6.828 +NEXT_PUBLIC_APP_VERSION=1.6.829 NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter) diff --git a/.env.production b/.env.production index 0697f90..44cdd90 100644 --- a/.env.production +++ b/.env.production @@ -5,5 +5,5 @@ NEXT_PUBLIC_CPL_API_PATH=/CPL NEXT_PUBLIC_EXPORT_STATIC=true NEXT_PUBLIC_USE_CGI=true # App-Versionsnummer -NEXT_PUBLIC_APP_VERSION=1.6.828 +NEXT_PUBLIC_APP_VERSION=1.6.829 NEXT_PUBLIC_CPL_MODE=production \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 329a0a2..d7f29de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [1.6.829] – 2025-09-03 + +- feat(mocks): mesages_all.json mock script + +--- ## [1.6.828] – 2025-09-03 - feat(mocks): retime chart mocks to today; add global/all-slot scripts diff --git a/components/main/system/DetailModal.tsx b/components/main/system/DetailModal.tsx index 7bce729..3a63a54 100644 --- a/components/main/system/DetailModal.tsx +++ b/components/main/system/DetailModal.tsx @@ -4,15 +4,11 @@ import React, { useEffect, useRef, useState, useCallback } from "react"; import { Line } from "react-chartjs-2"; import { useSelector } from "react-redux"; import { RootState, useAppDispatch } from "@/redux/store"; -import { Listbox } from "@headlessui/react"; import { setFullScreen } from "@/redux/slices/kabelueberwachungChartSlice"; -import DateRangePicker from "@/components/common/DateRangePicker"; -import { - setVonDatum, - setBisDatum, -} from "@/redux/slices/kabelueberwachungChartSlice"; +import { resetDateRange } from "@/redux/slices/dateRangePickerSlice"; // Import Thunks +import SystemChartActionBar from "@/components/main/system/SystemChartActionBar"; import { getSystemspannung5VplusThunk } from "@/redux/thunks/getSystemspannung5VplusThunk"; import { getSystemspannung15VplusThunk } from "@/redux/thunks/getSystemspannung15VplusThunk"; import { getSystemspannung15VminusThunk } from "@/redux/thunks/getSystemspannung15VminusThunk"; @@ -214,8 +210,8 @@ export const DetailModal = ({ useEffect(() => { if (isOpen) { setZeitraum("DIA0"); - dispatch(setVonDatum("")); - dispatch(setBisDatum("")); + // Reset DateRangePicker to its defaults (it sets 30 days → today on mount) + dispatch(resetDateRange()); // Chart-Daten zurücksetzen beim Öffnen setChartData({ datasets: [] }); @@ -260,8 +256,7 @@ export const DetailModal = ({ const handleClose = () => { dispatch(setFullScreen(false)); - dispatch(setVonDatum("")); - dispatch(setBisDatum("")); + dispatch(resetDateRange()); onClose(); }; @@ -307,25 +302,55 @@ export const DetailModal = ({ } }, [chartData, isLoading]); + // DateRange from global DateRangePicker slice + const pickerVonDatum = useSelector( + (state: RootState) => state.dateRangePicker.vonDatum + ); + const pickerBisDatum = useSelector( + (state: RootState) => state.dateRangePicker.bisDatum + ); + // Update chart data when Redux data changes (only after button click) useEffect(() => { if (shouldUpdateChart && reduxData && reduxData.length > 0) { - console.log("Redux data for chart:", reduxData); + // Filter data by selected date range (inclusive end date) + let filtered = reduxData; + try { + if (pickerVonDatum && pickerBisDatum) { + const start = new Date(`${pickerVonDatum}T00:00:00`); + const end = new Date(`${pickerBisDatum}T23:59:59`); + const s = start.getTime(); + const e = end.getTime(); + filtered = reduxData.filter((entry) => { + const t = new Date(entry.t).getTime(); + return t >= s && t <= e; + }); + } + } catch (err) { + console.warn("Zeitfilter konnte nicht angewendet werden:", err); + } + + console.log("Redux data for chart (filtered):", filtered.length); + if (!filtered.length) { + setChartData({ datasets: [] }); + setShouldUpdateChart(false); + return; + } // Create datasets array for multiple lines const datasets = []; // Check which data fields are available and create datasets accordingly - const hasMinimum = reduxData.some( + const hasMinimum = filtered.some( (entry) => entry.i !== undefined && entry.i !== null && entry.i !== 0 ); - const hasMaximum = reduxData.some( + const hasMaximum = filtered.some( (entry) => entry.a !== undefined && entry.a !== null ); - const hasAverage = reduxData.some( + const hasAverage = filtered.some( (entry) => entry.g !== undefined && entry.g !== null ); - const hasCurrent = reduxData.some( + const hasCurrent = filtered.some( (entry) => entry.m !== undefined && entry.m !== null ); @@ -333,7 +358,7 @@ export const DetailModal = ({ if (hasMinimum) { datasets.push({ label: "Messwert Minimum", - data: reduxData.map((entry) => ({ + data: filtered.map((entry) => ({ x: new Date(entry.t).getTime(), y: entry.i || 0, })), @@ -348,7 +373,7 @@ export const DetailModal = ({ if (hasMaximum) { datasets.push({ label: "Messwert Maximum", - data: reduxData.map((entry) => ({ + data: filtered.map((entry) => ({ x: new Date(entry.t).getTime(), y: entry.a || 0, })), @@ -364,7 +389,7 @@ export const DetailModal = ({ if (hasAverage) { datasets.push({ label: "Durchschnitt", - data: reduxData.map((entry) => ({ + data: filtered.map((entry) => ({ x: new Date(entry.t).getTime(), y: entry.g || 0, })), @@ -379,7 +404,7 @@ export const DetailModal = ({ if (hasCurrent) { datasets.push({ label: "Messwert", - data: reduxData.map((entry) => ({ + data: filtered.map((entry) => ({ x: new Date(entry.t).getTime(), y: entry.m || 0, })), @@ -449,70 +474,12 @@ export const DetailModal = ({ -
- - - -
- - - { - { - DIA0: "Alle Messwerte", - DIA1: "Stündlich", - DIA2: "Täglich", - }[zeitraum] - } - - - - - - - {["DIA0", "DIA1", "DIA2"].map((option) => ( - - `px-4 py-1 cursor-pointer ${ - selected - ? "bg-littwin-blue text-white" - : active - ? "bg-gray-200 dark:bg-gray-700" - : "" - }` - } - > - { - { - DIA0: "Alle Messwerte", - DIA1: "Stündlich", - DIA2: "Täglich", - }[option] - } - - ))} - -
-
- -
+
diff --git a/components/main/system/SystemChartActionBar.tsx b/components/main/system/SystemChartActionBar.tsx new file mode 100644 index 0000000..d774dc1 --- /dev/null +++ b/components/main/system/SystemChartActionBar.tsx @@ -0,0 +1,96 @@ +"use client"; +// components/main/system/SystemChartActionBar.tsx +import React from "react"; +import DateRangePicker from "@/components/common/DateRangePicker"; +import { Listbox } from "@headlessui/react"; + +type Props = { + zeitraum: "DIA0" | "DIA1" | "DIA2"; + setZeitraum: (typ: "DIA0" | "DIA1" | "DIA2") => void; + onFetchData: () => void; + isLoading?: boolean; + className?: string; +}; + +const SystemChartActionBar: React.FC = ({ + zeitraum, + setZeitraum, + onFetchData, + isLoading = false, + className = "", +}) => { + return ( +
+ {/* DateRangePicker – nutzt globalen Redux-Slice */} + + + {/* Zeitraum (DIA0/DIA1/DIA2) */} + + +
+ + + { + { DIA0: "Alle Messwerte", DIA1: "Stündlich", DIA2: "Täglich" }[ + zeitraum + ] + } + + + + + + + {["DIA0", "DIA1", "DIA2"].map((option) => ( + + `px-4 py-1 cursor-pointer ${ + selected + ? "bg-littwin-blue text-white" + : active + ? "bg-gray-200" + : "" + }` + } + > + { + { + DIA0: "Alle Messwerte", + DIA1: "Stündlich", + DIA2: "Täglich", + }[option as "DIA0" | "DIA1" | "DIA2"] + } + + ))} + +
+
+ + {/* Daten laden */} + +
+ ); +}; + +export default SystemChartActionBar; diff --git a/package-lock.json b/package-lock.json index 1b0107a..fd93edc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cpl-v4", - "version": "1.6.828", + "version": "1.6.829", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cpl-v4", - "version": "1.6.828", + "version": "1.6.829", "dependencies": { "@fontsource/roboto": "^5.1.0", "@headlessui/react": "^2.2.4", diff --git a/package.json b/package.json index 497b56b..c79423e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cpl-v4", - "version": "1.6.828", + "version": "1.6.829", "private": true, "scripts": { "dev": "next dev -p 3000",