Files
CPLv4.0/components/main/digitalOutputs/DigitalOutputsModal.tsx
2025-09-10 11:49:58 +02:00

143 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"; // /components/main/digitalOutputs/DigitalOutputsModal.tsx
import React, { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import { RootState } from "@/redux/store";
import type { DigitalOutput } from "@/types/digitalOutput";
export default function DigitalOutputsModal({
selectedOutput,
closeOutputModal,
isOpen,
}: {
selectedOutput: DigitalOutput | null;
closeOutputModal: () => void;
isOpen: boolean;
}) {
const allOutputs = useSelector(
(state: RootState) => state.digitalOutputsSlice.outputs
);
const [label, setLabel] = useState("");
const [status, setStatus] = useState(false);
const [isSaving, setIsSaving] = useState(false);
const [errorMsg, setErrorMsg] = useState("");
// ✅ Zustand neu setzen, wenn Modal geöffnet oder anderer Ausgang ausgewählt wird
useEffect(() => {
if (isOpen && selectedOutput) {
setLabel(selectedOutput.label || "");
setStatus(selectedOutput.status || false);
setErrorMsg("");
}
}, [isOpen, selectedOutput]);
if (!isOpen || !selectedOutput) return null;
const handleSave = async () => {
setIsSaving(true);
setErrorMsg("");
const updatedOutputs = allOutputs.map((output) =>
output.id === selectedOutput.id
? { ...output, label: label.trim(), status }
: output
);
const isCPL = process.env.NEXT_PUBLIC_NODE_ENV === "production";
try {
if (isCPL) {
const nameEncoded = encodeURIComponent(label.trim());
const nameUrl = `/CPL?digitalOutputs.html&DAN0${selectedOutput.id}=${nameEncoded}`;
const statusUrl = `/CPL?digitalOutputs.html&DAS0${selectedOutput.id}=${
status ? 1 : 0
}`;
try {
await fetch(nameUrl, { method: "GET" });
await new Promise((res) => setTimeout(res, 300));
await fetch(statusUrl, { method: "GET" });
closeOutputModal(); // Seite bleibt erhalten
} catch (err) {
console.error("❌ Fehler bei fetch:", err);
setErrorMsg("❌ Fehler beim Speichern.");
}
} else {
// 🧪 Lokaler Entwicklungsmodus
const res = await fetch("/api/cpl/updateDigitalOutputsHandler", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ outputs: updatedOutputs }),
});
if (!res.ok) {
const err = await res.json();
setErrorMsg(err?.error || "Fehler beim Speichern.");
} else {
console.log(
"✅ Status & Label gespeichert für Ausgang",
selectedOutput.id
);
closeOutputModal();
}
}
} catch (err) {
console.error("Fehler beim Speichern:", err);
setErrorMsg("❌ Fehler beim Speichern.");
} finally {
setIsSaving(false);
}
};
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-[var(--color-surface)] border border-base rounded-xl shadow-xl w-[32rem] max-w-full p-0 flex flex-col">
<header className="modal-header flex items-center justify-between px-6 py-4 border-b border-base">
<h2 className="text-base font-bold text-fg">
Einstellungen Schaltausgang {selectedOutput.id}
</h2>
<button
onClick={closeOutputModal}
className="icon-btn text-2xl"
aria-label="Modal schließen"
type="button"
>
<i className="bi bi-x-circle-fill" />
</button>
</header>
<div className="modal-body-scroll px-6 py-5 flex-1 text-fg">
<div className="grid grid-cols-2 gap-x-4 gap-y-3">
<div>
<span className="font-normal text-fg-secondary">
Bezeichnung:
</span>
</div>
<div>
<input
type="text"
value={label}
onChange={(e) => setLabel(e.target.value)}
className="border border-base rounded px-2 py-1 w-full bg-[var(--color-surface-alt)] text-fg"
placeholder="z.B. Licht Relais 1"
/>
</div>
</div>
{errorMsg && <p className="text-red-600 text-sm mb-2">{errorMsg}</p>}
</div>
<footer className="px-6 py-4 border-t border-base flex justify-end">
<button
onClick={handleSave}
disabled={isSaving}
className="btn-primary px-4 py-2 rounded flex items-center"
>
{isSaving ? "Speichern..." : "Speichern"}
</button>
</footer>
</div>
</div>
);
}