Files
CPLv4.0/components/main/einausgaenge/modals/InputModal.tsx
2025-04-24 13:19:58 +02:00

243 lines
7.3 KiB
TypeScript

"use client";
// /components/main/einausgaenge/modals/InputModal.tsx
import React, { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { RootState } from "../../../../redux/store";
import {
updateInvertierung,
updateName,
} from "../../../../redux/slices/digitalInputsSlice";
export default function InputModal({ selectedInput, closeInputModal, isOpen }) {
const dispatch = useDispatch();
const reduxInput = useSelector((state: RootState) =>
state.digitalInputsSlice.inputs.find(
(input) => input.id === Number(selectedInput?.id)
)
);
const [isInitialLoad, setIsInitialLoad] = useState(true);
const [name, setName] = useState("");
const [invertiert, setInvertiert] = useState(false);
const [filterzeit, setFilterzeit] = useState(0);
const [gewichtung, setGewichtung] = useState(0);
const [zaehlerAktiv, setZaehlerAktiv] = useState(false);
useEffect(() => {
if (reduxInput && isInitialLoad) {
setName(reduxInput.name || "");
setInvertiert(reduxInput.invertierung);
setFilterzeit(reduxInput.filterzeit);
setGewichtung(reduxInput.gewichtung);
setZaehlerAktiv(reduxInput.zaehlerAktiv);
setIsInitialLoad(false);
}
}, [reduxInput, isInitialLoad]);
if (!isOpen || !selectedInput || !reduxInput) return null;
const handleSpeichern = async () => {
const updates: any = { id: reduxInput.id };
let hasChange = false;
if (name !== reduxInput.name) {
updates.name = name;
dispatch(updateName({ id: reduxInput.id, name }));
hasChange = true;
}
if (invertiert !== reduxInput.invertierung) {
updates.invertierung = invertiert ? 1 : 0;
dispatch(
updateInvertierung({ id: reduxInput.id, invertierung: invertiert })
);
hasChange = true;
}
if (filterzeit !== reduxInput.filterzeit) {
updates.filterzeit = filterzeit;
hasChange = true;
}
if (gewichtung !== reduxInput.gewichtung) {
updates.gewichtung = gewichtung;
hasChange = true;
}
if (zaehlerAktiv !== reduxInput.zaehlerAktiv) {
updates.zaehlerAktiv = zaehlerAktiv ? 1 : 0;
hasChange = true;
}
if (!hasChange) {
alert("⚠️ Keine Änderungen erkannt.");
return;
}
try {
const res = await fetch("/api/cpl/updateDigitaleEingaenge", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(updates),
});
if (!res.ok) {
const errData = await res.json();
throw new Error(errData.error || "Unbekannter Fehler");
}
setIsInitialLoad(true); // Reset
closeInputModal(); // Modal schließen bei Erfolg
} catch (err: any) {
alert("❌ Fehler beim Speichern: " + err.message);
}
};
const handleClose = () => {
setIsInitialLoad(true);
closeInputModal();
};
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="bg-white rounded-lg shadow-lg p-6 w-1/2 max-w-lg">
<h2 className="text-xl font-semibold text-blue-500 mb-4 border-b pb-2">
Parameter für Eingang {selectedInput.id}
</h2>
<div className="grid grid-cols-2 gap-x-4 gap-y-3">
<div>
<strong>Zustand:</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">Aus</span>
</>
) : (
<>
<span className="w-4 h-4 bg-green-500 rounded-full inline-block"></span>
<span className="text-green-600">Ein</span>
</>
)}
</div>
<div>
<strong>Name:</strong>
</div>
<div>
<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}
/>
</div>
<div>
<strong>Invertierung:</strong>
</div>
<div className="flex justify-between items-center gap-2">
<span>{invertiert ? "Ein" : "Aus"}</span>
<button
onClick={() => setInvertiert(!invertiert)}
className="px-3 py-1 text-sm bg-gray-200 hover:bg-gray-300 rounded"
>
Umschalten
</button>
</div>
<div>
<strong>Zählerstand:</strong>
</div>
<div>{reduxInput.counter}</div>
<div>
<strong>Filterzeit:</strong>
</div>
<div className="relative">
<input
type="number"
min={0}
max={2000}
value={filterzeit}
onChange={(e) => {
const val = Number(e.target.value);
if (val <= 2000) {
setFilterzeit(val);
}
}}
className="border border-gray-300 rounded px-2 py-1 pr-10 w-full"
title="Maximal 2000 ms erlaubt"
/>
<span className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
ms
</span>
</div>
<div>
<strong>Gewichtung:</strong>
</div>
<div className="relative">
<input
type="number"
min={0}
max={1000}
value={gewichtung}
onChange={(e) => {
const val = Number(e.target.value);
if (val <= 1000) {
setGewichtung(val);
}
}}
className="border border-gray-300 rounded px-2 py-1 w-full"
title="Maximal 1000 erlaubt"
/>
{gewichtung > 1000 && (
<div className="text-sm text-red-600 mt-1">
Maximalwert 1000 überschritten!
</div>
)}
</div>
<div>
<strong>Zähler aktiv:</strong>
</div>
<div className="flex items-center gap-2">
<span>{zaehlerAktiv ? "Ja" : "Nein"}</span>
<button
onClick={() => setZaehlerAktiv(!zaehlerAktiv)}
className="ml-auto px-3 py-1 text-sm bg-gray-200 hover:bg-gray-300 rounded"
>
Umschalten
</button>
</div>
<div>
<strong>Status:</strong>
</div>
<div>{reduxInput.eingangOffline ? "Inaktiv" : "Aktiv"}</div>
</div>
<div className="mt-6 flex justify-end gap-2">
<button
onClick={handleClose}
className="px-4 py-2 bg-gray-300 hover:bg-gray-400 text-black rounded-lg transition"
>
Schließen
</button>
<button
onClick={handleSpeichern}
className="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg transition"
>
Speichern
</button>
</div>
</div>
</div>
);
}