diff --git a/index.html b/index.html
index 93d32c5..f27d0e4 100644
--- a/index.html
+++ b/index.html
@@ -2,6 +2,7 @@
+
Dashfront
diff --git a/package-lock.json b/package-lock.json
index 4838b4e..331ee24 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,7 +14,8 @@
"@mui/material": "^9.1.2",
"notistack": "^3.0.2",
"react": "^19.2.7",
- "react-dom": "^19.2.7"
+ "react-dom": "^19.2.7",
+ "react-router-dom": "^7.18.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^6.0.2",
@@ -1036,6 +1037,19 @@
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
"license": "MIT"
},
+ "node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
"node_modules/cosmiconfig": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
@@ -1772,6 +1786,44 @@
"integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==",
"license": "MIT"
},
+ "node_modules/react-router": {
+ "version": "7.18.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.0.tgz",
+ "integrity": "sha512-pTTGt8J+ji1NOmYnjzT+bAJy/1zD+Jp4ziO6cL7T3ZLvXKtusO7BpFqlRXitqpcPVqllsIXFHRMt+2/k3Xn6HQ==",
+ "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.18.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.0.tgz",
+ "integrity": "sha512-Fi0yY6kgtKae/Th2xibdWK0KSdYZ4B53Gyf6wRtomOKWgpNm7H7+DyfDhncdz9FKbpS+1jmDhg3F4WoGJ+yFOA==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.18.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@@ -1858,6 +1910,12 @@
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
"license": "MIT"
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
+ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
+ "license": "MIT"
+ },
"node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
diff --git a/package.json b/package.json
index c1e722a..251e10e 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,8 @@
"@mui/material": "^9.1.2",
"notistack": "^3.0.2",
"react": "^19.2.7",
- "react-dom": "^19.2.7"
+ "react-dom": "^19.2.7",
+ "react-router-dom": "^7.18.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^6.0.2",
diff --git a/public/favicon.svg b/public/favicon.svg
new file mode 100644
index 0000000..d713658
--- /dev/null
+++ b/public/favicon.svg
@@ -0,0 +1,12 @@
+
diff --git a/src/App.jsx b/src/App.jsx
index 56da491..cd85405 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,10 +1,12 @@
import Box from '@mui/material/Box';
import CircularProgress from '@mui/material/CircularProgress';
+import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
import { useAuth } from './auth/useAuth';
import LoginPage from './components/LoginPage';
import AppShell from './components/AppShell';
+import SectionPage from './pages/SectionPage';
+import { NAV_ITEMS } from './nav';
-// Top-level router by auth status. Kept tiny so it rarely re-renders.
export default function App() {
const { status } = useAuth();
@@ -23,5 +25,28 @@ export default function App() {
);
}
- return status === 'authed' ? : ;
+ if (status !== 'authed') {
+ return ;
+ }
+
+ return (
+
+
+ }>
+ {NAV_ITEMS.map(({ path, label }) =>
+ path === '/' ? (
+ } />
+ ) : (
+ }
+ />
+ ),
+ )}
+ } />
+
+
+
+ );
}
diff --git a/src/components/AppShell.jsx b/src/components/AppShell.jsx
index 9376bb1..85635b7 100644
--- a/src/components/AppShell.jsx
+++ b/src/components/AppShell.jsx
@@ -1,21 +1,15 @@
-import { useState } from 'react';
import Box from '@mui/material/Box';
import List from '@mui/material/List';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
+import { NavLink, Outlet } from 'react-router-dom';
import UserMenu from './UserMenu';
import { NAV_ITEMS } from '../nav';
const SIDEBAR_WIDTH = 240;
-// App layout. State lives in the children (UserMenu, page content) so the
-// shell itself does not re-render when their state changes.
export default function AppShell() {
- const [activeId, setActiveId] = useState(NAV_ITEMS[0].id);
- const activeItem = NAV_ITEMS.find((item) => item.id === activeId) ?? NAV_ITEMS[0];
- const ActivePage = activeItem.Page;
-
return (
- {NAV_ITEMS.map(({ id, label, icon: Icon }) => (
+ {NAV_ITEMS.map(({ path, label, icon: Icon }) => (
setActiveId(id)}
- sx={{ borderRadius: 0, px: 2 }}
+ key={path}
+ component={NavLink}
+ to={path}
+ end={path === '/'}
+ sx={{
+ borderRadius: 0,
+ px: 2,
+ '&.active': { bgcolor: 'action.selected' },
+ }}
>
@@ -49,7 +47,7 @@ export default function AppShell() {
-
+
);
diff --git a/src/components/PageLayout.jsx b/src/components/PageLayout.jsx
new file mode 100644
index 0000000..2fd8f70
--- /dev/null
+++ b/src/components/PageLayout.jsx
@@ -0,0 +1,13 @@
+import Box from '@mui/material/Box';
+import Typography from '@mui/material/Typography';
+
+export default function PageLayout({ title, children }) {
+ return (
+
+
+ {title}
+
+ {children}
+
+ );
+}
diff --git a/src/nav.js b/src/nav.js
index 158494b..b5d8495 100644
--- a/src/nav.js
+++ b/src/nav.js
@@ -1,11 +1,15 @@
-import DashboardIcon from '@mui/icons-material/Dashboard';
-import DashboardPage from './pages/DashboardPage';
+import HomeIcon from '@mui/icons-material/Home';
+import Inventory2Icon from '@mui/icons-material/Inventory2';
+import LocalShippingIcon from '@mui/icons-material/LocalShipping';
+import AssignmentIcon from '@mui/icons-material/Assignment';
+import PeopleIcon from '@mui/icons-material/People';
+import InfoIcon from '@mui/icons-material/Info';
export const NAV_ITEMS = [
- {
- id: 'dashboard',
- label: 'Dashboard',
- icon: DashboardIcon,
- Page: DashboardPage,
- },
+ { path: '/', label: 'Home', icon: HomeIcon },
+ { path: '/artikel', label: 'Artikel', icon: Inventory2Icon },
+ { path: '/lieferung', label: 'Lieferung', icon: LocalShippingIcon },
+ { path: '/auftrag', label: 'Auftrag', icon: AssignmentIcon },
+ { path: '/kunde', label: 'Kunde', icon: PeopleIcon },
+ { path: '/infos', label: 'Infos', icon: InfoIcon },
];
diff --git a/src/pages/DashboardPage.jsx b/src/pages/DashboardPage.jsx
deleted file mode 100644
index 09dc9a3..0000000
--- a/src/pages/DashboardPage.jsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import Typography from '@mui/material/Typography';
-
-export default function DashboardPage() {
- return (
-
- Dashboard
-
- );
-}
diff --git a/src/pages/SectionPage.jsx b/src/pages/SectionPage.jsx
new file mode 100644
index 0000000..448f217
--- /dev/null
+++ b/src/pages/SectionPage.jsx
@@ -0,0 +1,10 @@
+import Typography from '@mui/material/Typography';
+import PageLayout from '../components/PageLayout';
+
+export default function SectionPage({ title }) {
+ return (
+
+ Inhalt folgt.
+
+ );
+}