From c9e55dd66cc2ee26021037a98f5370bfdb4c3b36 Mon Sep 17 00:00:00 2001 From: ISA Date: Mon, 23 Sep 2024 10:32:17 +0200 Subject: [PATCH] =?UTF-8?q?Next.js=20mit=20App=20-Router=20f=C3=BCr=20expo?= =?UTF-8?q?rt=20zu=20statische=20dateien?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/access/page.jsx | 136 ++++++++++++++++++++ app/analogeEingaenge/page.jsx | 224 +++++++++++++++++++++++++++++++++ app/dashboard/page.jsx | 24 ++++ app/einausgaenge/page.jsx | 166 ++++++++++++++++++++++++ app/kabelueberwachung/page.jsx | 98 +++++++++++++++ app/layout.js | 43 +++---- app/meldungen/page.jsx | 138 ++++++++++++++++++++ components/Footer.jsx | 21 ++++ components/Header.jsx | 63 ++++++++++ components/Layout.jsx | 21 ++++ components/Navigation.jsx | 46 +++++++ next.config.mjs | 8 +- public/images/Logo.png | Bin 0 -> 6598 bytes 13 files changed, 961 insertions(+), 27 deletions(-) create mode 100644 app/access/page.jsx create mode 100644 app/analogeEingaenge/page.jsx create mode 100644 app/dashboard/page.jsx create mode 100644 app/einausgaenge/page.jsx create mode 100644 app/kabelueberwachung/page.jsx create mode 100644 app/meldungen/page.jsx create mode 100644 components/Footer.jsx create mode 100644 components/Header.jsx create mode 100644 components/Layout.jsx create mode 100644 components/Navigation.jsx create mode 100644 public/images/Logo.png diff --git a/app/access/page.jsx b/app/access/page.jsx new file mode 100644 index 0000000..d7c1b25 --- /dev/null +++ b/app/access/page.jsx @@ -0,0 +1,136 @@ +// pages/Zutrittskontrolle.jsx +import React from "react"; +import Layout from "../components/Layout"; + +function Access() { + return ( + +
+
+

+ Zutrittskontrolle 1 +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ Betrieb + Status: ...
+ Status + ...
Letzte Chip-ID...
Zeitstempel...
Access Typ...
+
+
+ + + + + + + + + + + + + + + + + + + + +
EingangZustandBezeichnung
1......
2......
+
+
+
+ + {/* Zutrittskontrolle 2 */} +
+

+ Zutrittskontrolle 2 +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ Betrieb + Status: ...
+ Status + ...
Letzte Chip-ID...
Zeitstempel...
Access Typ...
+
+
+ + + + + + + + + + + + + + + + + + + + +
EingangZustandBezeichnung
1......
2......
+
+
+
+
+
+ ); +} + +export default Access; diff --git a/app/analogeEingaenge/page.jsx b/app/analogeEingaenge/page.jsx new file mode 100644 index 0000000..2977ef9 --- /dev/null +++ b/app/analogeEingaenge/page.jsx @@ -0,0 +1,224 @@ +import React, { useState } from "react"; +import Layout from "../components/Layout"; + +function AnalogeEingaenge() { + const [activeConfig, setActiveConfig] = useState(null); + + // Beispiel-Daten, du kannst die Daten dynamisch laden + const inputs = [ + { + id: 1, + value: 0, + name: "------------------", + uG: true, + uW: true, + oW: true, + oG: true, + }, + { + id: 2, + value: 0, + name: "------------------", + uG: true, + uW: true, + oW: true, + oG: true, + }, + { + id: 3, + value: 0, + name: "------------------", + uG: true, + uW: true, + oW: true, + oG: true, + }, + { + id: 4, + value: 0, + name: "------------------", + uG: true, + uW: true, + oW: true, + oG: true, + }, + { + id: 5, + value: 0, + name: "------------------", + uG: true, + uW: true, + oW: true, + oG: true, + }, + { + id: 6, + value: 0, + name: "------------------", + uG: true, + uW: true, + oW: true, + oG: true, + }, + { + id: 7, + value: 0, + name: "------------------", + uG: true, + uW: true, + oW: true, + oG: true, + }, + { + id: 8, + value: 0, + name: "------------------", + uG: true, + uW: true, + oW: true, + oG: true, + }, + ]; + + return ( + +
+

Analoge Eingänge

+
+ {inputs.map((input) => ( +
+
+

XIO-PM {input.id}

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
EingangWertBezeichnunguGuWoWoGKonfig
{input.id}{input.value}{input.name} + + + + + + + + + +
+
+
+ ))} +
+ + {/* Modal für Konfiguration */} + {activeConfig && ( +
+
+

+ Konfiguration - XIO-PM {activeConfig} +

+ + {/* Konfigurationsformular hier einfügen */} +
+
+ + +
+
+ + +
+ {/* Weitere Felder hier hinzufügen */} + +
+
+
+ )} +
+
+ ); +} + +export default AnalogeEingaenge; diff --git a/app/dashboard/page.jsx b/app/dashboard/page.jsx new file mode 100644 index 0000000..8a5ac1c --- /dev/null +++ b/app/dashboard/page.jsx @@ -0,0 +1,24 @@ +import React, { useEffect } from "react"; +import Layout from "../components/Layout"; +import Image from "next/image"; +import "tailwindcss/tailwind.css"; // Stelle sicher, dass Tailwind CSS korrekt importiert wird +import "@fontsource/roboto"; // Standardimport für alle Schriftstärken +import "bootstrap-icons/font/bootstrap-icons.css"; + +function Dashboard() { + return ( + +
+
+ {/* Main Section */} +
+ {/* Hauptinhalt */} +

