From 7661c951ad478cfeda11647b128b3ebbd4b3be77 Mon Sep 17 00:00:00 2001 From: Philippe Torrel Date: Wed, 26 Aug 2026 12:56:36 +0200 Subject: [PATCH] --- .../tag52/react-app/package-lock.json | 76 ++++++++++++++++++- .../unterricht/tag52/react-app/package.json | 4 +- .../unterricht/tag52/react-app/src/App.jsx | 7 +- .../src/components/footers/FooterMain.jsx | 4 +- .../src/components/headers/HeaderMain.jsx | 8 ++ .../react-app/src/components/navs/NavMain.jsx | 57 ++++++++++++++ .../src/components/navs/NavSocial.jsx | 33 ++++++++ .../src/components/sliders/SliderSplide.jsx | 33 ++++++++ .../unterricht/tag52/react-app/src/main.jsx | 7 +- .../tag52/react-app/src/pages/About.jsx | 13 ++++ .../tag52/react-app/src/pages/Contact.jsx | 16 ++++ .../tag52/react-app/src/pages/Home.jsx | 13 ++++ .../tag52/react-app/src/routes/Router.jsx | 17 +++++ .../react-app/src/styles/03_base/_colors.scss | 2 + .../react-app/src/styles/03_base/_theme.scss | 5 ++ .../src/styles/04_plugins/_index.scss | 4 +- .../src/styles/05_modules/_footer-main.scss | 25 +++++- .../src/styles/05_modules/_header-main.scss | 10 +-- .../src/styles/05_modules/_index.scss | 3 +- .../src/styles/05_modules/_nav-social.scss | 74 ++++++++++++++++++ 20 files changed, 395 insertions(+), 16 deletions(-) create mode 100644 05_react/unterricht/tag52/react-app/src/components/navs/NavMain.jsx create mode 100644 05_react/unterricht/tag52/react-app/src/components/navs/NavSocial.jsx create mode 100644 05_react/unterricht/tag52/react-app/src/components/sliders/SliderSplide.jsx create mode 100644 05_react/unterricht/tag52/react-app/src/pages/About.jsx create mode 100644 05_react/unterricht/tag52/react-app/src/pages/Contact.jsx create mode 100644 05_react/unterricht/tag52/react-app/src/pages/Home.jsx create mode 100644 05_react/unterricht/tag52/react-app/src/routes/Router.jsx create mode 100644 05_react/unterricht/tag52/react-app/src/styles/05_modules/_nav-social.scss diff --git a/05_react/unterricht/tag52/react-app/package-lock.json b/05_react/unterricht/tag52/react-app/package-lock.json index 8b27f45..cd9d4bb 100644 --- a/05_react/unterricht/tag52/react-app/package-lock.json +++ b/05_react/unterricht/tag52/react-app/package-lock.json @@ -8,11 +8,13 @@ "name": "react-app", "version": "0.0.0", "dependencies": { + "@splidejs/react-splide": "^0.7.12", "axios": "^1.19.0", "bootstrap": "^5.3.8", "react": "^19.2.8", "react-dom": "^19.2.8", - "react-icons": "^5.7.0" + "react-icons": "^5.7.0", + "react-router-dom": "^7.18.2" }, "devDependencies": { "@types/react": "^19.2.18", @@ -984,6 +986,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@splidejs/react-splide": { + "version": "0.7.12", + "resolved": "https://registry.npmjs.org/@splidejs/react-splide/-/react-splide-0.7.12.tgz", + "integrity": "sha512-UfXH+j47jsMc4x5HA/aOwuuHPqn6y9+ZTNYPWDRD8iLKvIVMZlzq2unjUEvyDAU+TTVPZOXkG2Ojeoz0P4AkZw==", + "license": "MIT", + "dependencies": { + "@splidejs/splide": "^4.1.3" + } + }, + "node_modules/@splidejs/splide": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@splidejs/splide/-/splide-4.1.4.tgz", + "integrity": "sha512-5I30evTJcAJQXt6vJ26g2xEkG+l1nXcpEw4xpKh0/FWQ8ozmAeTbtniVtVmz2sH1Es3vgfC4SS8B2X4o5JMptA==", + "license": "MIT" + }, "node_modules/@types/react": { "version": "19.2.18", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", @@ -1136,6 +1153,19 @@ "node": ">= 0.8" } }, + "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/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -1932,6 +1962,44 @@ "react": "*" } }, + "node_modules/react-router": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.2.tgz", + "integrity": "sha512-aUVMjFm3GAPTTZL7oYr5E7ETiqfQCHRLH+B+5afnICvf0r7kkK4eR6SMuwbSTJw/7t+12khT/Kahij49fqOCIg==", + "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.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.2.tgz", + "integrity": "sha512-AIKJ/jgGlFb3EbfCXk5Gzshiwt+l3mqbCrNjmEWMMjqQxNJ3svBa6bgzFyCC2Sw3RA0VWF1kg3uQf2OFhxb8hw==", + "license": "MIT", + "dependencies": { + "react-router": "7.18.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/readdirp": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", @@ -2375,6 +2443,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-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", diff --git a/05_react/unterricht/tag52/react-app/package.json b/05_react/unterricht/tag52/react-app/package.json index 882699a..b5a9606 100644 --- a/05_react/unterricht/tag52/react-app/package.json +++ b/05_react/unterricht/tag52/react-app/package.json @@ -10,11 +10,13 @@ "preview": "vite preview" }, "dependencies": { + "@splidejs/react-splide": "^0.7.12", "axios": "^1.19.0", "bootstrap": "^5.3.8", "react": "^19.2.8", "react-dom": "^19.2.8", - "react-icons": "^5.7.0" + "react-icons": "^5.7.0", + "react-router-dom": "^7.18.2" }, "devDependencies": { "@types/react": "^19.2.18", diff --git a/05_react/unterricht/tag52/react-app/src/App.jsx b/05_react/unterricht/tag52/react-app/src/App.jsx index 7df15ad..9fd262a 100644 --- a/05_react/unterricht/tag52/react-app/src/App.jsx +++ b/05_react/unterricht/tag52/react-app/src/App.jsx @@ -1,5 +1,7 @@ import FooterMain from './components/footers/FooterMain'; import HeaderMain from './components/headers/HeaderMain'; +import NavMain from './components/navs/NavMain'; +import Router from './routes/Router'; function App(props) { // const { } = props; @@ -7,8 +9,9 @@ function App(props) { return ( <> -
-

Hello

+ +
+
diff --git a/05_react/unterricht/tag52/react-app/src/components/footers/FooterMain.jsx b/05_react/unterricht/tag52/react-app/src/components/footers/FooterMain.jsx index 1c6a6dc..edb318a 100644 --- a/05_react/unterricht/tag52/react-app/src/components/footers/FooterMain.jsx +++ b/05_react/unterricht/tag52/react-app/src/components/footers/FooterMain.jsx @@ -1,3 +1,5 @@ +import NavSocial from '../navs/NavSocial'; + const FooterMain = (props) => { // const { } = props; @@ -35,7 +37,7 @@ const FooterMain = (props) => {

Social Media

- {/* social media icons */} +
diff --git a/05_react/unterricht/tag52/react-app/src/components/headers/HeaderMain.jsx b/05_react/unterricht/tag52/react-app/src/components/headers/HeaderMain.jsx index 2150dce..f06dc74 100644 --- a/05_react/unterricht/tag52/react-app/src/components/headers/HeaderMain.jsx +++ b/05_react/unterricht/tag52/react-app/src/components/headers/HeaderMain.jsx @@ -1,8 +1,16 @@ import LogoMain from '../logos/LogoMain'; +import SliderSplide from '../sliders/SliderSplide'; const HeaderMain = () => { + const images = [ + { path: '/img/slides/slide-01.jpg', title: 'Classroom' }, + { path: '/img/slides/slide-02.jpg', title: 'Mountains' }, + { path: '/img/slides/slide-03.jpg', title: 'Canyons' }, + ]; + return (
+
diff --git a/05_react/unterricht/tag52/react-app/src/components/navs/NavMain.jsx b/05_react/unterricht/tag52/react-app/src/components/navs/NavMain.jsx new file mode 100644 index 0000000..21d3c0b --- /dev/null +++ b/05_react/unterricht/tag52/react-app/src/components/navs/NavMain.jsx @@ -0,0 +1,57 @@ +import { NavLink } from 'react-router-dom'; + +const NavMain = () => { + return ( + + ); +}; +export default NavMain; diff --git a/05_react/unterricht/tag52/react-app/src/components/navs/NavSocial.jsx b/05_react/unterricht/tag52/react-app/src/components/navs/NavSocial.jsx new file mode 100644 index 0000000..f69fde1 --- /dev/null +++ b/05_react/unterricht/tag52/react-app/src/components/navs/NavSocial.jsx @@ -0,0 +1,33 @@ +import { FaInstagram, FaXTwitter, FaYoutube, FaMeta } from 'react-icons/fa6'; + +const NavSocial = (props) => { + // const { } = props; + + return ( + + ); +}; +export default NavSocial; diff --git a/05_react/unterricht/tag52/react-app/src/components/sliders/SliderSplide.jsx b/05_react/unterricht/tag52/react-app/src/components/sliders/SliderSplide.jsx new file mode 100644 index 0000000..eb27bfd --- /dev/null +++ b/05_react/unterricht/tag52/react-app/src/components/sliders/SliderSplide.jsx @@ -0,0 +1,33 @@ +import { Splide, SplideSlide } from '@splidejs/react-splide'; + +const SliderSplide = (props) => { + const { + images = [], + label = 'Slides', + options = { + rewind: true, + height: '100%', + autoplay: true, + speed: 800, + type: 'fade', + }, + } = props; + + return ( + <> + {images.length > 0 && ( +
+ + {images.map(({ path, title }, idx) => ( + // + + {title} + + ))} + +
+ )} + + ); +}; +export default SliderSplide; diff --git a/05_react/unterricht/tag52/react-app/src/main.jsx b/05_react/unterricht/tag52/react-app/src/main.jsx index afc3f15..6187b22 100644 --- a/05_react/unterricht/tag52/react-app/src/main.jsx +++ b/05_react/unterricht/tag52/react-app/src/main.jsx @@ -1,13 +1,18 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; +import { BrowserRouter } from 'react-router-dom'; // eigene separate Gestaltung mit main.scss (beinhaltet boostrap) import './styles/main.scss'; +import 'bootstrap'; // bootstrap JS wird über esbuild aus node_modules ausgelesen und eingebunden (bundled) + import App from './App.jsx'; createRoot(document.getElementById('root')).render( - + + + , ); diff --git a/05_react/unterricht/tag52/react-app/src/pages/About.jsx b/05_react/unterricht/tag52/react-app/src/pages/About.jsx new file mode 100644 index 0000000..6be700c --- /dev/null +++ b/05_react/unterricht/tag52/react-app/src/pages/About.jsx @@ -0,0 +1,13 @@ +const About = (props) => { + // const { } = props; + + return ( +
+
+

About

+

Welcome to the Single-Page-Application (SPA) with React. This is the About page.

+
+
+ ); +}; +export default About; diff --git a/05_react/unterricht/tag52/react-app/src/pages/Contact.jsx b/05_react/unterricht/tag52/react-app/src/pages/Contact.jsx new file mode 100644 index 0000000..68ff51a --- /dev/null +++ b/05_react/unterricht/tag52/react-app/src/pages/Contact.jsx @@ -0,0 +1,16 @@ +const Contact = (props) => { + // const { } = props; + + return ( +
+
+

Contact

+

+ Lorem ipsum dolor, sit amet consectetur adipisicing elit. Iste suscipit eos autem iure soluta laboriosam in + perferendis atque explicabo, possimus eius? Ea magnam sed atque exercitationem officiis ipsum, deserunt iste. +

+
+
+ ); +}; +export default Contact; diff --git a/05_react/unterricht/tag52/react-app/src/pages/Home.jsx b/05_react/unterricht/tag52/react-app/src/pages/Home.jsx new file mode 100644 index 0000000..ee88d61 --- /dev/null +++ b/05_react/unterricht/tag52/react-app/src/pages/Home.jsx @@ -0,0 +1,13 @@ +const Home = (props) => { + // const { } = props; + + return ( +
+
+

Hello, Spa!

+

Welcome to the Single-Page-Application (SPA) with React. This is the Home page.

+
+
+ ); +}; +export default Home; diff --git a/05_react/unterricht/tag52/react-app/src/routes/Router.jsx b/05_react/unterricht/tag52/react-app/src/routes/Router.jsx new file mode 100644 index 0000000..53cd192 --- /dev/null +++ b/05_react/unterricht/tag52/react-app/src/routes/Router.jsx @@ -0,0 +1,17 @@ +import { Route, Routes } from 'react-router-dom'; +import Home from '../pages/Home'; +import About from '../pages/About'; +import Contact from '../pages/Contact'; + +const Router = (props) => { + // const { } = props; + + return ( + + } /> + } /> + } /> + + ); +}; +export default Router; diff --git a/05_react/unterricht/tag52/react-app/src/styles/03_base/_colors.scss b/05_react/unterricht/tag52/react-app/src/styles/03_base/_colors.scss index fcd9a54..452a8e5 100644 --- a/05_react/unterricht/tag52/react-app/src/styles/03_base/_colors.scss +++ b/05_react/unterricht/tag52/react-app/src/styles/03_base/_colors.scss @@ -10,3 +10,5 @@ $color-white: white; // falls weiß geändert wird z.B.: #f8f8f8 $color-dark-blue: #283e4a; $linear-gradient-dark: linear-gradient(180deg, rgba(40, 62, 74, 1) 0%, rgba(24, 32, 38, 1) 100%); + +$color-link: $color-2; diff --git a/05_react/unterricht/tag52/react-app/src/styles/03_base/_theme.scss b/05_react/unterricht/tag52/react-app/src/styles/03_base/_theme.scss index a892494..6042f02 100644 --- a/05_react/unterricht/tag52/react-app/src/styles/03_base/_theme.scss +++ b/05_react/unterricht/tag52/react-app/src/styles/03_base/_theme.scss @@ -44,3 +44,8 @@ h6 { font-family: $font-headline; font-weight: 700; } + +a { + color: $color-link; + text-decoration: none; +} diff --git a/05_react/unterricht/tag52/react-app/src/styles/04_plugins/_index.scss b/05_react/unterricht/tag52/react-app/src/styles/04_plugins/_index.scss index 162f2b9..68cffed 100644 --- a/05_react/unterricht/tag52/react-app/src/styles/04_plugins/_index.scss +++ b/05_react/unterricht/tag52/react-app/src/styles/04_plugins/_index.scss @@ -1,4 +1,4 @@ -// @import 'splide-4.1.4/themes/default/index'; -// @import 'splide-4.1.4/core/index'; +@import 'splide-4.1.4/themes/default/index'; +@import 'splide-4.1.4/core/index'; // @import 'toastify-1.12/toastify'; diff --git a/05_react/unterricht/tag52/react-app/src/styles/05_modules/_footer-main.scss b/05_react/unterricht/tag52/react-app/src/styles/05_modules/_footer-main.scss index e171af5..14cd675 100644 --- a/05_react/unterricht/tag52/react-app/src/styles/05_modules/_footer-main.scss +++ b/05_react/unterricht/tag52/react-app/src/styles/05_modules/_footer-main.scss @@ -4,6 +4,12 @@ padding: 3rem 0; [class^='col'] { color: $color-white; + + display: flex; + justify-content: center; + @include media-breakpoint-up(md) { + justify-content: flex-start; + } h2, h3, h4, @@ -13,6 +19,18 @@ padding: 0.5rem 0; margin-bottom: 1rem; letter-spacing: 2px; + text-align: center; + } + } + + @include media-breakpoint-up(sm) { + h1, + h2, + h3, + h4, + h5, + h6 { + text-align: left; } } @@ -20,9 +38,12 @@ flex-direction: column; > div { &:nth-child(1) { - order: 2; + order: 3; } &:nth-child(2) { + order: 2; + } + &:nth-child(3) { order: 1; } } @@ -31,7 +52,7 @@ // @media (min-width:576px) { @include media-breakpoint-up(sm) { .row { - flex-direction: row; + flex-direction: row-reverse; } } } diff --git a/05_react/unterricht/tag52/react-app/src/styles/05_modules/_header-main.scss b/05_react/unterricht/tag52/react-app/src/styles/05_modules/_header-main.scss index 8b78bb8..1c6fe7e 100644 --- a/05_react/unterricht/tag52/react-app/src/styles/05_modules/_header-main.scss +++ b/05_react/unterricht/tag52/react-app/src/styles/05_modules/_header-main.scss @@ -41,6 +41,11 @@ overflow: hidden; .splide__track { height: 100%; + .splide__slide img { + object-fit: cover; + width: 100%; + height: 100%; + } .splider-content { &::after { content: ''; @@ -55,11 +60,6 @@ height: 100%; padding: 0; - img { - object-fit: cover; - width: 100%; - height: 100%; - } } } } diff --git a/05_react/unterricht/tag52/react-app/src/styles/05_modules/_index.scss b/05_react/unterricht/tag52/react-app/src/styles/05_modules/_index.scss index 9ea0ada..49f2ce8 100644 --- a/05_react/unterricht/tag52/react-app/src/styles/05_modules/_index.scss +++ b/05_react/unterricht/tag52/react-app/src/styles/05_modules/_index.scss @@ -3,6 +3,7 @@ @import 'header-main'; // @import 'inputAmount'; @import 'logo-main'; -@import 'nav-menu'; +// @import 'nav-menu'; +@import 'nav-social'; // @import 'menu-main'; // @import 'product-manager'; diff --git a/05_react/unterricht/tag52/react-app/src/styles/05_modules/_nav-social.scss b/05_react/unterricht/tag52/react-app/src/styles/05_modules/_nav-social.scss new file mode 100644 index 0000000..3b07117 --- /dev/null +++ b/05_react/unterricht/tag52/react-app/src/styles/05_modules/_nav-social.scss @@ -0,0 +1,74 @@ +@use 'sass:color'; + +.nav-social { + ul { + list-style: none; + padding: 0; + margin: 0; + display: flex; + justify-content: flex-start; + align-items: center; + li { + a { + color: $color-white; + display: inline-block; + padding: 0.5rem; + margin: 3px; + background-color: color.scale($color-dark-blue, $lightness: 10%); + // background-color: lighten($color-dark-blue, 5%); // deprecated + border-radius: 50%; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + text-decoration: none; + transition: all 0.4s ease-out; + &:hover, + &:focus { + background-color: color.scale($color-dark-blue, $lightness: 20%); + } + + &[aria-label='Youtube'] { + &:hover, + &:focus { + background-color: #f00; + } + } + &[aria-label='Meta'] { + &:hover, + &:focus { + background-color: #0064e0; + } + } + &[aria-label^='X '] { + &:hover, + &:focus { + background-color: #000; + } + } + &[aria-label^='X '] { + &:hover, + &:focus { + background-color: #000; + } + } + &[aria-label^='Instagram'] { + &:hover, + &:focus { + // background: linear-gradient( + // 9deg, + // rgba(254, 218, 117, 1) 10%, + // rgba(250, 126, 30, 1) 30%, + // rgba(239, 100, 57, 1) 43%, + // rgba(214, 41, 118, 1) 55%, + // rgba(150, 47, 191, 1) 67%, + // rgba(79, 91, 213, 1) 81% + // ); + background-color: #405de6; + } + } + } + } + } +}