Feat: KVz Bereich in EinstellungsModal in KÜs Modal

This commit is contained in:
ISA
2025-07-31 10:42:06 +02:00
parent b68eb10ad4
commit 97eb40e1c6
8 changed files with 235 additions and 19 deletions

View File

@@ -6,6 +6,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
NEXT_PUBLIC_EXPORT_STATIC=false NEXT_PUBLIC_EXPORT_STATIC=false
NEXT_PUBLIC_USE_CGI=false NEXT_PUBLIC_USE_CGI=false
# App-Versionsnummer # App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.660 NEXT_PUBLIC_APP_VERSION=1.6.661
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter) NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)

View File

@@ -5,5 +5,5 @@ NEXT_PUBLIC_CPL_API_PATH=/CPL
NEXT_PUBLIC_EXPORT_STATIC=true NEXT_PUBLIC_EXPORT_STATIC=true
NEXT_PUBLIC_USE_CGI=true NEXT_PUBLIC_USE_CGI=true
# App-Versionsnummer # App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.660 NEXT_PUBLIC_APP_VERSION=1.6.661
NEXT_PUBLIC_CPL_MODE=production NEXT_PUBLIC_CPL_MODE=production

View File

@@ -1,3 +1,8 @@
## [1.6.661] 2025-07-31
- feat: TDR starten Button in KÜ Chart
---
## [1.6.660] 2025-07-31 ## [1.6.660] 2025-07-31
- fix: Schleifenwiderstand (TDR) Messung starten Button auf der Produktion - fix: Schleifenwiderstand (TDR) Messung starten Button auf der Produktion

View File

