fix: Vergleich und Speicherung von Änderungen im KUE-Modul korrigiert
- Originalwerte werden jetzt direkt aus window.win_kueXYZ geladen - Vergleiche in handleSave.ts angepasst für stabile Zahl/String-Auswertung - Fehlerhafte Meldung „Keine Änderungen vorgenommen“ behoben - Nur geänderte Werte werden per GET-API gesendet
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"use client"; // components/modules/kue705FO/Kue705FO.tsx
|
||||
import React, { useState, useEffect, useRef, useMemo } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import KueModal from "./KueModal";
|
||||
import KueModal from "./modals/KueModal";
|
||||
import "bootstrap-icons/font/bootstrap-icons.css"; // Import Bootstrap Icons
|
||||
import { Kue705FOProps } from "../../../../types/components/Kue705FOProps";
|
||||
import ChartSwitcher from "./Charts/ChartSwitcher";
|
||||
|
||||
@@ -1,304 +0,0 @@
|
||||
"use client"; // components/modales/KueModal.jsx
|
||||
import ReactModal from "react-modal";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import type { RootState } from "../../../../redux/store";
|
||||
import "bootstrap-icons/font/bootstrap-icons.css";
|
||||
import handleSave, { OriginalValues } from "./handlers/handleSave";
|
||||
import handleDisplayEinschalten from "./handlers/handleDisplayEinschalten";
|
||||
import firmwareUpdate from "./handlers/firmwareUpdate";
|
||||
import decodeToken from "../../../../utils/decodeToken";
|
||||
import { setKueData } from "../../../../redux/slices/kueDataSlice";
|
||||
|
||||
interface KueModalProps {
|
||||
showModal: boolean;
|
||||
onClose: () => void;
|
||||
slot: number;
|
||||
onModulNameChange: (id: string) => void;
|
||||
}
|
||||
|
||||
function KueModal({
|
||||
showModal,
|
||||
onClose,
|
||||
slot,
|
||||
onModulNameChange,
|
||||
}: KueModalProps): JSX.Element {
|
||||
const dispatch = useDispatch();
|
||||
const isAdminLoggedIn = useSelector(
|
||||
(state: any) => state.authSlice.isAdminLoggedIn
|
||||
);
|
||||
const [isAdmin, setIsAdmin] = useState(false);
|
||||
|
||||
const {
|
||||
kueID,
|
||||
kueLimit1,
|
||||
kueDelay1,
|
||||
kueLimit2Low,
|
||||
kueLimit2High,
|
||||
kueLoopInterval,
|
||||
} = useSelector((state: RootState) => state.kueDataSlice);
|
||||
|
||||
const [bezeichnungen, setBezeichnungen] = useState(Array(32).fill(""));
|
||||
|
||||
const [originalValues, setOriginalValues] = useState<OriginalValues>({
|
||||
kueID: Array(32).fill(""),
|
||||
kueBezeichnungen: Array(32).fill(""),
|
||||
isolationsgrenzwerte: Array(32).fill(10.0),
|
||||
verzoegerung: Array(32).fill(1.0),
|
||||
untereSchleifenGrenzwerte: Array(32).fill(0.1),
|
||||
obereSchleifenGrenzwerte: Array(32).fill(1.0),
|
||||
schleifenintervall: Array(32).fill(24),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (showModal) {
|
||||
setBezeichnungen(
|
||||
kueID
|
||||
? kueID.map((name: string) => name.trim() || "---")
|
||||
: bezeichnungen
|
||||
);
|
||||
|
||||
setOriginalValues({
|
||||
kueID: [...kueID],
|
||||
kueBezeichnungen: [...bezeichnungen],
|
||||
isolationsgrenzwerte: [...kueLimit1],
|
||||
verzoegerung: [...kueDelay1],
|
||||
untereSchleifenGrenzwerte: [...kueLimit2Low],
|
||||
obereSchleifenGrenzwerte: [...kueLimit2High],
|
||||
schleifenintervall: [...kueLoopInterval],
|
||||
});
|
||||
}
|
||||
}, [
|
||||
showModal,
|
||||
kueID,
|
||||
kueLimit1,
|
||||
kueDelay1,
|
||||
kueLimit2Low,
|
||||
kueLimit2High,
|
||||
kueLoopInterval,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const token = sessionStorage.getItem("token");
|
||||
if (token) {
|
||||
const decoded = decodeToken(token);
|
||||
setIsAdmin(decoded?.role?.toLowerCase() === "admin");
|
||||
}
|
||||
}, [showModal]);
|
||||
|
||||
const handleSaveWrapper = () => {
|
||||
handleSave({
|
||||
ids: [...kueID],
|
||||
bezeichnungen,
|
||||
isolationsgrenzwerte: [...kueLimit1],
|
||||
verzoegerung: [...kueDelay1],
|
||||
untereSchleifenGrenzwerte: [...kueLimit2Low],
|
||||
obereSchleifenGrenzwerte: [...kueLimit2High],
|
||||
schleifenintervall: [...kueLoopInterval],
|
||||
originalValues,
|
||||
slot,
|
||||
dispatch,
|
||||
onModulNameChange,
|
||||
onClose,
|
||||
});
|
||||
};
|
||||
|
||||
// Korrekte updateArray Methode ohne Thunk
|
||||
const updateArray = (
|
||||
key: keyof RootState["kueDataSlice"],
|
||||
array: number[],
|
||||
value: number
|
||||
) => {
|
||||
const updatedArray = [...array];
|
||||
updatedArray[slot] = value;
|
||||
dispatch(setKueData({ [key]: updatedArray }));
|
||||
};
|
||||
|
||||
const handleDisplayEinschaltenWrapper = () => {
|
||||
handleDisplayEinschalten(slot);
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactModal
|
||||
isOpen={showModal}
|
||||
onRequestClose={onClose}
|
||||
ariaHideApp={false}
|
||||
style={{
|
||||
overlay: {
|
||||
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
||||
zIndex: 100,
|
||||
},
|
||||
content: {
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
right: "auto",
|
||||
bottom: "auto",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: "90%",
|
||||
maxWidth: "800px",
|
||||
padding: "10px",
|
||||
borderRadius: "8px",
|
||||
border: "none",
|
||||
position: "relative", // wichtig
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div className="relative bg-littwin-blue text-white p-1 rounded-t-lg">
|
||||
<h2 className="text-sm font-bold">KUE Einstellung - Slot {slot + 1}</h2>
|
||||
<button
|
||||
onClick={onClose}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "0rem",
|
||||
right: "0.5rem",
|
||||
background: "transparent",
|
||||
border: "none",
|
||||
fontSize: "1.5rem",
|
||||
color: "#000",
|
||||
cursor: "pointer",
|
||||
zIndex: 10,
|
||||
}}
|
||||
>
|
||||
<i className="bi bi-x-circle-fill"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="p-2 mb-4 text-black">
|
||||
<label className="font-bold">Kabelbezeichnung:</label>
|
||||
<input
|
||||
type="text"
|
||||
className="border rounded p-1 w-full text-sm"
|
||||
value={kueID[slot] || ""}
|
||||
onChange={(e) => {
|
||||
const newIds = [...kueID];
|
||||
newIds[slot] = e.target.value;
|
||||
dispatch(setKueData({ kueID: newIds }));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="p-2 text-black">
|
||||
<h3 className="font-bold text-center mb-4">Isolationsmessung</h3>
|
||||
<table className="w-full text-left border-collapse mb-4">
|
||||
<thead className="bg-gray-100">
|
||||
<tr>
|
||||
<th className="p-2 border text-sm text-center">
|
||||
Grenzwert (MOhm)
|
||||
</th>
|
||||
<th className="p-2 border text-sm text-center">
|
||||
Verzögerung (sek)
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="p-2 border text-center">
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
className="w-[6rem] border rounded p-1 text-sm"
|
||||
value={kueLimit1[slot] ?? ""}
|
||||
onChange={(e) =>
|
||||
updateArray(
|
||||
"kueLimit1",
|
||||
kueLimit1,
|
||||
parseFloat(e.target.value)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
<td className="p-2 border text-center">
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
className="w-[6rem] border rounded p-1 text-sm"
|
||||
value={kueDelay1[slot] ?? ""}
|
||||
onChange={(e) =>
|
||||
updateArray(
|
||||
"kueDelay1",
|
||||
kueDelay1,
|
||||
parseFloat(e.target.value)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3 className="font-bold text-center mb-4">Schleifenmessung</h3>
|
||||
<table className="w-full text-left border-collapse">
|
||||
<thead className="bg-gray-100">
|
||||
<tr>
|
||||
<th className="p-2 border text-sm text-center">
|
||||
Grenzwert (kOhm)
|
||||
</th>
|
||||
<th className="p-2 border text-sm text-center">
|
||||
Schleifenintervall (h)
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="p-2 border text-center">
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
className="w-[6rem] border rounded p-1 text-sm"
|
||||
value={kueLimit2Low[slot] ?? ""}
|
||||
onChange={(e) =>
|
||||
updateArray(
|
||||
"kueLimit2Low",
|
||||
kueLimit2Low,
|
||||
parseFloat(e.target.value)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
<td className="p-2 border text-center">
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
className="w-[6rem] border rounded p-1 text-sm"
|
||||
value={kueLoopInterval[slot] ?? ""}
|
||||
onChange={(e) =>
|
||||
updateArray(
|
||||
"kueLoopInterval",
|
||||
kueLoopInterval,
|
||||
parseFloat(e.target.value)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end bg-gray-100 p-4 rounded-b-lg">
|
||||
{isAdminLoggedIn && (
|
||||
<button
|
||||
onClick={() => firmwareUpdate(slot)}
|
||||
className="bg-littwin-blue text-white p-2 rounded flex items-center mr-2"
|
||||
>
|
||||
Firmware Update
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={handleDisplayEinschaltenWrapper}
|
||||
className="bg-littwin-blue text-white p-2 rounded flex items-center mr-2"
|
||||
>
|
||||
<span className="mr-2">📺</span> Display einschalten
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSaveWrapper}
|
||||
className="bg-littwin-blue text-white p-2 rounded flex items-center"
|
||||
>
|
||||
<span className="mr-2">💾</span> Speichern
|
||||
</button>
|
||||
</div>
|
||||
</ReactModal>
|
||||
);
|
||||
}
|
||||
|
||||
export default KueModal;
|
||||
@@ -3,7 +3,6 @@ import { setKueData } from "../../../../../redux/slices/kueDataSlice";
|
||||
|
||||
export interface OriginalValues {
|
||||
kueID: string[];
|
||||
kueBezeichnungen: string[];
|
||||
isolationsgrenzwerte: number[];
|
||||
verzoegerung: number[];
|
||||
untereSchleifenGrenzwerte: number[];
|
||||
@@ -13,7 +12,6 @@ export interface OriginalValues {
|
||||
|
||||
interface HandleSaveParams {
|
||||
ids: string[];
|
||||
bezeichnungen: string[];
|
||||
isolationsgrenzwerte: number[];
|
||||
verzoegerung: number[];
|
||||
untereSchleifenGrenzwerte: number[];
|
||||
@@ -26,9 +24,17 @@ interface HandleSaveParams {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const isDifferent = (a: any, b: any): boolean => {
|
||||
const aNum = Number(a);
|
||||
const bNum = Number(b);
|
||||
if (!isNaN(aNum) && !isNaN(bNum)) {
|
||||
return Math.abs(aNum - bNum) > 0.0001;
|
||||
}
|
||||
return String(a).trim() !== String(b).trim();
|
||||
};
|
||||
|
||||
const handleSave = async ({
|
||||
ids,
|
||||
bezeichnungen,
|
||||
isolationsgrenzwerte,
|
||||
verzoegerung,
|
||||
untereSchleifenGrenzwerte,
|
||||
@@ -40,88 +46,73 @@ const handleSave = async ({
|
||||
onModulNameChange,
|
||||
onClose,
|
||||
}: HandleSaveParams): Promise<void> => {
|
||||
const changes: Partial<{
|
||||
KID: string;
|
||||
KIA: string;
|
||||
KL_: number;
|
||||
KD_: number;
|
||||
KR_: number;
|
||||
KRO_: number;
|
||||
KRI: number;
|
||||
}> = {};
|
||||
const changesForFile: Record<string, any> = {};
|
||||
|
||||
if (ids[slot] !== originalValues.kueID[slot]) {
|
||||
changes.KID = ids[slot];
|
||||
}
|
||||
if (bezeichnungen[slot] !== originalValues.kueBezeichnungen[slot]) {
|
||||
changes.KIA = bezeichnungen[slot];
|
||||
if (isDifferent(ids[slot], originalValues.kueID[slot])) {
|
||||
changesForFile.win_kueID = ids[slot];
|
||||
}
|
||||
if (
|
||||
isolationsgrenzwerte[slot] !== originalValues.isolationsgrenzwerte[slot]
|
||||
isDifferent(
|
||||
isolationsgrenzwerte[slot],
|
||||
originalValues.isolationsgrenzwerte[slot]
|
||||
)
|
||||
) {
|
||||
changes.KL_ = isolationsgrenzwerte[slot];
|
||||
changesForFile.win_kueLimit1 = isolationsgrenzwerte[slot];
|
||||
}
|
||||
if (verzoegerung[slot] !== originalValues.verzoegerung[slot]) {
|
||||
changes.KD_ = verzoegerung[slot];
|
||||
if (isDifferent(verzoegerung[slot], originalValues.verzoegerung[slot])) {
|
||||
changesForFile.win_kueDelay1 = verzoegerung[slot];
|
||||
}
|
||||
if (
|
||||
untereSchleifenGrenzwerte[slot] !==
|
||||
originalValues.untereSchleifenGrenzwerte[slot]
|
||||
isDifferent(
|
||||
untereSchleifenGrenzwerte[slot],
|
||||
originalValues.untereSchleifenGrenzwerte[slot]
|
||||
)
|
||||
) {
|
||||
changes.KR_ = untereSchleifenGrenzwerte[slot];
|
||||
changesForFile.win_kueLimit2Low = untereSchleifenGrenzwerte[slot];
|
||||
}
|
||||
if (
|
||||
obereSchleifenGrenzwerte[slot] !==
|
||||
originalValues.obereSchleifenGrenzwerte[slot]
|
||||
isDifferent(
|
||||
obereSchleifenGrenzwerte[slot],
|
||||
originalValues.obereSchleifenGrenzwerte[slot]
|
||||
)
|
||||
) {
|
||||
changes.KRO_ = obereSchleifenGrenzwerte[slot];
|
||||
changesForFile.win_kueLimit2High = obereSchleifenGrenzwerte[slot];
|
||||
}
|
||||
if (schleifenintervall[slot] !== originalValues.schleifenintervall[slot]) {
|
||||
changes.KRI = schleifenintervall[slot];
|
||||
if (
|
||||
isDifferent(
|
||||
schleifenintervall[slot],
|
||||
originalValues.schleifenintervall[slot]
|
||||
)
|
||||
) {
|
||||
changesForFile.win_kueLoopInterval = schleifenintervall[slot];
|
||||
}
|
||||
|
||||
if (Object.keys(changes).length > 0) {
|
||||
if (Object.keys(changesForFile).length > 0) {
|
||||
const isDev = window.location.hostname === "localhost";
|
||||
|
||||
if (isDev) {
|
||||
await fetch("/api/cpl/updateKueDataAPIHandler", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
slot,
|
||||
changes: {
|
||||
win_kueID: ids[slot],
|
||||
win_kueLimit1: isolationsgrenzwerte[slot],
|
||||
win_kueDelay1: verzoegerung[slot],
|
||||
win_kueLimit2Low: untereSchleifenGrenzwerte[slot],
|
||||
win_kueLimit2High: obereSchleifenGrenzwerte[slot],
|
||||
win_kueLoopInterval: schleifenintervall[slot],
|
||||
},
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
let url = `/cpl?/kabelueberwachung.html&slot=${slot}`;
|
||||
Object.entries(changes).forEach(([paramKey, paramValue]) => {
|
||||
if (paramValue !== undefined) {
|
||||
url += `&${paramKey}${slot}=${encodeURIComponent(paramValue)}`;
|
||||
for (const [key, value] of Object.entries(changesForFile)) {
|
||||
const params = new URLSearchParams({
|
||||
key,
|
||||
value: String(value),
|
||||
slot: String(slot),
|
||||
});
|
||||
const response = await fetch(
|
||||
`/api/cpl/updateKueDataAPIHandler?${params.toString()}`
|
||||
);
|
||||
if (!response.ok) {
|
||||
alert(`❌ Fehler beim Schreiben der Datei (${key})`);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
const response = await fetch(url, { method: "GET" });
|
||||
|
||||
if (!response.ok) {
|
||||
alert("Fehler beim Speichern der Daten!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
alert("Daten erfolgreich gespeichert!");
|
||||
alert("✅ Daten erfolgreich gespeichert!");
|
||||
onModulNameChange(ids[slot]);
|
||||
|
||||
dispatch(
|
||||
setKueData({
|
||||
kueID: [...ids],
|
||||
kueBezeichnungen: [...bezeichnungen],
|
||||
isolationsgrenzwerte: [...isolationsgrenzwerte],
|
||||
verzoegerung: [...verzoegerung],
|
||||
untereSchleifenGrenzwerte: [...untereSchleifenGrenzwerte],
|
||||
@@ -130,7 +121,7 @@ const handleSave = async ({
|
||||
})
|
||||
);
|
||||
} else {
|
||||
alert("Keine Änderungen vorgenommen.");
|
||||
alert("ℹ️ Keine Änderungen vorgenommen.");
|
||||
}
|
||||
|
||||
onClose();
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from "react";
|
||||
|
||||
interface Props {
|
||||
slot: number;
|
||||
}
|
||||
|
||||
export default function Knotenpunkte({ slot }: Props) {
|
||||
return <div>Knotenpunkte – Slot {slot + 1}</div>;
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
"use client";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import type { RootState } from "../../../../../redux/store";
|
||||
import { setKueData } from "../../../../../redux/slices/kueDataSlice";
|
||||
import handleSave, { OriginalValues } from "../handlers/handleSave";
|
||||
import handleDisplayEinschalten from "../handlers/handleDisplayEinschalten";
|
||||
import firmwareUpdate from "../handlers/firmwareUpdate";
|
||||
|
||||
interface Props {
|
||||
slot: number;
|
||||
onClose?: () => void;
|
||||
onModulNameChange?: (id: string) => void;
|
||||
}
|
||||
|
||||
export default function KueEinstellung({
|
||||
slot,
|
||||
onClose = () => {},
|
||||
onModulNameChange = () => {},
|
||||
}: Props) {
|
||||
const dispatch = useDispatch();
|
||||
const {
|
||||
kueID,
|
||||
kueLimit1,
|
||||
kueDelay1,
|
||||
kueLimit2Low,
|
||||
kueLoopInterval,
|
||||
kueLimit2High,
|
||||
} = useSelector((state: RootState) => state.kueDataSlice);
|
||||
|
||||
const isAdminLoggedIn = useSelector(
|
||||
(state: any) => state.authSlice.isAdminLoggedIn
|
||||
);
|
||||
|
||||
const handleSaveWrapper = () => {
|
||||
const originalValues: OriginalValues = {
|
||||
kueID: [...(window.win_kueID ?? [])],
|
||||
isolationsgrenzwerte: [...(window.win_kueLimit1 ?? [])],
|
||||
verzoegerung: [...(window.win_kueDelay1 ?? [])],
|
||||
untereSchleifenGrenzwerte: [...(window.win_kueLimit2Low ?? [])],
|
||||
obereSchleifenGrenzwerte: [...(window.win_kueLimit2High ?? [])],
|
||||
schleifenintervall: [...(window.win_kueLoopInterval ?? [])],
|
||||
};
|
||||
|
||||
handleSave({
|
||||
ids: [...kueID],
|
||||
isolationsgrenzwerte: [...kueLimit1],
|
||||
verzoegerung: [...kueDelay1],
|
||||
untereSchleifenGrenzwerte: [...kueLimit2Low],
|
||||
obereSchleifenGrenzwerte: [...kueLimit2High],
|
||||
schleifenintervall: [...kueLoopInterval],
|
||||
originalValues,
|
||||
slot,
|
||||
dispatch,
|
||||
onModulNameChange,
|
||||
onClose,
|
||||
});
|
||||
};
|
||||
|
||||
const updateArray = (
|
||||
key: keyof RootState["kueDataSlice"],
|
||||
array: number[],
|
||||
value: number
|
||||
) => {
|
||||
const updated = [...array];
|
||||
updated[slot] = value;
|
||||
dispatch(setKueData({ [key]: updated }));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="text-black space-y-6">
|
||||
<div>
|
||||
<label className="font-bold">Kabelbezeichnung:</label>
|
||||
<input
|
||||
type="text"
|
||||
className="w-full border rounded p-1 text-sm"
|
||||
value={kueID[slot] || ""}
|
||||
onChange={(e) => {
|
||||
const newIds = [...kueID];
|
||||
newIds[slot] = e.target.value;
|
||||
dispatch(setKueData({ kueID: newIds }));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-bold text-center mb-2">Isolationsmessung</h3>
|
||||
<table className="w-full border-collapse text-sm">
|
||||
<thead className="bg-gray-100">
|
||||
<tr>
|
||||
<th className="border p-2 text-center">Grenzwert (MOhm)</th>
|
||||
<th className="border p-2 text-center">Verzögerung (sek)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="border p-2 text-center">
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
className="w-[6rem] border rounded p-1"
|
||||
value={kueLimit1[slot] ?? ""}
|
||||
onChange={(e) =>
|
||||
updateArray(
|
||||
"kueLimit1",
|
||||
kueLimit1,
|
||||
parseFloat(e.target.value)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
<td className="border p-2 text-center">
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
className="w-[6rem] border rounded p-1"
|
||||
value={kueDelay1[slot] ?? ""}
|
||||
onChange={(e) =>
|
||||
updateArray(
|
||||
"kueDelay1",
|
||||
kueDelay1,
|
||||
parseFloat(e.target.value)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-bold text-center mb-2">Schleifenmessung</h3>
|
||||
<table className="w-full border-collapse text-sm">
|
||||
<thead className="bg-gray-100">
|
||||
<tr>
|
||||
<th className="border p-2 text-center">Grenzwert (kOhm)</th>
|
||||
<th className="border p-2 text-center">Schleifenintervall (h)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="border p-2 text-center">
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
className="w-[6rem] border rounded p-1"
|
||||
value={kueLimit2Low[slot] ?? ""}
|
||||
onChange={(e) =>
|
||||
updateArray(
|
||||
"kueLimit2Low",
|
||||
kueLimit2Low,
|
||||
parseFloat(e.target.value)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
<td className="border p-2 text-center">
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
className="w-[6rem] border rounded p-1"
|
||||
value={kueLoopInterval[slot] ?? ""}
|
||||
onChange={(e) =>
|
||||
updateArray(
|
||||
"kueLoopInterval",
|
||||
kueLoopInterval,
|
||||
parseFloat(e.target.value)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-2 bg-gray-100 p-3 rounded">
|
||||
{isAdminLoggedIn && (
|
||||
<button
|
||||
onClick={() => firmwareUpdate(slot)}
|
||||
className="bg-littwin-blue text-white px-4 py-2 rounded flex items-center"
|
||||
>
|
||||
<span className="mr-2">🔧</span> Firmware Update
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={() => handleDisplayEinschalten(slot)}
|
||||
className="bg-littwin-blue text-white px-4 py-2 rounded flex items-center"
|
||||
>
|
||||
<span className="mr-2">📺</span> Display einschalten
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSaveWrapper}
|
||||
className="bg-littwin-blue text-white px-4 py-2 rounded flex items-center"
|
||||
>
|
||||
<span className="mr-2">💾</span> Speichern
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
108
components/main/kabelueberwachung/kue705FO/modals/KueModal.tsx
Normal file
108
components/main/kabelueberwachung/kue705FO/modals/KueModal.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
"use client";
|
||||
import { useState, useEffect } from "react";
|
||||
import ReactModal from "react-modal";
|
||||
import KueEinstellung from "./KueEinstellung";
|
||||
import TdrEinstellung from "./TdrEinstellung";
|
||||
import Knotenpunkte from "./Knotenpunkte";
|
||||
|
||||
interface KueModalProps {
|
||||
showModal: boolean;
|
||||
onClose: () => void;
|
||||
slot: number;
|
||||
onModulNameChange: (id: string) => void; // NEU!
|
||||
}
|
||||
|
||||
export default function KueModal({ showModal, onClose, slot }: KueModalProps) {
|
||||
const [activeTab, setActiveTab] = useState<"kue" | "tdr" | "knoten">("kue");
|
||||
|
||||
useEffect(() => {
|
||||
if (showModal) {
|
||||
setActiveTab("kue");
|
||||
}
|
||||
}, [showModal]);
|
||||
|
||||
return (
|
||||
<ReactModal
|
||||
isOpen={showModal}
|
||||
onRequestClose={onClose}
|
||||
ariaHideApp={false}
|
||||
style={{
|
||||
overlay: {
|
||||
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
||||
zIndex: 100,
|
||||
},
|
||||
content: {
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
right: "auto",
|
||||
bottom: "auto",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: "90%",
|
||||
maxWidth: "850px",
|
||||
padding: "0px",
|
||||
border: "none",
|
||||
borderRadius: "8px",
|
||||
position: "relative",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div className="bg-littwin-blue text-white p-2 flex justify-between items-center rounded-t-md">
|
||||
<h2 className="text-sm font-bold">Einstellungen – Slot {slot + 1}</h2>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-white text-xl hover:text-gray-200"
|
||||
>
|
||||
<i className="bi bi-x-circle-fill"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center bg-gray-100 space-x-2 p-2">
|
||||
<button
|
||||
onClick={() => setActiveTab("kue")}
|
||||
className={`px-4 py-1 rounded-t font-bold text-sm ${
|
||||
activeTab === "kue"
|
||||
? "bg-white text-blue-600"
|
||||
: "text-gray-500 hover:text-black"
|
||||
}`}
|
||||
>
|
||||
KUE Einstellung
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab("tdr")}
|
||||
className={`px-4 py-1 rounded-t font-bold text-sm ${
|
||||
activeTab === "tdr"
|
||||
? "bg-white text-blue-600"
|
||||
: "text-gray-500 hover:text-black"
|
||||
}`}
|
||||
>
|
||||
TDR Einstellung
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab("knoten")}
|
||||
className={`px-4 py-1 rounded-t font-bold text-sm ${
|
||||
activeTab === "knoten"
|
||||
? "bg-white text-blue-600"
|
||||
: "text-gray-500 hover:text-black"
|
||||
}`}
|
||||
>
|
||||
Knotenpunkte
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="p-4 bg-white rounded-b-md max-h-[75vh] overflow-y-auto">
|
||||
{activeTab === "kue" && (
|
||||
<KueEinstellung
|
||||
slot={slot}
|
||||
onModulNameChange={(id) => {
|
||||
console.log("Modulname geändert:", id);
|
||||
}}
|
||||
onClose={onClose}
|
||||
/>
|
||||
)}
|
||||
|
||||
{activeTab === "tdr" && <TdrEinstellung slot={slot} />}
|
||||
{activeTab === "knoten" && <Knotenpunkte slot={slot} />}
|
||||
</div>
|
||||
</ReactModal>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from "react";
|
||||
|
||||
interface Props {
|
||||
slot: number;
|
||||
}
|
||||
|
||||
export default function TdrEinstellung({ slot }: Props) {
|
||||
return <div>TdrEinstellung – Slot {slot + 1}</div>;
|
||||
}
|
||||
Reference in New Issue
Block a user