diff --git a/.gitignore b/.gitignore index 9bfad9c..22e6c72 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ dashboard/pages/test.py dashboard/sidebar_test.py dashboard/assets/responsive-sidebar.css certs/ +sync.ffs_db diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json index 96a63f0..ec436ac 100644 --- a/dashboard/package-lock.json +++ b/dashboard/package-lock.json @@ -13,8 +13,10 @@ "@syncfusion/ej2-react-grids": "^29.2.11", "@syncfusion/ej2-react-schedule": "^29.2.10", "cldr-data": "^36.0.4", + "lucide-react": "^0.522.0", "react": "^19.1.0", - "react-dom": "^19.1.0" + "react-dom": "^19.1.0", + "react-router-dom": "^7.6.2" }, "devDependencies": { "@eslint/js": "^9.25.0", @@ -23,6 +25,7 @@ "@tailwindcss/typography": "^0.5.16", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", + "@types/react-router-dom": "^5.3.3", "@typescript-eslint/eslint-plugin": "^8.34.1", "@typescript-eslint/parser": "^8.34.1", "@vitejs/plugin-react": "^4.4.1", @@ -1985,6 +1988,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -2012,6 +2022,29 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.34.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.1.tgz", @@ -3038,6 +3071,15 @@ "dev": true, "license": "MIT" }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/cosmiconfig": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", @@ -5357,6 +5399,15 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "0.522.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.522.0.tgz", + "integrity": "sha512-jnJbw974yZ7rQHHEFKJOlWAefG3ATSCZHANZxIdx8Rk/16siuwjgA4fBULpXEAWx/RlTs3FzmKW/udWUuO0aRw==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -6267,6 +6318,44 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.2.tgz", + "integrity": "sha512-U7Nv3y+bMimgWjhlT5CRdzHPu2/KVmqPwKUCChW8en5P3znxUqwlYFlbmyj8Rgp1SF6zs5X4+77kBVknkg6a0w==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.2.tgz", + "integrity": "sha512-Q8zb6VlTbdYKK5JJBLQEN06oTUa/RAbG/oQS1auK1I0TbJOXktqm+QENEVJU6QvWynlXPRBXI3fiOQcSEA78rA==", + "license": "MIT", + "dependencies": { + "react-router": "7.6.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -6521,6 +6610,12 @@ "node": ">=10" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", diff --git a/dashboard/package.json b/dashboard/package.json index 1ba0b0e..1a589cd 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -15,8 +15,10 @@ "@syncfusion/ej2-react-grids": "^29.2.11", "@syncfusion/ej2-react-schedule": "^29.2.10", "cldr-data": "^36.0.4", + "lucide-react": "^0.522.0", "react": "^19.1.0", - "react-dom": "^19.1.0" + "react-dom": "^19.1.0", + "react-router-dom": "^7.6.2" }, "devDependencies": { "@eslint/js": "^9.25.0", @@ -25,6 +27,7 @@ "@tailwindcss/typography": "^0.5.16", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", + "@types/react-router-dom": "^5.3.3", "@typescript-eslint/eslint-plugin": "^8.34.1", "@typescript-eslint/parser": "^8.34.1", "@vitejs/plugin-react": "^4.4.1", diff --git a/dashboard/src/App.tsx b/dashboard/src/App.tsx index fa2f587..d03e342 100644 --- a/dashboard/src/App.tsx +++ b/dashboard/src/App.tsx @@ -1,113 +1,156 @@ -// import 'react-app-polyfill/ie11'; // optional, falls benötigt +import React, { useState } from 'react'; +import { BrowserRouter as Router, Routes, Route, Link, Outlet } from 'react-router-dom'; +import logo from './assets/logo.png'; import './App.css'; -import React from 'react'; + +// Lucide Icons importieren import { - ScheduleComponent, - Day, - Week, - WorkWeek, - Month, - Agenda, - TimelineViews, - TimelineMonth, - Inject, - ViewsDirective, - ViewDirective, - ResourcesDirective, - ResourceDirective, -} from '@syncfusion/ej2-react-schedule'; -import { L10n, loadCldr, setCulture } from '@syncfusion/ej2-base'; -import * as de from 'cldr-data/main/de/ca-gregorian.json'; -import * as numbers from 'cldr-data/main/de/numbers.json'; -import * as timeZoneNames from 'cldr-data/main/de/timeZoneNames.json'; -import * as numberingSystems from 'cldr-data/supplemental/numberingSystems.json'; + LayoutDashboard, + Calendar, + Boxes, + Users, + UserSquare, + Image, + User, + Settings, +} from 'lucide-react'; -// CLDR-Daten laden -loadCldr( - (de as unknown as { default: object }).default, - (numbers as unknown as { default: object }).default, - (timeZoneNames as unknown as { default: object }).default, - (numberingSystems as unknown as { default: object }).default -); - -// Deutsche Lokalisierung für den Scheduler -L10n.load({ - de: { - schedule: { - day: 'Tag', - week: 'Woche', - workWeek: 'Arbeitswoche', - month: 'Monat', - agenda: 'Agenda', - today: 'Heute', - noEvents: 'Keine Termine', - }, - }, -}); - -// Kultur setzen -setCulture('de'); - -// Ressourcen-Daten -const resources = [ - { text: 'Raum A', id: 1, color: '#1aaa55' }, - { text: 'Raum B', id: 2, color: '#357cd2' }, - { text: 'Raum C', id: 3, color: '#7fa900' }, +const sidebarItems = [ + { name: 'Dashboard', path: '/', icon: LayoutDashboard }, + { name: 'Termine', path: '/termine', icon: Calendar }, + { name: 'Ressourcen', path: '/ressourcen', icon: Boxes }, + { name: 'Infoscreens', path: '/Infoscreens', icon: Users }, + { name: 'Gruppen', path: '/gruppen', icon: UserSquare }, + { name: 'Medien', path: '/medien', icon: Image }, + { name: 'Benutzer', path: '/benutzer', icon: User }, + { name: 'Einstellungen', path: '/einstellungen', icon: Settings }, ]; -// Dummy-Termine generieren -const now = new Date(); -const appointments = Array.from({ length: 10 }).map((_, i) => { - const dayOffset = Math.floor(i * 1.4); // verteilt auf 14 Tage - const start = new Date(now); - start.setDate(now.getDate() + dayOffset); - start.setHours(9 + (i % 4), 0, 0, 0); - const end = new Date(start); - end.setHours(start.getHours() + 1); +const Layout: React.FC = () => { + const [collapsed, setCollapsed] = useState(false); - return { - Id: i + 1, - Subject: `Termin ${i + 1}`, - StartTime: start, - EndTime: end, - ResourceId: (i % 3) + 1, - Location: resources[i % 3].text, - }; -}); - -const App: React.FC = () => { return ( -
Willkommen im Infoscreen-Management Benutzer.
+Willkommen im Infoscreen-Management Infoscreens.
+Willkommen im Infoscreen-Management Dashboard.
+Willkommen im Infoscreen-Management Einstellungen.
+Willkommen im Infoscreen-Management Gruppen.
+Willkommen im Infoscreen-Management Medien.
+Willkommen im Infoscreen-Management Ressourcen.
+