Dashboard Übersicht

+
+
+
+
+ ); +} + +export default Dashboard; diff --git a/app/einausgaenge/page.jsx b/app/einausgaenge/page.jsx new file mode 100644 index 0000000..8d1a72e --- /dev/null +++ b/app/einausgaenge/page.jsx @@ -0,0 +1,166 @@ +// pages/Einausgaenge.jsx +import React, { useState } from "react"; +import Layout from "../components/Layout"; + +function Einausgaenge() { + // Beispiel-Daten für Ein- und Ausgänge (kannst du durch deine Daten ersetzen) + const inputs = [ + { + id: 1, + name: "Eingang 1", + status: "Aktiv", + description: "Beschreibung 1", + }, + { + id: 2, + name: "Eingang 2", + status: "Inaktiv", + description: "Beschreibung 2", + }, + { + id: 3, + name: "Eingang 3", + status: "Aktiv", + description: "Beschreibung 3", + }, + { + id: 4, + name: "Eingang 4", + status: "Inaktiv", + description: "Beschreibung 4", + }, + ]; + + const outputs = [ + { + id: 1, + name: "Ausgang 1", + status: "Aktiv", + description: "Beschreibung 1", + }, + { + id: 2, + name: "Ausgang 2", + status: "Inaktiv", + description: "Beschreibung 2", + }, + { + id: 3, + name: "Ausgang 3", + status: "Aktiv", + description: "Beschreibung 3", + }, + { + id: 4, + name: "Ausgang 4", + status: "Inaktiv", + description: "Beschreibung 4", + }, + ]; + + // Zustand für aktiven Tab (Ein- oder Ausgänge) + const [activeTab, setActiveTab] = useState("inputs"); + + return ( + +
+ {/* Tabs für Ein- und Ausgänge */} +
    +
  • + +
  • +
  • + +
  • +
