Compare commits

...

1 Commits

Author SHA1 Message Date
e560248
cd4f632c85 add Page Router & improve styling 2025-04-07 17:01:44 +02:00
17 changed files with 214 additions and 23 deletions

View File

@@ -9,7 +9,8 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0" "react-dom": "^19.0.0",
"react-router-dom": "^7.5.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.21.0", "@eslint/js": "^9.21.0",
@@ -1393,6 +1394,12 @@
"@babel/types": "^7.20.7" "@babel/types": "^7.20.7"
} }
}, },
"node_modules/@types/cookie": {
"version": "0.6.0",
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@types/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
"license": "MIT"
},
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@types/estree/-/estree-1.0.7.tgz", "resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@types/estree/-/estree-1.0.7.tgz",
@@ -2035,6 +2042,15 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/cookie": {
"version": "1.0.2",
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/cookie/-/cookie-1.0.2.tgz",
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.6", "version": "7.0.6",
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/cross-spawn/-/cross-spawn-7.0.6.tgz", "resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -3077,6 +3093,46 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-router": {
"version": "7.5.0",
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/react-router/-/react-router-7.5.0.tgz",
"integrity": "sha512-estOHrRlDMKdlQa6Mj32gIks4J+AxNsYoE0DbTTxiMy2mPzZuWSDU+N85/r1IlNR7kGfznF3VCUlvc5IUO+B9g==",
"license": "MIT",
"dependencies": {
"@types/cookie": "^0.6.0",
"cookie": "^1.0.1",
"set-cookie-parser": "^2.6.0",
"turbo-stream": "2.4.0"
},
"engines": {
"node": ">=20.0.0"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
}
}
},
"node_modules/react-router-dom": {
"version": "7.5.0",
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/react-router-dom/-/react-router-dom-7.5.0.tgz",
"integrity": "sha512-fFhGFCULy4vIseTtH5PNcY/VvDJK5gvOWcwJVHQp8JQcWVr85ENhJ3UpuF/zP1tQOIFYNRJHzXtyhU1Bdgw0RA==",
"license": "MIT",
"dependencies": {
"react-router": "7.5.0"
},
"engines": {
"node": ">=20.0.0"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
}
},
"node_modules/resolve-from": { "node_modules/resolve-from": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/resolve-from/-/resolve-from-4.0.0.tgz", "resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -3178,6 +3234,12 @@
"semver": "bin/semver.js" "semver": "bin/semver.js"
} }
}, },
"node_modules/set-cookie-parser": {
"version": "2.7.1",
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"license": "MIT"
},
"node_modules/shebang-command": { "node_modules/shebang-command": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -3328,6 +3390,12 @@
"typescript": ">=4.8.4" "typescript": ">=4.8.4"
} }
}, },
"node_modules/turbo-stream": {
"version": "2.4.0",
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/turbo-stream/-/turbo-stream-2.4.0.tgz",
"integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
"license": "ISC"
},
"node_modules/type-check": { "node_modules/type-check": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/type-check/-/type-check-0.4.0.tgz", "resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/type-check/-/type-check-0.4.0.tgz",

View File

@@ -11,7 +11,8 @@
}, },
"dependencies": { "dependencies": {
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0" "react-dom": "^19.0.0",
"react-router-dom": "^7.5.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.21.0", "@eslint/js": "^9.21.0",

View File

@@ -1,9 +1,4 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.logo { .logo {
height: 6em; height: 6em;

View File

@@ -1,17 +1,23 @@
import { Route, Routes } from 'react-router-dom'
import './App.css' import './App.css'
// import EffectExercises from './components/exercises/EffectExercises' // import EffectExercises from './components/exercises/EffectExercises'
import UserEffect from './components/exercises/UserEffect'
import { UserOverview } from './components/exercises/UserOverview'
import Heading from './components/globals/Heading'
import MainLayout from './layouts/MainLayout' import MainLayout from './layouts/MainLayout'
import HomePage from './routes/HomePage'
import UsersPage from './routes/UsersPage'
import EffectExercisesPage from './routes/EffectExercisesPage'
import FormsPage from './routes/FormsPage'
import MemoCallbackPage from './routes/MemoCallbackPage'
function App() { function App() {
return <MainLayout> return <MainLayout>
<Heading /> <Routes>
{/* <EffectExercises /> */} <Route path="/" element={<HomePage />} />
<UserEffect /> <Route path="/user" element={<UsersPage />} />
<UserOverview /> <Route path="/effect" element={<EffectExercisesPage />} />
<Route path="/forms" element={<FormsPage />} />
<Route path="/memocallback" element={<MemoCallbackPage />} />
</Routes>
</MainLayout> </MainLayout>
} }

View File

@@ -2,8 +2,11 @@ export default function Navigation () {
return ( return (
<nav> <nav>
<ul> <ul>
<li>home</li> <li><a href="/">Home</a></li>
<li>test</li> <li><a href="/user">Users</a></li>
<li><a href="/effect">Effects</a></li>
<li><a href="/forms">Forms</a></li>
<li><a href="/memocallback">Memo und Callback</a></li>
</ul> </ul>
</nav>); </nav>);
} }

View File

@@ -4,7 +4,7 @@ const Header = () => {
console.log("Header rendered"); console.log("Header rendered");
return ( return (
<header> <header>
<h2>My Application</h2> <h1>My Application</h1>
<Navigation /> <Navigation />
</header> </header>
); );

View File

@@ -23,7 +23,6 @@ export default function MemoCallback() {
}); });
return ( return (
<div> <div>
<h1>Memo Callback Übung</h1>
<button onClick={handleShuffle}>Shuffle</button> <button onClick={handleShuffle}>Shuffle</button>
<Search onChange={handleSearch} /> <Search onChange={handleSearch} />
<div> <div>

View File

@@ -1,8 +1,8 @@
export default function Heading({title = "Hallo Teilnehmer"}: {title?: string}): React.ReactElement { export default function Heading({title = "Hallo Teilnehmer"}: {title?: string}): React.ReactElement {
console.log("Heading rendered"); console.log("Heading rendered");
return ( return (
<h1 > <h2 >
{title} {title}
</h1> </h2>
); );
} }

View File

@@ -25,7 +25,6 @@ a:hover {
body { body {
margin: 0; margin: 0;
display: flex; display: flex;
place-items: center;
min-width: 320px; min-width: 320px;
min-height: 100vh; min-height: 100vh;
} }

View File

@@ -0,0 +1,56 @@
#root {
width: 100%;
}
header {
background-color: #1a1a1a;
color: #ffffff;
padding: 1rem;
text-align: center;
}
header nav {
display: flex;
justify-content: center;
gap: 2rem;
}
header nav ul {
list-style: none;
padding: 0;
}
header nav li {
display: inline;
}
header nav a {
color: #ffffff;
text-decoration: none;
font-weight: bold;
padding: 0.5rem 1rem;
transition: background-color 0.3s, color 0.3s;
}
header nav a:hover {
text-decoration: underline;
}
header nav a.active {
text-decoration: underline;
}
footer {
background-color: #1a1a1a;
color: #ffffff;
padding: 1rem;
text-align: center;
}
.content {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

View File

@@ -1,6 +1,7 @@
import { useState } from "react"; import { useState } from "react";
import Footer from "../components/Footer"; import Footer from "../components/Footer";
import Header from "../components/Header"; import Header from "../components/Header";
import './MainLayout.css'
export default function MainLayout({children}: {children: React.ReactNode | React.ReactElement | React.ReactElement[]}): React.ReactElement { export default function MainLayout({children}: {children: React.ReactNode | React.ReactElement | React.ReactElement[]}): React.ReactElement {
@@ -17,9 +18,13 @@ export default function MainLayout({children}: {children: React.ReactNode | Reac
return ( return (
<> <>
<Header /> <Header />
<div className="content">
{children} {children}
<button onClick={handleClick}>Click</button> <button onClick={handleClick}>Click</button>
</div>
<Footer /> <Footer />
</> </>
); );

View File

@@ -2,9 +2,12 @@ import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client' import { createRoot } from 'react-dom/client'
import './index.css' import './index.css'
import App from './App.tsx' import App from './App.tsx'
import { BrowserRouter } from 'react-router-dom'
createRoot(document.getElementById('root')!).render( createRoot(document.getElementById('root')!).render(
<StrictMode> <StrictMode>
<BrowserRouter>
<App /> <App />
</BrowserRouter>
</StrictMode>, </StrictMode>,
) )

View File

@@ -0,0 +1,11 @@
import EffectExercises from "../components/exercises/EffectExercises";
import Heading from "../components/globals/Heading"
export default function EffectExercisesPage() {
return (
<div>
<Heading title="Effekte" />
<EffectExercises />
</div>
);
}

View File

@@ -0,0 +1,11 @@
import RefExercise from "../components/exercises/RefExercise";
import Heading from "../components/globals/Heading";
export default function FormsPage() {
return (
<div>
<Heading title="Formulare" />
<RefExercise />
</div>
);
}

View File

@@ -0,0 +1,10 @@
import Heading from "../components/globals/Heading"
export default function HomePage() {
return (
<>
<Heading title="Willkommen" />
<p>Willkommen auf der Startseite!</p>
</>
);
}

View File

@@ -0,0 +1,11 @@
import MemoCallback from "../components/exercises/MemoCallback";
import Heading from "../components/globals/Heading";
export default function MemoCallbackPage() {
return (
<>
<Heading title="Memo und Callback" />
<MemoCallback />
</>
)
}

View File

@@ -0,0 +1,13 @@
import UserEffect from "../components/exercises/UserEffect";
import { UserOverview } from "../components/exercises/UserOverview";
import Heading from "../components/globals/Heading";
export default function UsersPage() {
return (
<div>
<Heading title="Benutzer" />
<UserEffect />
<UserOverview />
</div>
);
}