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:
Ismail Ali
2025-02-25 19:46:52 +01:00
parent 327a101386
commit 8c01dd3fc3
12 changed files with 591 additions and 175 deletions

View 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>
);
}

View File

@@ -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;

View 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>
);
}

View File

@@ -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]);
};