@@ -79,6 +79,7 @@ const Kue705FO: React.FC<Kue705FOProps> = ({
kueOverflow: kueOverflowRaw, kueOverflow: kueOverflowRaw,
kuePSTmMinus96V, // <- richtig, weil so im State vorhanden kuePSTmMinus96V, // <- richtig, weil so im State vorhanden
tdrActive, // <- TDR aktiv Status hinzugefügt tdrActive, // <- TDR aktiv Status hinzugefügt
win_fallSensorsActive, // <- KVz aktiv Status hinzugefügt
} = useSelector((state: RootState) => state.kueDataSlice); } = useSelector((state: RootState) => state.kueDataSlice);
//--------------------------------------------- //---------------------------------------------
@@ -227,6 +228,9 @@ const Kue705FO: React.FC<Kue705FOProps> = ({
// TDR aktiv Status für diesen Slot prüfen // TDR aktiv Status für diesen Slot prüfen
const isTdrActiveForSlot = tdrActive?.[slotIndex] === 1; const isTdrActiveForSlot = tdrActive?.[slotIndex] === 1;
// KVz aktiv Status für diesen Slot prüfen
const isKvzActiveForSlot = win_fallSensorsActive?.[slotIndex] === 1;
// Removed useChartData(loopMeasurementCurveChartData) as the state was unused // Removed useChartData(loopMeasurementCurveChartData) as the state was unused
//--------------------------------- //---------------------------------
@@ -401,12 +405,15 @@ const Kue705FO: React.FC<Kue705FOProps> = ({
TDR TDR
</button> </button>
)} )}
<button {/* KVz Button - nur anzeigen wenn KVz aktiv ist */}
onClick={openKvzModal} {isKvzActiveForSlot && (
className="bg-littwin-blue text-white text-[0.625rem] flex items-center justify-center p-2" <button
> onClick={openKvzModal}
KVz className="bg-littwin-blue text-white text-[0.625rem] flex items-center justify-center p-2"
</button> >
KVz
</button>
)}
</div> </div>
{/* Messkurve Button */} {/* Messkurve Button */}
@@ -443,8 +450,8 @@ const Kue705FO: React.FC<Kue705FOProps> = ({
</> </>
)} )}
{/* KVz Panel - Anzeige ganz unten */} {/* KVz Panel - Anzeige ganz unten, nur wenn KVz aktiv ist */}
{showKvzPanel && ( {showKvzPanel && isKvzActiveForSlot && (
<div className=" bg-gray-400 mt-4 border p-1"> <div className=" bg-gray-400 mt-4 border p-1">
<FallSensors /> <FallSensors />
</div> </div>

View File

@@ -0,0 +1,199 @@
"use client";
import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { RootState } from "../../../../../redux/store";
import { setKueData } from "../../../../../redux/slices/kueDataSlice";
import { useAdminAuth } from "../../../settingsPageComponents/hooks/useAdminAuth";
type KvzData = {
// Hier können später weitere KVz-spezifische Einstellungen hinzugefügt werden
kvzSettings: string;
};
declare global {
interface Window {
__kvzCache?: Record<string, { data: KvzData; kvzActive: boolean }>;
}
}
interface Props {
slot: number;
onClose?: () => void;
}
export default function KvzModalView({ slot, onClose }: Props) {
const { isAdminLoggedIn } = useAdminAuth(true);
const dispatch = useDispatch();
const kvzSlice = useSelector((state: RootState) => state.kueDataSlice);
const cacheKey = `kvz_slot_${slot}`;
if (typeof window !== "undefined") {
window.__kvzCache = window.__kvzCache || {};
}
const cachedKvz =
typeof window !== "undefined"
? window.__kvzCache?.[cacheKey] ?? null
: null;
const [kvzData] = useState(
() =>
cachedKvz?.data || {
kvzSettings: "", // Placeholder für zukünftige Einstellungen
}
);
const [kvzActive, setKvzActive] = useState(
() => cachedKvz?.kvzActive ?? kvzSlice.win_fallSensorsActive?.[slot] === 1
);
const updateCache = (data: typeof kvzData, active = kvzActive) => {
if (typeof window !== "undefined") {
(window.__kvzCache ??= {})[cacheKey] = {
data,
kvzActive: active,
};
}
};
const handleKvzToggle = () => {
const newState = !kvzActive;
setKvzActive(newState);
updateCache(kvzData, newState);
// Redux State sofort aktualisieren für UI-Update
const updatedKvzActive = [...(kvzSlice.win_fallSensorsActive || [])];
updatedKvzActive[slot] = newState ? 1 : 0;
dispatch(setKueData({ win_fallSensorsActive: updatedKvzActive }));
const isDev = window.location.hostname === "localhost";
const slotParam = `KVZ${slot}=${newState ? 1 : 0}`;
const reloadAfterConfirm = () => {
const msg = newState
? "✅ KVz wurde aktiviert."
: "⚠️ KVz wurde deaktiviert.";
alert(msg);
location.reload();
};
if (isDev) {
const updates = [
{ key: "win_fallSensorsActive", slot, value: newState ? 1 : 0 },
];
fetch("/api/cpl/updateKvzSettingsDataAPIHandler", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ updates }),
})
.then((res) => res.json())
.then(() => {
console.log("KVz-Aktiv-Status gespeichert.");
reloadAfterConfirm();
})
.catch((err) => {
console.error("Fehler beim Speichern von KVz aktiv:", err);
});
} else {
const url = `${window.location.origin}/CPL?/kabelueberwachung.html&${slotParam}`;
fetch(url)
.then((res) => {
if (!res.ok) throw new Error("KVz-Befehl fehlgeschlagen");
console.log("KVz aktiviert/deaktiviert:", res.status);
reloadAfterConfirm();
})
.catch((err) => {
console.error("Fehler beim KVz-Befehl:", err);
alert("Fehler beim Umschalten der KVz-Funktion.");
});
}
};
const handleSave = () => {
const isDev = window.location.hostname === "localhost";
if (isDev) {
const updates = [
{ key: "win_fallSensorsActive", slot, value: kvzActive ? 1 : 0 },
// Hier können später weitere KVz-Einstellungen hinzugefügt werden
];
fetch("/api/cpl/updateKvzSettingsDataAPIHandler", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ updates }),
})
.then((res) => res.json())
.then(() => {
alert("KVz-Einstellungen erfolgreich gespeichert.");
if (typeof onClose === "function") onClose();
})
.catch((err) => {
console.error("Fehler beim Speichern:", err);
alert("Speichern fehlgeschlagen.");
});
} else {
// Originaler Webservice-Teil für Produktionsumgebung
alert("KVz-Einstellungen gespeichert.");
if (typeof onClose === "function") onClose();
}
updateCache(kvzData, kvzActive);
};
return (
<div className="p-4 text-sm">
{/* KVz-Funktion */}
{isAdminLoggedIn && (
<div className="mb-4 mt-4 grid grid-cols-3 items-center gap-2 w-full">
<span className="text-sm font-medium">KVz-Funktion:</span>
<div className="col-span-2 flex items-center gap-4">
<button
type="button"
role="switch"
aria-checked={kvzActive}
onClick={handleKvzToggle}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors duration-200 ${
kvzActive ? "bg-littwin-blue" : "bg-gray-300"
}`}
>
<span
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform duration-200 ${
kvzActive ? "translate-x-6" : "translate-x-1"
}`}
/>
</button>
<span className="text-sm text-gray-600">
{kvzActive ? "aktiviert" : "deaktiviert"}
</span>
</div>
</div>
)}
{/* Zukünftige KVz-Einstellungen können hier hinzugefügt werden */}
{!isAdminLoggedIn && (
<div className="mt-6 mb-4">
<div className="mb-4">
<p className="text-sm text-gray-600">
Nur Admin-Benutzer können diese Einstellungen ändern.
</p>
</div>
</div>
)}
{/* Speichern Button */}
{/* <div className="mt-36">
<div className="flex justify-end gap-2 p-3 rounded">
<button
onClick={handleSave}
className="bg-littwin-blue text-white px-4 py-2 rounded flex items-center"
>
Speichern
</button>
</div>
</div> */}
</div>
);
}

