Files
CPLv4.0/pages/dashboard.tsx
2025-01-27 10:31:11 +01:00

261 lines
9.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"; // app/dashboard/page.jsx
import React from "react";
import { useRouter } from "next/navigation";
import "tailwindcss/tailwind.css";
import "@fontsource/roboto";
import "bootstrap-icons/font/bootstrap-icons.css";
import CPLStatus from "../components/modulesStatus/CPLStatus";
import KabelModulStatus from "../components/modulesStatus/KabelModulStatus";
import { Icon } from "@iconify/react";
import { useSelector } from "react-redux";
import { RootState } from "../store/store";
function Dashboard() {
const router = useRouter();
// Redux-Variablen abrufen
const rawLast20Messages = useSelector(
(state: RootState) => state.variables.last20Messages
);
const ip = useSelector((state: RootState) => state.variables.ip);
const subnet = useSelector((state: RootState) => state.variables.subnet);
const gateway = useSelector((state: RootState) => state.variables.gateway);
const appVersion = useSelector(
(state: RootState) => state.variables.appVersion
);
const kueCableBreak = useSelector(
(state: RootState) => state.variables.kueCableBreak
);
const kueOnline = useSelector(
(state: RootState) => state.variables.kueOnline
);
const kueVersion = useSelector(
(state: RootState) => state.variables.kueVersion
);
const kueAlarm1 = useSelector(
(state: RootState) => state.variables.kueAlarm1
);
const kueAlarm2 = useSelector(
(state: RootState) => state.variables.kueAlarm2
);
const kueGroundFault = useSelector(
(state: RootState) => state.variables.kueGroundFault
);
// Hilfsfunktion zum Parsen der Nachrichten
const parseMessages = (messages) => {
if (typeof messages === "string") {
messages = messages
.replace(/<tr>/g, "\n")
.replace(/<\/?td>/g, "")
.replace(/<\/tr>/g, "")
.trim();
const rows = messages.split("\n");
return rows.map((row) => [
row.substring(0, 5),
row.substring(5, 10),
row.substring(10, 29),
row.substring(33, row.length - 1),
row.substring(row.length - 1),
]);
}
return [];
};
const last20Messages = parseMessages(rawLast20Messages);
const handleModuleClick = (rackNumber) => {
router.push(`/kabelueberwachung?rack=${rackNumber}`);
};
const renderBaugruppentraeger = () => {
const baugruppen: JSX.Element[] = [];
const numBaugruppen = Math.ceil(kueOnline.length / 8);
for (let i = 0; i < numBaugruppen; i++) {
const slots = kueOnline.slice(i * 8, (i + 1) * 8);
baugruppen.push(
<div
key={i}
className="flex bg-white shadow-md rounded-lg mb-4 xl:mb-0 lg:mb-0 border border-gray-200 w-full laptop:scale-y-75 xl:scale-y-90"
>
<div className="flex gap-1">
{slots.map((version, index) => {
const slotNumber = i * 8 + index + 1;
const isSlotOnline = kueOnline[slotNumber - 1] === 1;
const moduleVersion = kueVersion[slotNumber - 1] || version;
// Berechnung der Rack-Nummer basierend auf dem slotNumber
const rackNumber = Math.ceil(slotNumber / 8); // 18 -> Rack 1, 916 -> Rack 2 usw.
return (
<div
key={slotNumber}
className="cursor-pointer"
onClick={() => handleModuleClick(rackNumber)} // Klick-Handler mit Rack-Nummer
>
<KabelModulStatus
slot={slotNumber}
isOnline={isSlotOnline}
moduleVersion={moduleVersion}
kueCableBreak={kueCableBreak}
kueAlarm1={kueAlarm1}
kueAlarm2={kueAlarm2}
kueGroundFault={kueGroundFault}
/>
</div>
);
})}
</div>
</div>
);
}
return baugruppen;
};
return (
<div className="flex flex-col gap-3 p-4 h-[calc(100vh-13vh-8vh)] laptop:h-[calc(100vh-10vh-5vh)] xl:h-[calc(100vh-10vh-6vh)] laptop:gap-0">
<div className="flex justify-between items-center w-full lg:w-2/3">
<div className="flex justify-between gap-1 ">
<Icon
icon="ri:calendar-schedule-line"
className="text-littwin-blue text-4xl xl:text-2xl"
/>
<h1 className="text-xl font-bold text-gray-700 xl:text-base">
Letzten 20 Meldungen
</h1>
</div>
</div>
<div className="flex flex-col lg:flex-row gap-0 overflow-hidden ">
<div className="bg-white shadow-md rounded-lg w-full lg:w-2/3 overflow-auto flex ">
<table className="min-w-full border border-gray-200 text-left table-fixed ">
<thead className="bg-gray-100 border-b border-gray-300">
<tr>
<th className="py-1 px-4 text-gray-700 text-sm font-medium">
ID
</th>
<th className="py-1 px-4 text-gray-700 text-sm font-medium">
Modul
</th>
<th className="py-1 px-4 text-gray-700 text-sm font-medium">
Zeitstempel
</th>
<th className="py-1 px-4 text-gray-700 text-sm font-medium w-2/3">
Meldung
</th>
<th className="py-1 px-4 text-gray-700 text-sm font-medium">
Status
</th>
</tr>
</thead>
<tbody className="text-xs text-gray-600 laptop:text-xs flex-shrink-0 ">
{last20Messages.length > 0 ? (
last20Messages.map((columns, index) => (
<tr
key={index}
className="border-b border-gray-200 hover:bg-gray-50 "
>
<td className="px-4 w-1/7">{columns[0]}</td>
<td className="px-4 w-1/7">{columns[1]}</td>
<td className="px-4 w-3/7 whitespace-nowrap">
<div className="flex flex-row space-x-2">
<span>{columns[2].split(" ")[0]}</span>
<span>{columns[2].split(" ")[1]}</span>
</div>
</td>
<td className="px-4 w-2/7">{columns[3]}</td>
<td className="px-4 w-1/7">{columns[4]}</td>
</tr>
))
) : (
<tr>
<td className="px-4 text-center" colSpan={5}>
Keine Meldungen verfügbar.
</td>
</tr>
)}
</tbody>
</table>
</div>
<div
className="shadow-md rounded-lg
w-full sm:w-3/4 md:w-2/3 lg:w-1/2 xl:w-1/3
flex flex-col gap-2"
>
<div className="bg-gray-50 p-4 sm:p-3 md:p-4 lg:p-2 xl:p-2 rounded-lg shadow-sm border border-gray-200 w-full ">
<h2 className="text-lg 2xl:text-lg xl:text-sm font-semibold text-gray-700 mb-2 ">
Versionsinformationen
</h2>
<div className="flex flex-row p-2 sm:p-1 md:p-2 space-x-2 laptop:p-0 xl:p-0">
<Icon
icon="bx:code-block"
className="text-xl 2xl:text-xl xl:text-base text-blue-400"
/>
<p className="text-sm 2xl:text-lg text-gray-600">
<span className="font-bold"></span> Applikationsversion:{" "}
{appVersion}
</p>
</div>
<div className="flex flex-row p-2 sm:p-1 md:p-2 space-x-2 laptop:p-0 xl:p-0">
<Icon
icon="mdi:web"
className="text-xl lg:text-base text-blue-400"
/>
<p className="text-sm sm:text-xs md:text-sm lg:text-base text-gray-600">
<span className="font-bold"></span> Webserverversion: 1.0.6.0
</p>
</div>
</div>
{renderBaugruppentraeger()}
</div>
</div>
<div className="flex-shrink-0 flex justify-between items-center mt-1 bg-white p-2 rounded-lg shadow-md border border-gray-200 laptop:m-0 laptop:scale-y-75">
<div className="flex items-center space-x-4">
<img src="/images/IP-icon.svg" alt="IP Address" className="w-6 " />
<div>
<p className="text-xs text-gray-500">IP-Adresse</p>
<p className="text-sm font-medium text-gray-700">{ip}</p>
</div>
</div>
<div className="flex items-center space-x-4">
<img
src="/images/subnet-mask.svg"
alt="subnet mask"
className="w-6 "
/>
<div>
<p className="text-xs text-gray-500">Subnet-Maske</p>
<p className="text-sm font-medium text-gray-700">{subnet}</p>
</div>
</div>
<div className="flex items-center space-x-4">
<img src="/images/gateway.svg" alt="gateway" className="w-6 " />
<div>
<p className="text-xs text-gray-500">Gateway</p>
<p className="text-sm font-medium text-gray-700">{gateway}</p>
</div>
</div>
<div className="flex items-center space-x-4">
<img src="/images/IP-icon.svg" alt="IP Address" className="w-6 " />
<div>
<p className="text-xs text-gray-500">OPCUA Status</p>
<p className="text-sm font-medium text-gray-700">{ip}</p>
</div>
</div>
</div>
</div>
);
}
export default Dashboard;