+ + {/* Inhalt für die aktiven Tabs */} +
+ {activeTab === "inputs" && ( +
+

Eingänge

+ + + + + + + + + + + {inputs.map((input) => ( + + + + + + + ))} + +
IDNameStatusBeschreibung
{input.id}{input.name}{input.status} + {input.description} +
+
+ )} + + {activeTab === "outputs" && ( +
+

Ausgänge

+ + + + + + + + + + + {outputs.map((output) => ( + + + + + + + ))} + +
IDNameStatusBeschreibung
{output.id}{output.name}{output.status} + {output.description} +
+
+ )} +
+
+
+ ); +} + +export default Einausgaenge; diff --git a/app/kabelueberwachung/page.jsx b/app/kabelueberwachung/page.jsx new file mode 100644 index 0000000..620c27a --- /dev/null +++ b/app/kabelueberwachung/page.jsx @@ -0,0 +1,98 @@ +import React, { useState } from "react"; +import Layout from "../components/Layout"; + +function Kabelueberwachung() { + const [activeTab, setActiveTab] = useState(1); + + const racks = [ + { id: 1, name: "Rack 1" }, + { id: 2, name: "Rack 2" }, + { id: 3, name: "Rack 3" }, + { id: 4, name: "Rack 4" }, + ]; + + return ( + +
+ {" "} + {/* overflow-hidden hinzugefügt */} + {/* Tabs */} +
    + {racks.map((rack) => ( +
  • + +
  • + ))} +
+ {/* Rack-Inhalte */} +
+ {" "} + {/* max-h-full und overflow-auto für Inhalt */} + {racks.map( + (rack) => + activeTab === rack.id && ( +
+

+ {rack.name} Inhalte +

+ {/* Hier kannst du den Inhalt für jedes Rack einfügen */} + + + + + + + + + + + + + {Array.from({ length: 8 }, (_, index) => ( + + + + + + + + + ))} + +
SlotBezeichnung + Isolationsgrenzwert + + Schleifengrenzwert + FilterzeitAktionen
+ Slot {index + 1} + + Beispielbezeichnung + 0.5 MOhm10 kOhm5 sek. + +
+
+ ) + )} +
+
+
+ ); +} + +export default Kabelueberwachung; diff --git a/app/layout.js b/app/layout.js index 9800bf8..84087ad 100644 --- a/app/layout.js +++ b/app/layout.js @@ -1,30 +1,21 @@ -import localFont from "next/font/local"; -import "./globals.css"; +// src/components/Layout.jsx +import React from "react"; +import Header from "../components/Header"; // Passe den Pfad an, falls nötig +import Navigation from "../components/Navigation"; // Passe den Pfad an, falls nötig +import Footer from "../components/Footer"; // Passe den Pfad an, falls nötig -const geistSans = localFont({ - src: "./fonts/GeistVF.woff", - variable: "--font-geist-sans", - weight: "100 900", -}); -const geistMono = localFont({ - src: "./fonts/GeistMonoVF.woff", - variable: "--font-geist-mono", - weight: "100 900", -}); - -export const metadata = { - title: "Create Next App", - description: "Generated by create next app", -}; - -export default function RootLayout({ children }) { +function Layout({ children }) { return ( - - - {children} - - +
+
+
+ + {/* Der eigentliche Seiteninhalt */} +
{children}
+
+
+
); } + +export default Layout; diff --git a/app/meldungen/page.jsx b/app/meldungen/page.jsx new file mode 100644 index 0000000..bfd9aae --- /dev/null +++ b/app/meldungen/page.jsx @@ -0,0 +1,138 @@ +// pages/Meldungen.jsx +import React, { useState } from "react"; +import Layout from "../components/Layout"; + +function Meldungen() { + const [rowsPerPage, setRowsPerPage] = useState(25); + const [filter, setFilter] = useState(""); + const [selectedMonth, setSelectedMonth] = useState("01"); + const [selectedYear, setSelectedYear] = useState("23"); + const [selectedDay, setSelectedDay] = useState(""); + + // Platzhalter für Meldungen + const messages = Array.from({ length: 50 }, (_, i) => ({ + date: `2023-01-${String(i + 1).padStart(2, "0")}`, + message: `Meldung ${i + 1}`, + })); + + const filteredMessages = messages.filter((msg) => { + const dayMatch = selectedDay + ? msg.date.split("-")[2] === selectedDay.padStart(2, "0") + : true; + const monthMatch = msg.date.split("-")[1] === selectedMonth; + const yearMatch = msg.date.split("-")[0].substring(2) === selectedYear; + const filterMatch = msg.message + .toLowerCase() + .includes(filter.toLowerCase()); + return dayMatch && monthMatch && yearMatch && filterMatch; + }); + + return ( + +
+ {/* Filterleiste */} +
+
+ Interner Meldungsspeicher + + + setSelectedDay(e.target.value)} + min="1" + max="31" + placeholder="Tag" + className="bg-white text-black p-1 rounded" + /> +
+
+ setFilter(e.target.value)} + placeholder="Filter" + className="bg-white text-black p-1 rounded" + /> + +
+
+ + {/* Meldungen Tabelle */} +
+ + + + + + + + + {filteredMessages.slice(0, rowsPerPage).map((msg, index) => ( + + + + + ))} + +
DatumMeldung
{msg.date}{msg.message}
+
+ + {/* Pagination */} +
+
    + {Array.from( + { length: Math.ceil(filteredMessages.length / rowsPerPage) }, + (_, i) => ( +
  • + {i + 1} +
  • + ) + )} +