View File

@@ -3,6 +3,7 @@ import { useState, useEffect } from "react";
import ReactModal from "react-modal"; import ReactModal from "react-modal";
import KueEinstellung from "./KueEinstellung"; import KueEinstellung from "./KueEinstellung";
import TdrEinstellung from "./TdrEinstellung"; import TdrEinstellung from "./TdrEinstellung";
import KvzModalView from "./KvzModalView";
import Knotenpunkte from "./Knotenpunkte"; import Knotenpunkte from "./Knotenpunkte";
interface KueModalProps { interface KueModalProps {
@@ -14,18 +15,20 @@ interface KueModalProps {
declare global { declare global {
interface Window { interface Window {
__lastKueTab?: "kue" | "tdr" | "knoten"; __lastKueTab?: "kue" | "tdr" | "kvz" | "knoten";
kabelModalOpen?: boolean; kabelModalOpen?: boolean;
} }
} }
export default function KueModal({ showModal, onClose, slot }: KueModalProps) { export default function KueModal({ showModal, onClose, slot }: KueModalProps) {
const [activeTab, setActiveTab] = useState<"kue" | "tdr" | "knoten">(() => { const [activeTab, setActiveTab] = useState<"kue" | "tdr" | "kvz" | "knoten">(
if (typeof window !== "undefined" && window.__lastKueTab) { () => {
return window.__lastKueTab; if (typeof window !== "undefined" && window.__lastKueTab) {
return window.__lastKueTab;
}
return "kue";
} }
return "kue"; );
});
useEffect(() => { useEffect(() => {
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
@@ -77,6 +80,7 @@ export default function KueModal({ showModal, onClose, slot }: KueModalProps) {
{[ {[
{ label: "Allgemein", key: "kue" as const }, { label: "Allgemein", key: "kue" as const },
{ label: "TDR ", key: "tdr" as const }, { label: "TDR ", key: "tdr" as const },
{ label: "KVz", key: "kvz" as const },
{ label: "Knotenpunkte", key: "knoten" as const }, { label: "Knotenpunkte", key: "knoten" as const },
].map(({ label, key }) => ( ].map(({ label, key }) => (
<button <button
@@ -105,6 +109,7 @@ export default function KueModal({ showModal, onClose, slot }: KueModalProps) {
{activeTab === "tdr" && ( {activeTab === "tdr" && (
<TdrEinstellung slot={slot} onClose={onClose} /> <TdrEinstellung slot={slot} onClose={onClose} />
)} )}
{activeTab === "kvz" && <KvzModalView slot={slot} onClose={onClose} />}
{activeTab === "knoten" && ( {activeTab === "knoten" && (
<Knotenpunkte slot={slot} onClose={onClose} /> <Knotenpunkte slot={slot} onClose={onClose} />
)} )}

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.660", "version": "1.6.661",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.660", "version": "1.6.661",
"dependencies": { "dependencies": {
"@fontsource/roboto": "^5.1.0", "@fontsource/roboto": "^5.1.0",
"@headlessui/react": "^2.2.4", "@headlessui/react": "^2.2.4",

View File

@@ -1,6 +1,6 @@
{ {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.660", "version": "1.6.661",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",