Break: Digitale Eingänge, es soll Kabelüberwachung Isolation zu erst angezeigt, und ein Button Daten anzeigen, dass die nicht bei DatePicker autmatisch holt

This commit is contained in:
ISA
2025-04-03 13:16:35 +02:00
parent 75759791cd
commit c44920e7aa
5 changed files with 141 additions and 108 deletions

View File

@@ -1,108 +1,87 @@
"use client"; "use client";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux"; import { useSelector, useDispatch } from "react-redux";
import { RootState } from "../../../../redux/store"; import { RootState } from "../../../../redux/store";
import { useAppDispatch } from "../../../../redux/store"; import {
import { updateInvertierung } from "../../../../redux/slices/digitalInputsSlice"; updateInvertierung,
updateName,
} from "../../../../redux/slices/digitalInputsSlice";
export default function InputModal({ selectedInput, closeInputModal, isOpen }) { export default function InputModal({ selectedInput, closeInputModal, isOpen }) {
const dispatch = useAppDispatch(); const [invertiert, setInvertiert] = useState(false);
const [name, setName] = useState("");
const dispatch = useDispatch();
const reduxInput = useSelector((state: RootState) => const reduxInput = useSelector((state: RootState) =>
state.digitalInputsSlice.inputs.find( state.digitalInputsSlice.inputs.find(
(input) => input.id === Number(selectedInput.id) (input) => input.id === Number(selectedInput?.id)
) )
); );
const [invertiert, setInvertiert] = useState<boolean>(false);
const isDev = process.env.NODE_ENV === "development";
useEffect(() => {
if (selectedInput) {
if (isDev) {
const saved = localStorage.getItem(`invertierung_${selectedInput.id}`);
if (saved !== null) {
setInvertiert(parseInt(saved) === 1);
} else {
setInvertiert(selectedInput.invertierung);
}
} else {
setInvertiert(selectedInput.invertierung);
}
}
}, [selectedInput, isDev]);
if (!isOpen || !selectedInput) return null;
const handleInvertierungToggle = async () => {
const neueInvertierung = !invertiert;
if (process.env.NODE_ENV === "development") {
dispatch(
updateInvertierung({
id: Number(selectedInput.id),
invertierung: neueInvertierung,
})
);
setInvertiert(neueInvertierung);
} else {
const url = `/CPL?/CPL/SERVICE/empty.acp&DEI${selectedInput.id}=${
neueInvertierung ? 1 : 0
}`;
try {
const response = await fetch(url);
if (!response.ok) throw new Error("Fehler beim Senden der Anfrage");
dispatch(
updateInvertierung({
id: Number(selectedInput.id),
invertierung: neueInvertierung,
})
);
setInvertiert(neueInvertierung);
} catch (error) {
console.error("Invertierung fehlgeschlagen:", error);
alert("Invertierung konnte nicht geändert werden.");
}
}
};
//---------------------------------
useEffect(() => { useEffect(() => {
if (reduxInput) { if (reduxInput) {
setInvertiert(reduxInput.invertierung); setInvertiert(reduxInput.invertierung);
setName(reduxInput.name || "");
} }
}, [reduxInput]); }, [reduxInput]);
//--------------------------------- if (!isOpen || !selectedInput || !reduxInput) return null;
const handleInvertierungToggle = () => {
const neueInvertierung = !invertiert;
dispatch(
updateInvertierung({ id: reduxInput.id, invertierung: neueInvertierung })
);
setInvertiert(neueInvertierung);
};
const handleNameSpeichern = () => {
dispatch(updateName({ id: reduxInput.id, name }));
};
return ( return (
<div className="fixed top-0 left-0 w-full h-full bg-black bg-opacity-50 flex justify-center items-center z-50"> <div className="fixed top-0 left-0 w-full h-full bg-black bg-opacity-50 flex justify-center items-center z-50">
<div className="bg-white rounded-lg shadow-lg p-6 w-1/2 max-w-lg"> <div className="bg-white rounded-lg shadow-lg p-6 w-1/2 max-w-lg">
<h2 className="text-xl font-semibold text-littwin-blue mb-4 border-b pb-2"> <h2 className="text-xl font-semibold text-blue-500 mb-4 border-b pb-2">
Details für Eingang {selectedInput.id} Parameter für Eingang {selectedInput.id}
</h2> </h2>
<div className="grid grid-cols-2 gap-x-4 gap-y-2">
<div>
<strong>Status:</strong>
</div>
<div>
<strong>Status:</strong>
</div>
<div
className={reduxInput?.status ? "text-red-600" : "text-green-600"}
>
{reduxInput?.status ? "Inaktiv" : "Aktiv"}
</div>
<div className="grid grid-cols-2 gap-x-4 gap-y-3">
<div> <div>
<strong>Beschreibung:</strong> <strong>Status:</strong>
</div>
<div className="flex items-center gap-3 text-xl font-semibold col-span-1">
{reduxInput.status ? (
<>
<span className="w-4 h-4 bg-red-500 rounded-full inline-block"></span>
<span className="text-red-600">Inaktiv</span>
</>
) : (
<>
<span className="w-4 h-4 bg-green-500 rounded-full inline-block"></span>
<span className="text-green-600">Aktiv</span>
</>
)}
</div> </div>
<div>{selectedInput.description}</div>
<div> <div>
<strong>Name:</strong> <strong>Name:</strong>
</div> </div>
<div>{selectedInput.name}</div> <div className="flex gap-2">
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
className="border border-gray-300 rounded px-2 py-1 w-full"
maxLength={32}
/>
<button
onClick={handleNameSpeichern}
className="px-2 py-1 text-sm bg-blue-500 hover:bg-blue-600 text-white rounded"
>
Speichern
</button>
</div>
<div className="flex items-center gap-2 col-span-2"> <div className="flex items-center gap-2 col-span-2">
<strong>Invertierung:</strong> <strong>Invertierung:</strong>
@@ -115,35 +94,35 @@ export default function InputModal({ selectedInput, closeInputModal, isOpen }) {
</button> </button>
</div> </div>
<div>
<strong>Zählerstand:</strong>
</div>
<div>{reduxInput.counter}</div>
<div> <div>
<strong>Filterzeit:</strong> <strong>Filterzeit:</strong>
</div> </div>
<div>{selectedInput.filterzeit} ms</div> <div>{reduxInput.filterzeit} ms</div>
<div> <div>
<strong>Gewichtung:</strong> <strong>Gewichtung:</strong>
</div> </div>
<div>{selectedInput.gewichtung}</div> <div>{reduxInput.gewichtung}</div>
<div>
<strong>Zählerstand:</strong>
</div>
<div>{selectedInput.zaehlerstand}</div>
<div> <div>
<strong>Zähler aktiv:</strong> <strong>Zähler aktiv:</strong>
</div> </div>
<div>{selectedInput.zaehlerAktiv ? "Ja" : "Nein"}</div> <div>{reduxInput.zaehlerAktiv ? "Ja" : "Nein"}</div>
<div> <div>
<strong>Eingang offline:</strong> <strong>Eingang offline:</strong>
</div> </div>
<div>{selectedInput.eingangOffline ? "Offline" : "Online"}</div> <div>{reduxInput.eingangOffline ? "Offline" : "Online"}</div>
</div> </div>
<button <button
onClick={closeInputModal} onClick={closeInputModal}
className="mt-6 px-4 py-2 bg-littwin-blue hover:bg-blue-600 text-white rounded-lg transition" className="mt-6 px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg transition"
> >
Schließen Schließen
</button> </button>

View File

@@ -6,5 +6,5 @@
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen). 2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
*/ */
const webVersion = "1.6.209"; const webVersion = "1.6.210";
export default webVersion; export default webVersion;

View File

@@ -1,10 +1,12 @@
// public/CPLmockData/SERVICE/de.js // public/CPLmockData/SERVICE/de.js
// Zustand -> DESxx xx =Nr Eingang 1-32 80-83 = BGT 1 bis 4
var win_de_state = [ var win_de_state = [
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]; ];
// Invertierung -> DEIxx xx = Nr Eingang 1-32
// Invertierung -> DEIxx xx = Nr Eingang 1-32
var win_de_invert = [ var win_de_invert = [
1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -18,6 +20,49 @@ Status Invertierung Anzeige
0 1 ✅ grün 0 1 ✅ grün
0 0 ✅ grün 0 0 ✅ grün
*/ */
//Zählerstand -> DESxx xx =Nr Eingang 1-32 80-83 = BGT 1 bis 4
var win_de_counter = [
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0,
]; //Zählerstand
//Filterzeit -> DEFxx xx =Nr Eingang 1-32 80-83 = BGT 1 bis 4
// Frage: In digitale Eingänge Filterzeit DEFxx (In Lastenheft) und Flatter var flutter DEFxx ist ein und das selbe, welche Begriff soll ich nehmen?
// Antwort: Es ist die Filterzeit. Die Flatterzeit kommt später hinzu.
var win_de_time_filter = [
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0,
]; //Filterzeit
// Gewichtung -> DEGxx xx = Nr Eingang 1-32 80-83 = BGT 1 bis 4
var win_de_weighting = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
]; //Gewichtung
// Zähler aktiv -> DEZxx xx = Nr Eingang 1-32 80-83 = BGT 1 bis 4
var win_de_counter_active = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
]; //Zähler aktiv
// Eingang offline -> DEAxx xx = Nr Eingang 1-32 80-83 = BGT 1 bis 4
var win_de_offline = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
]; //Eingang offline
// Zähler aktiv -> DEZxx xx = Nr Eingang 1-32 80-83 = BGT 1 bis 4
var win_counter = [
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0,
];
// Name -> DENxx xx =Nr Eingang 1-32 80-83 = BGT 1 bis 4
var win_de_label = [ var win_de_label = [
"DE1", "DE1",
"DE2", "DE2",
@@ -52,12 +97,10 @@ var win_de_label = [
"DE31", "DE31",
"DE32", "DE32",
]; ];
var win_counter = [
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, // Frage: In digitale Eingänge Filterzeit DEFxx (In Lastenheft) und Flatter var flutter DEFxx ist ein und das selbe, welche Begriff soll ich nehmen?
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, // Antwort: Es ist die Filterzeit. Die Flatterzeit kommt später hinzu.
0.0, 0.0, /* var win_flutter = [
];
var win_flutter = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]; ]; */

View File

@@ -1,4 +1,4 @@
// slices/digitalInputsSlice.ts // /redux/slices/digitalInputsSlice.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { createSlice, PayloadAction } from "@reduxjs/toolkit";
interface DigitalInput { interface DigitalInput {
@@ -8,6 +8,11 @@ interface DigitalInput {
counter: number; counter: number;
flutter: number; flutter: number;
invertierung: boolean; invertierung: boolean;
filterzeit: number;
gewichtung: number;
zaehlerAktiv: boolean;
eingangOffline: boolean;
name: string;
} }
interface DigitalInputsState { interface DigitalInputsState {

View File

@@ -26,16 +26,22 @@ export const fetchDigitaleEingaenge = async () => {
return []; return [];
} }
const formattedData = win.win_de_state.map( const formattedData = win.win_de_state.map((status, index) => ({
(status: number, index: number) => ({ id: index + 1,
id: index + 1, label: win.win_de_label?.[index] || `DE${index + 1}`,
label: win.win_de_label?.[index] || `DE${index + 1}`, name: win.win_de_label?.[index] || "",
status: status === 1,
counter: win.win_counter?.[index] || 0, status: status === 1,
flutter: win.win_flutter?.[index] || 0, counter: win.win_de_counter?.[index] || 0,
invertierung: win.win_de_invert?.[index] === 1, flutter: win.win_flutter?.[index] || 0,
}) invertierung: win.win_de_invert?.[index] === 1,
);
// 🔽 NEU:
filterzeit: win.win_de_time_filter?.[index] || 0,
gewichtung: win.win_de_weighting?.[index] || 0,
zaehlerAktiv: win.win_de_counter_active?.[index] === 1,
eingangOffline: win.win_de_offline?.[index] === 1,
}));
return formattedData; return formattedData;
} catch (error) { } catch (error) {