+
+
+
+ ); +} + +export default Meldungen; diff --git a/components/Footer.jsx b/components/Footer.jsx new file mode 100644 index 0000000..e14f6be --- /dev/null +++ b/components/Footer.jsx @@ -0,0 +1,21 @@ +// src/components/Footer.jsx +import React from 'react'; + +function Footer() { + return ( + + ); +} + +export default Footer; diff --git a/components/Header.jsx b/components/Header.jsx new file mode 100644 index 0000000..382c59f --- /dev/null +++ b/components/Header.jsx @@ -0,0 +1,63 @@ +// src/components/Header.jsx +import React from "react"; +import Image from "next/image"; + +function Header() { + return ( +
+
+ Logo +
+ + {/* CPL Status und Stationsname */} +
+
+

Stationsname

+

CPLV4Rastede

+
+
+

CPL Status

+ normiert +
+
+ + {/* Temperatur und Icons */} +
+ {/* Temperatur und Luftfeuchtigkeit */} +
+
+ +

20.5 °C

+
+
+ +

60%

+
+
+ + {/* Toggle Switch light and dark mode */} +
+ +
+ + +
+
+ + {/* User Icon */} +
+ +
+
+
+ ); +} + +export default Header; diff --git a/components/Layout.jsx b/components/Layout.jsx new file mode 100644 index 0000000..420e34b --- /dev/null +++ b/components/Layout.jsx @@ -0,0 +1,21 @@ +// src/components/Layout.jsx +import React from "react"; +import Header from "./Header"; // Passe den Pfad an, falls nötig +import Navigation from "./Navigation"; // Passe den Pfad an, falls nötig +import Footer from "./Footer"; // Passe den Pfad an, falls nötig + +function Layout({ children }) { + return ( +
+
+
+ + {/* Der eigentliche Seiteninhalt */} +
{children}
+
+
+
+ ); +} + +export default Layout; diff --git a/components/Navigation.jsx b/components/Navigation.jsx new file mode 100644 index 0000000..6e5f0c8 --- /dev/null +++ b/components/Navigation.jsx @@ -0,0 +1,46 @@ +// src/components/Navigation.jsx +import React, { useEffect, useState } from "react"; +import Link from "next/link"; // Importiere Link von Next.js +import { useRouter } from "next/router"; + +function Navigation() { + const router = useRouter(); + const [activeLink, setActiveLink] = useState(router.pathname); // Verwende den aktuellen Pfad als initialen Wert + + useEffect(() => { + // Wenn sich die Route ändert, wird der activeLink-Zustand aktualisiert + setActiveLink(router.pathname); + }, [router.pathname]); + + const menuItems = [ + { name: "Übersicht", path: "/" }, + { name: "Kabelüberwachung", path: "/Kabelueberwachung" }, + { name: "Zutrittskontrolle", path: "/Access" }, // Pfad angepasst + { name: "Ein- und Ausgänge", path: "/Einausgaenge" }, + { name: "Analoge Eingänge", path: "/AnalogeEingaenge" }, + { name: "Meldungen", path: "/Meldungen" }, + ]; + + return ( + + ); +} + +export default Navigation; diff --git a/next.config.mjs b/next.config.mjs index 4678774..0448bad 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,10 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + reactStrictMode: true, + output: "export", // Stellt den statischen Export sicher + images: { + unoptimized: true, // Deaktiviert Bildoptimierung für den Export + }, +}; export default nextConfig; diff --git a/public/images/Logo.png b/public/images/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8c8b2f0decd405d59cef42388be0a1dc1b44370f GIT binary patch literal 6598 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