- <select> durch Headless UI Listbox ersetzt - Optionen DIA0, DIA1, DIA2 mit deutschem Label dargestellt - Einheitliches Styling mit littwin-blue wie in anderen Komponenten
158 lines
5.0 KiB
TypeScript
158 lines
5.0 KiB
TypeScript
// components/main/system/DetailModal.tsx
|
||
"use client";
|
||
import React from "react";
|
||
import { Line } from "react-chartjs-2";
|
||
import { useSelector } from "react-redux";
|
||
import { RootState } from "@/redux/store";
|
||
import { Listbox } from "@headlessui/react";
|
||
|
||
type Props = {
|
||
isOpen: boolean;
|
||
selectedKey: string | null;
|
||
onClose: () => void;
|
||
zeitraum: "DIA0" | "DIA1" | "DIA2";
|
||
setZeitraum: (typ: "DIA0" | "DIA1" | "DIA2") => void;
|
||
};
|
||
|
||
type ReduxDataEntry = { t: string; i: number };
|
||
|
||
export const DetailModal = ({
|
||
isOpen,
|
||
selectedKey,
|
||
onClose,
|
||
zeitraum,
|
||
setZeitraum,
|
||
}: Props) => {
|
||
const reduxData: ReduxDataEntry[] = useSelector((state: RootState) => {
|
||
switch (selectedKey) {
|
||
case "+5V":
|
||
return state.systemspannung5Vplus[zeitraum] as ReduxDataEntry[];
|
||
case "+15V":
|
||
return state.systemspannung15Vplus[zeitraum] as ReduxDataEntry[];
|
||
case "-15V":
|
||
return state.systemspannung15Vminus[zeitraum] as ReduxDataEntry[];
|
||
case "-98V":
|
||
return state.systemspannung98Vminus[zeitraum] as ReduxDataEntry[];
|
||
case "ADC Temp":
|
||
return state.temperaturAdWandler[zeitraum] as ReduxDataEntry[];
|
||
case "CPU Temp":
|
||
return state.temperaturProzessor[zeitraum] as ReduxDataEntry[];
|
||
default:
|
||
return [] as ReduxDataEntry[];
|
||
}
|
||
});
|
||
|
||
const labels = reduxData.map((e: ReduxDataEntry) => e.t);
|
||
const values = reduxData.map((e: ReduxDataEntry) => e.i);
|
||
|
||
const baseOptions = {
|
||
responsive: true,
|
||
maintainAspectRatio: false,
|
||
scales: {
|
||
y: {
|
||
beginAtZero: false,
|
||
grid: { color: "rgba(200,200,200,0.2)" },
|
||
title: { display: true, text: "Wert" },
|
||
},
|
||
x: {
|
||
grid: { color: "rgba(200,200,200,0.2)" },
|
||
title: { display: true, text: "Zeit" },
|
||
},
|
||
},
|
||
plugins: {
|
||
legend: { position: "bottom" as const },
|
||
title: { display: true, text: `Verlauf – ${selectedKey}` },
|
||
},
|
||
};
|
||
|
||
if (!isOpen || !selectedKey) return null;
|
||
|
||
return (
|
||
<div className="fixed inset-0 bg-black bg-opacity-40 flex items-center justify-center z-50">
|
||
<div className="bg-white p-6 rounded-xl w-[50%] h-[60%] overflow-auto shadow-2xl">
|
||
<div className="flex justify-between items-center mb-4">
|
||
<h2 className="text-xl font-semibold">
|
||
Detailansicht: {selectedKey}
|
||
</h2>
|
||
<button onClick={onClose} className="text-red-500 hover:text-red-700">
|
||
✕
|
||
</button>
|
||
</div>
|
||
|
||
<div className="flex items-center space-x-2 mb-4">
|
||
<label className="font-medium">Zeitraum:</label>
|
||
<Listbox value={zeitraum} onChange={setZeitraum}>
|
||
<div className="relative w-48">
|
||
<Listbox.Button className="w-full border px-3 py-1 rounded text-left bg-white flex justify-between items-center text-sm">
|
||
<span>
|
||
{
|
||
{
|
||
DIA0: "Alle Messwerte",
|
||
DIA1: "Stündlich",
|
||
DIA2: "Täglich",
|
||
}[zeitraum]
|
||
}
|
||
</span>
|
||
<svg
|
||
className="w-5 h-5 text-gray-400"
|
||
viewBox="0 0 20 20"
|
||
fill="currentColor"
|
||
>
|
||
<path
|
||
fillRule="evenodd"
|
||
d="M5.23 7.21a.75.75 0 011.06.02L10 10.585l3.71-3.355a.75.75 0 111.02 1.1l-4.25 3.85a.75.75 0 01-1.02 0l-4.25-3.85a.75.75 0 01.02-1.06z"
|
||
clipRule="evenodd"
|
||
/>
|
||
</svg>
|
||
</Listbox.Button>
|
||
<Listbox.Options className="absolute z-50 mt-1 w-full border rounded bg-white shadow max-h-60 overflow-auto text-sm">
|
||
{["DIA0", "DIA1", "DIA2"].map((option) => (
|
||
<Listbox.Option
|
||
key={option}
|
||
value={option}
|
||
className={({ selected, active }) =>
|
||
`px-4 py-1 cursor-pointer ${
|
||
selected
|
||
? "bg-littwin-blue text-white"
|
||
: active
|
||
? "bg-blue-100"
|
||
: ""
|
||
}`
|
||
}
|
||
>
|
||
{
|
||
{
|
||
DIA0: "Alle Messwerte",
|
||
DIA1: "Stündlich",
|
||
DIA2: "Täglich",
|
||
}[option]
|
||
}
|
||
</Listbox.Option>
|
||
))}
|
||
</Listbox.Options>
|
||
</div>
|
||
</Listbox>
|
||
</div>
|
||
|
||
<div className="h-[85%]">
|
||
<Line
|
||
data={{
|
||
labels,
|
||
datasets: [
|
||
{
|
||
label: selectedKey,
|
||
data: values,
|
||
borderColor: "rgba(59,130,246,1)",
|
||
backgroundColor: "rgba(59,130,246,0.2)",
|
||
fill: false,
|
||
},
|
||
],
|
||
}}
|
||
options={baseOptions}
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|