git commit -m "feat: UI-Optimierung für analoge Eingänge & Diagramm
- Layout verbessert: Tabelle und Diagramm jetzt nebeneinander (grid-responsive) - Responsivität optimiert: Kein unnötiges horizontales Scrollen mehr - Diagramm verbessert: - Höhere Lesbarkeit mit stärkeren Linien und Abstand für Achsenbeschriftungen - Anpassung der Höhe und Breite für mobile & große Bildschirme - Tabelle optimiert: - Bessere Lesbarkeit mit größeren Abständen - Hover-Effekte für Zeilen - Dynamisches Spaltenlayout für kleine & große Bildschirme - Code aufgeräumt und verbessert Test auf verschiedenen Bildschirmgrößen erfolgreich!"
This commit is contained in:
50
components/main/analogeEingaenge/AnalogInputsChart.tsx
Normal file
50
components/main/analogeEingaenge/AnalogInputsChart.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
"use client"; // components/main/analogeEingaenge/AnalogInputsChart.tsx
|
||||
import React from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RootState } from "../../../redux/store";
|
||||
import {
|
||||
LineChart,
|
||||
Line,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
ResponsiveContainer,
|
||||
} from "recharts";
|
||||
|
||||
export default function AnalogInputsChart() {
|
||||
const analogInputs = useSelector(
|
||||
(state: RootState) => state.analogeEingaenge
|
||||
);
|
||||
|
||||
// Daten für das Diagramm vorbereiten
|
||||
const chartData = Object.values(analogInputs).map((input) => ({
|
||||
name: `Input ${input.id}`,
|
||||
value: input.value ?? 0, // Falls kein Wert vorhanden ist, wird 0 gesetzt
|
||||
}));
|
||||
|
||||
return (
|
||||
<div className="w-full h-[350px] bg-white shadow-md rounded-lg p-4 border border-gray-200">
|
||||
<h3 className="text-sm font-semibold mb-2 text-gray-700">
|
||||
Analog Inputs Chart
|
||||
</h3>
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart
|
||||
data={chartData}
|
||||
margin={{ top: 10, right: 20, left: 0, bottom: 10 }}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="name" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="value"
|
||||
stroke="#4A90E2"
|
||||
strokeWidth={2}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
"use client"; // components/modules/AnalogeEingaengeComponent.tsx
|
||||
import React, { useState } from "react";
|
||||
import { Icon } from "@iconify/react";
|
||||
import { analogInputs } from "../../../data/mockdata/analogInputs";
|
||||
|
||||
const AnalogeEingaengeComponent = () => {
|
||||
const [activeConfig, setActiveConfig] = useState<number | null>(null);
|
||||
|
||||
return (
|
||||
<div className="border rounded-lg shadow-md bg-white flex flex-col h-full p-4 lg:p-6 xl:p-8">
|
||||
<h3 className="text-sm lg:text-base xl:text-lg font-semibold mb-2">
|
||||
Analoge Eingänge
|
||||
</h3>
|
||||
|
||||
<div className="overflow-auto flex-grow">
|
||||
<table className="table-auto w-full text-xs lg:text-sm xl:text-md text-left border-collapse">
|
||||
<thead className="bg-gray-100 text-gray-700">
|
||||
<tr>
|
||||
<th className="px-2 lg:px-3 py-1 lg:py-2 whitespace-nowrap">
|
||||
Eingang
|
||||
</th>
|
||||
<th className="px-2 lg:px-3 py-1 lg:py-2 whitespace-nowrap">
|
||||
Wert
|
||||
</th>
|
||||
<th className="px-2 lg:px-3 py-1 lg:py-2 whitespace-nowrap">
|
||||
Bezeichnung
|
||||
</th>
|
||||
<th className="px-2 lg:px-3 py-1 lg:py-2 text-center">uW</th>
|
||||
<th className="px-2 lg:px-3 py-1 lg:py-2 text-center">uG</th>
|
||||
<th className="px-2 lg:px-3 py-1 lg:py-2 text-center">oW</th>
|
||||
<th className="px-2 lg:px-3 py-1 lg:py-2 text-center">oG</th>
|
||||
<th className="px-2 lg:px-3 py-1 lg:py-2 text-center">Aktion</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="text-gray-600">
|
||||
{analogInputs.map((input) => (
|
||||
<tr
|
||||
key={input.id}
|
||||
className="border-t hover:bg-gray-50 transition"
|
||||
>
|
||||
<td className="px-2 lg:px-3 py-1 lg:py-2">{input.id}</td>
|
||||
<td className="px-2 lg:px-3 py-1 lg:py-2">{input.value}</td>
|
||||
<td className="px-2 lg:px-3 py-1 lg:py-2">{input.name}</td>
|
||||
<td className="px-2 lg:px-3 py-1 lg:py-2 text-center">
|
||||
<span
|
||||
className={
|
||||
input.uW
|
||||
? "text-green-500 text-lg lg:text-xl"
|
||||
: "text-gray-400"
|
||||
}
|
||||
>
|
||||
●
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-2 lg:px-3 py-1 lg:py-2 text-center">
|
||||
<span
|
||||
className={
|
||||
input.uG
|
||||
? "text-green-500 text-lg lg:text-xl"
|
||||
: "text-gray-400"
|
||||
}
|
||||
>
|
||||
●
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-2 lg:px-3 py-1 lg:py-2 text-center">
|
||||
<span
|
||||
className={
|
||||
input.oW
|
||||
? "text-orange-500 text-lg lg:text-xl"
|
||||
: "text-gray-400"
|
||||
}
|
||||
>
|
||||
●
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-2 lg:px-3 py-1 lg:py-2 text-center">
|
||||
<span
|
||||
className={
|
||||
input.oG
|
||||
? "text-green-500 text-lg lg:text-xl"
|
||||
: "text-gray-400"
|
||||
}
|
||||
>
|
||||
●
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-2 lg:px-3 py-1 lg:py-2 text-center">
|
||||
<button
|
||||
onClick={() => setActiveConfig(input.id)}
|
||||
className="text-littwin-blue hover:text-littwin-dark transition"
|
||||
>
|
||||
<Icon
|
||||
icon="mdi:cog-outline"
|
||||
className="w-4 lg:w-5 xl:w-6"
|
||||
/>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AnalogeEingaengeComponent;
|
||||
66
components/main/analogeEingaenge/AnalogeEingaengeTable.tsx
Normal file
66
components/main/analogeEingaenge/AnalogeEingaengeTable.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
"use client"; // components/main/analogeEingaenge/AnalogeEingaengeTable.tsx
|
||||
import React from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RootState } from "../../../redux/store";
|
||||
import { useFetchAnalogeEingaenge } from "./hooks/useFetchAnalogeEingaenge"; // ✅ Hook importieren
|
||||
|
||||
export default function AnalogeEingaengeTable() {
|
||||
useFetchAnalogeEingaenge(); // ✅ Hook aufrufen (lädt Daten und aktualisiert sie regelmäßig)
|
||||
|
||||
const analogeEingaenge = useSelector(
|
||||
(state: RootState) => state.analogeEingaenge
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
{/* Card Container */}
|
||||
<div className="bg-white shadow-lg rounded-lg p-4 border border-gray-200">
|
||||
{/* Card Title */}
|
||||
<h2 className="text-lg md:text-xl font-semibold mb-4 text-gray-700">
|
||||
Analoge Eingänge
|
||||
</h2>
|
||||
|
||||
{/* Tabelle in einem Scroll-Container für kleine Screens */}
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full border-collapse border border-gray-300 text-sm md:text-base">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 text-gray-700">
|
||||
<th className="border p-3 text-left">Eingang</th>
|
||||
<th className="border p-3 text-left">Wert</th>
|
||||
<th className="border p-3 text-left">Bezeichnung</th>
|
||||
<th className="border p-3 text-center">uW</th>
|
||||
<th className="border p-3 text-center">uG</th>
|
||||
<th className="border p-3 text-center">oW</th>
|
||||
<th className="border p-3 text-center">oG</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.values(analogeEingaenge).map((eingang, index) => (
|
||||
<tr
|
||||
key={index}
|
||||
className="text-gray-700 hover:bg-gray-50 transition"
|
||||
>
|
||||
<td className="border p-3">{eingang.id ?? "-"}</td>
|
||||
<td className="border p-3">{eingang.value ?? "-"}</td>
|
||||
<td className="border p-3">{eingang.name || "----"}</td>
|
||||
<td className="border p-3 text-center">
|
||||
{eingang.uW ? "🟢" : "⚪"}
|
||||
</td>
|
||||
<td className="border p-3 text-center">
|
||||
{eingang.uG ? "🟢" : "⚪"}
|
||||
</td>
|
||||
<td className="border p-3 text-center">
|
||||
{eingang.oW ? "🟠" : "⚪"}
|
||||
</td>
|
||||
<td className="border p-3 text-center">
|
||||
{eingang.oG ? "🟢" : "⚪"}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// components/main/analogeEingaenge/hooks/useFetchAnalogeEingaenge.ts
|
||||
import { useEffect } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import {
|
||||
loadFromWindow,
|
||||
setAnalogeEingaenge,
|
||||
} from "../../../../redux/slices/analogeEingaengeSlice";
|
||||
|
||||
export const useFetchAnalogeEingaenge = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(loadFromWindow()); // Initial Mock-Daten aus `window` laden
|
||||
|
||||
const interval = setInterval(async () => {
|
||||
try {
|
||||
const response = await fetch("/api/get-embedded-data");
|
||||
if (!response.ok) throw new Error("Fehler beim Abrufen der Daten");
|
||||
const data = await response.json();
|
||||
dispatch(setAnalogeEingaenge(data));
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Abruf der Sensordaten:", error);
|
||||
}
|
||||
}, 5000); // Alle 5 Sekunden neue Daten abrufen
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [dispatch]);
|
||||
};
|
||||
Reference in New Issue
Block a user