Compare commits
11 Commits
main
...
branch-fra
| Author | SHA1 | Date |
|---|---|---|
|
|
26c9dcd953 | |
|
|
6e90fc3725 | |
|
|
082eb3009e | |
|
|
f3859ea3e4 | |
|
|
773145a856 | |
|
|
b48789e805 | |
|
|
a0b6a56ef7 | |
|
|
f8a77ea1e9 | |
|
|
cf3de64554 | |
|
|
f802e63dc5 | |
|
|
0899971a83 |
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset ="utf-8">
|
||||||
|
<title>Ungeordnete Liste</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Unnummerierte Liste</h1>
|
||||||
|
<ul>
|
||||||
|
<li>HTML lernen</li>
|
||||||
|
<ul>
|
||||||
|
<li>Tags</li>
|
||||||
|
<li>Listen</li>
|
||||||
|
<li>Formulare</li>
|
||||||
|
</ul>
|
||||||
|
<li>CSS entdecken</li>
|
||||||
|
<li>JavaScript üben</li>
|
||||||
|
</ul>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Muffins</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Muffins backen</h1>
|
||||||
|
<ol type="I" start="IV" reversed>
|
||||||
|
<li>Backofen auf 180 °C vorheizen</li>
|
||||||
|
<li>Teig vorbereiten (Mehl, Zucker, Eier etc. verrühren)</li>
|
||||||
|
<li>Teig in Förmchen füllen</li>
|
||||||
|
<li>Muffins 20 Minuten backen</li>
|
||||||
|
<li>Abkühlen lassen und servieren</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Stundenplan</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table border="1">
|
||||||
|
<caption>Stundenplan - 8. Schuljahr</caption>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Zeit</th>
|
||||||
|
<th>Montag</th>
|
||||||
|
<th>Dienstag</th>
|
||||||
|
<th>Mittwoch</th>
|
||||||
|
<th>Donnerstag</th>
|
||||||
|
<th>Freitag</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>08-10 Uhr</td>
|
||||||
|
<td>Mathe</td>
|
||||||
|
<td>Englisch</td>
|
||||||
|
<td>Physik</td>
|
||||||
|
<td>Chemie</td>
|
||||||
|
<td>Sport</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>10-12 Uhr</td>
|
||||||
|
<td>Deutsch</td>
|
||||||
|
<td>Biologie</td>
|
||||||
|
<td>Musik</td>
|
||||||
|
<td>Mathe</td>
|
||||||
|
<td>Kunst</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td colspan="6">Stand: Juli 2025</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Sectioning</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<nav>
|
||||||
|
<a href="#main">Hauptinhalt</a>
|
||||||
|
<a href="#html">Design</a>
|
||||||
|
<a href =#css>Design</a>
|
||||||
|
<a href="#footer">Kontakt</a>
|
||||||
|
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<main id="main">
|
||||||
|
<section>
|
||||||
|
<article id="html">
|
||||||
|
<h2>HTML</h2>
|
||||||
|
<p>HTML ist eine Auszeichnungssprache</p>
|
||||||
|
</article>
|
||||||
|
<article id="css">
|
||||||
|
<h2>CSS</h2>
|
||||||
|
<p>CSS ist eine Stylesprache</p>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2>Tipp der Woche</h2>
|
||||||
|
<p>...selbst Tippen!</p>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
<footer id="footer">
|
||||||
|
<p>© 2025 WebWeekly Redaktion</p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Meine Lieblingsrezepte</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<nav>
|
||||||
|
<a href="rezepte/bolognese.html">Vegetarische Bolognese</a> |
|
||||||
|
<a href="rezepte/ramen.html">Ramen</a> |
|
||||||
|
<a href="rezepte/kimchi.html">Kimchi</a> |
|
||||||
|
<a href="rezepte/nudelpfanne.html">Nudelpfanne</a> |
|
||||||
|
<a href="rezepte/salat.html">Salat</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<table border="1">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Rezept</th>
|
||||||
|
<th>Bild</th>
|
||||||
|
<th>Arbeitsaufwand</th>
|
||||||
|
<th>Portionen</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><a href="detailseiten/bolognese.html">Vegetarische Bolognese</a></td>
|
||||||
|
<td><img src="img/bolognese.jpeg" alt="Spaghetti Bolognese"width="300"></td>
|
||||||
|
<td>60 Minuten</td>
|
||||||
|
<td>4</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="detailseiten/ramen.html">Ramen</a></td>
|
||||||
|
<td><img src="img/ramen.jpeg" alt="Vegetarische Ramen"width="300"></td>
|
||||||
|
<td>30 Minuten</td>
|
||||||
|
<td>2</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="detailseiten/kimchi.html">Kimchi</a></td>
|
||||||
|
<td><img src="img/kimchi.jpeg" alt="Kimchi"width="300"></td>
|
||||||
|
<td>30 Minuten + 3 Wochen Wartezeit</td>
|
||||||
|
<td>30</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="detailseiten/nudelpfanne.html">Nudelpfanne</a></td>
|
||||||
|
<td><img src="img/nudelpfanne.jpeg" alt="Nudelpfanne" width="300"></td>
|
||||||
|
<td>20 Minuten</td>
|
||||||
|
<td>2</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="detailseiten/salat.html">Salat</a></td>
|
||||||
|
<td><img src="img/salat.jpeg" alt="Salat" width="300"></td>
|
||||||
|
<td>10 Minuten</td>
|
||||||
|
<td>2</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
<footer>
|
||||||
|
<p>Kontakt: <a href="mailto:meine.rezepte@example.com">meine.rezepte@example.com</a></p>
|
||||||
|
<p>Erstellt von: Francesca Bläse | © 2025 Meine Lieblingsrezepte</p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Vegetarische Spaghetti Bolognese</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Vegetarische Spaghetti Bolognese</h1>
|
||||||
|
<nav>
|
||||||
|
<a href="../index.html">Zurück zur Übersicht</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<img src="../img/bolognese.jpeg" alt="Vegetarische Spaghetti Bolognese" width="400">
|
||||||
|
|
||||||
|
<h2>Beschreibung</h2>
|
||||||
|
<p>Eine herzhafte, vegetarische Variante der klassischen Bolognese – mit Tofu statt Hackfleisch.
|
||||||
|
Perfekt für alle, die bewusst genießen wollen, ohne auf Geschmack zu verzichten.</p>
|
||||||
|
|
||||||
|
<h2>Zutaten (für 4 Personen)</h2>
|
||||||
|
<ul>
|
||||||
|
<li>400 g Spaghetti</li>
|
||||||
|
<li>300 g fester Tofu</li>
|
||||||
|
<li>1 Zwiebel, 2 Knoblauchzehen</li>
|
||||||
|
<li>1 Dose stückige Tomaten (400 g)</li>
|
||||||
|
<li>2 EL Tomatenmark</li>
|
||||||
|
<li>2 EL Olivenöl</li>
|
||||||
|
<li>1 TL Sojasauce</li>
|
||||||
|
<li>Salz, Pfeffer, Oregano, Basilikum</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Zubereitung</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Zwiebel und Knoblauch fein hacken und in Olivenöl glasig anbraten.</li>
|
||||||
|
<li>Tofu mit einer Gabel zerbröseln oder fein zerdrücken, dann mit Sojasauce goldbraun anbraten.</li>
|
||||||
|
<li>Tomaten und Tomatenmark hinzufügen, würzen und etwa 20–30 Minuten köcheln lassen.</li>
|
||||||
|
<li>Spaghetti nach Packungsanweisung kochen, abgießen und mit d
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Kimchi</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Kimchi</h1>
|
||||||
|
<nav>
|
||||||
|
<a href="../index.html">Zurück zur Übersicht</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<img src="../img/kimchi.jpeg" alt="Kimchi" width="400">
|
||||||
|
|
||||||
|
<h2>Beschreibung</h2>
|
||||||
|
<p>Koreanisches fermentiertes Gemüse – scharf, würzig und gesund.</p>
|
||||||
|
|
||||||
|
<h2>Zutaten (ergibt ca. 1 Glas)</h2>
|
||||||
|
<ul>
|
||||||
|
<li>1 Chinakohl</li>
|
||||||
|
<li>2 EL Salz</li>
|
||||||
|
<li>2 Knoblauchzehen, 1 Stück Ingwer</li>
|
||||||
|
<li>2 EL Gochugaru (Chilipulver)</li>
|
||||||
|
<li>1 TL Zucker, 1 Frühlingszwiebel</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Zubereitung</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Chinakohl in Stücke schneiden, salzen und 2 Stunden ziehen lassen.</li>
|
||||||
|
<li>Wasser abgießen, mit Gewürzpaste mischen.</li>
|
||||||
|
<li>In Glas füllen, 2–3 Tage bei Zimmertemperatur fermentieren lassen.</li>
|
||||||
|
<li>Kühl lagern und genießen.</li>
|
||||||
|
</ol>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>© 2025 Meine Lieblingsrezepte</p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Nudelpfanne</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Nudelpfanne</h1>
|
||||||
|
<nav>
|
||||||
|
<a href="../index.html">Zurück zur Übersicht</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<img src="../img/nudelpfanne.jpeg" alt="Nudelpfanne" width="400">
|
||||||
|
|
||||||
|
<h2>Beschreibung</h2>
|
||||||
|
<p>Schnelles Wokgericht mit Gemüse und Nudeln – ideal für den Feierabend.</p>
|
||||||
|
|
||||||
|
<h2>Zutaten (für 2 Personen)</h2>
|
||||||
|
<ul>
|
||||||
|
<li>200 g Nudeln</li>
|
||||||
|
<li>1 Paprika, 1 Zucchini</li>
|
||||||
|
<li>1 Zwiebel, 1 Knoblauchzehe</li>
|
||||||
|
<li>2 EL Sojasauce</li>
|
||||||
|
<li>Etwas Öl zum Braten</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Zubereitung</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Nudeln kochen und beiseitestellen.</li>
|
||||||
|
<li>Gemüse anbraten, Nudeln hinzufügen.</li>
|
||||||
|
<li>Mit Sojasauce abschmecken und servieren.</li>
|
||||||
|
</ol>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>© 2025 Meine Lieblingsrezepte</p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Vegetarische Ramen</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Vegetarische Ramen</h1>
|
||||||
|
<nav>
|
||||||
|
<a href="../index.html">Zurück zur Übersicht</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<img src="../img/ramen.jpeg" alt="Vegetarische Ramen" width="400">
|
||||||
|
|
||||||
|
<h2>Beschreibung</h2>
|
||||||
|
<p>Japanische Nudelsuppe mit Gemüse und würziger Brühe – perfekt für kalte Tage.</p>
|
||||||
|
|
||||||
|
<h2>Zutaten (für 2 Personen)</h2>
|
||||||
|
<ul>
|
||||||
|
<li>150 g Ramen-Nudeln</li>
|
||||||
|
<li>1 Liter Gemüsebrühe</li>
|
||||||
|
<li>1 Möhre, 1 Frühlingszwiebel</li>
|
||||||
|
<li>100 g Tofu</li>
|
||||||
|
<li>Sojasauce, Sesamöl, Chili</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Zubereitung</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Brühe erhitzen, mit Sojasauce und Sesamöl würzen.</li>
|
||||||
|
<li>Gemüse schneiden und kurz mitköcheln lassen.</li>
|
||||||
|
<li>Nudeln und Tofu hinzufügen, 5 Minuten ziehen lassen.</li>
|
||||||
|
<li>Mit Chili und Frühlingszwiebeln garnieren.</li>
|
||||||
|
</ol>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>© 2025 Meine Lieblingsrezepte</p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Bunter Salat</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Bunter Salat</h1>
|
||||||
|
<nav>
|
||||||
|
<a href="../index.html">Zurück zur Übersicht</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<img src="../img/salat.jpeg" alt="Bunter Salat" width="400">
|
||||||
|
|
||||||
|
<h2>Beschreibung</h2>
|
||||||
|
<p>Frischer, leichter Salat mit knackigem Gemüse – perfekt als Beilage oder leichtes Mittagessen.</p>
|
||||||
|
|
||||||
|
<h2>Zutaten (für 2 Personen)</h2>
|
||||||
|
<ul>
|
||||||
|
<li>1 Kopf Blattsalat</li>
|
||||||
|
<li>1 Tomate, ½ Gurke</li>
|
||||||
|
<li>1 Karotte, etwas Mais</li>
|
||||||
|
<li>2 EL Olivenöl, 1 EL Essig</li>
|
||||||
|
<li>Salz, Pfeffer</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Zubereitung</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Gemüse waschen und in Stücke schneiden.</li>
|
||||||
|
<li>Mit Öl und Essig anmachen.</li>
|
||||||
|
<li>Mit Salz und Pfeffer abschmecken.</li>
|
||||||
|
</ol>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>© 2025 Meine Lieblingsrezepte</p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
|
@ -0,0 +1,34 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Login</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Kundenkonto</h1><br>
|
||||||
|
<h2>Melden Sie sich bitte an</h2><br>
|
||||||
|
<form action="" method="GET">
|
||||||
|
<label for="email">E-Mail:</label>
|
||||||
|
<input type="email" name="email" id="email" required><br>
|
||||||
|
<label for="password">Passwort:</label>
|
||||||
|
<input type="password" name="password" id="password" required><br>
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Aufgabe 8
|
||||||
|
|
||||||
|
a)
|
||||||
|
Ja die Eingabe wurde als Query Parameter übernommen
|
||||||
|
Problematisch ist das, weil sowohl Passwort als auch Benutzername in der URL sichtbar sind (Klartext)
|
||||||
|
|
||||||
|
b)
|
||||||
|
Nein ich bekomme keine Meldung aber das Formular wird auch nicht abgesendet
|
||||||
|
|
||||||
|
c)
|
||||||
|
Ja, es erscheint die Nachricht "bitte füllen Sie dieses Feld aus"
|
||||||
|
-->
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Obstebestellung</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Bestellen Sie sich Ihr Obst direkt nach Hause!</h1>
|
||||||
|
<form action="" method="GET">
|
||||||
|
<label for="obst">Obst:</label>
|
||||||
|
<input type="text" id="obst" name="obst" list="obstListe" required>
|
||||||
|
<datalist id="obstListe">
|
||||||
|
<option value="Apfel">
|
||||||
|
<option value="Banane">
|
||||||
|
<option value="Birne">
|
||||||
|
<option value="Kirsche">
|
||||||
|
<option value="Traube">
|
||||||
|
<option value="Pfirsich">
|
||||||
|
<option value="Mango">
|
||||||
|
<option value="Erdbeere">
|
||||||
|
</datalist>
|
||||||
|
<br><br>
|
||||||
|
<label for="number">Stückzahl:</label>
|
||||||
|
<input type="number" min="1" max="10" name="number" id="number">
|
||||||
|
<br><br>
|
||||||
|
<label for"color">Farbe:</label>
|
||||||
|
<input type="color">
|
||||||
|
<br><br>
|
||||||
|
<button type="submit">Bestellen</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Aufgabe 8
|
||||||
|
|
||||||
|
a) Ja, werden übernommen:
|
||||||
|
http://127.0.0.1:3000/web/04/labor/04_loesungen/obstbestellung.html?obst=Apfel&number=10
|
||||||
|
|
||||||
|
b) ja, ich erhalte aber nicht nur Vorschläge für den Anfangsbuchstaben
|
||||||
|
|
||||||
|
c) Ja, die Eingaben werden trotzdem übernommen
|
||||||
|
http://127.0.0.1:3000/web/04/labor/04_loesungen/obstbestellung.html?obst=Maracuja&number=2
|
||||||
|
|
||||||
|
d) Ich erhalte die Validierungsnachricht bereits vor dem senden
|
||||||
|
-->
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Workshop-Anmeldung</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Workshopanmeldung</h1>
|
||||||
|
|
||||||
|
<form action="http://localhost:8080/registrierung" method="POST">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Persönliche Angaben:</legend>
|
||||||
|
<label for="vorname">Vorname:</label><br>
|
||||||
|
<input type="text" id="vorname" name="vorname" placeholder="Vorname" required><br><br>
|
||||||
|
|
||||||
|
<label for="nachname">Nachname:</label><br>
|
||||||
|
<input type="text" id="nachname" name="nachname" placeholder="Nachname" required><br><br>
|
||||||
|
|
||||||
|
<label for="email">E-Mail:</label><br>
|
||||||
|
<input type="email" id="email" name="email" required><br><br>
|
||||||
|
|
||||||
|
<label for="handy">Handynummer:</label><br>
|
||||||
|
<input type="tel" id="handy" name="handy"><br>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Kursauswahl:</legend>
|
||||||
|
<label for="kurs">Kurs:</label><br>
|
||||||
|
<input type="text" id="kurs" name="kurs" value="Webentwicklung Basics" readonly><br><br>
|
||||||
|
|
||||||
|
<label for="session">Bevorzugte Session:</label><br>
|
||||||
|
<select id="session" name="session" size="4">
|
||||||
|
<option value="vormittag">Vormittag</option>
|
||||||
|
<option value="nachmittag">Nachmittag</option>
|
||||||
|
<option value="abend">Abend</option>
|
||||||
|
<option value="wochenende">Wochenende</option>
|
||||||
|
</select>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Zusätzliche Optionen:</legend>
|
||||||
|
<input type="checkbox" id="agb" name="agb" required>
|
||||||
|
<label for="agb">Ich akzeptiere die Teilnahmebedingungen.</label><br>
|
||||||
|
|
||||||
|
<input type="checkbox" id="newsletter" name="newsletter" value="ja">
|
||||||
|
<label for="newsletter">Newsletter abonnieren.</label><br>
|
||||||
|
|
||||||
|
<input type="checkbox" id="equipment" name="equipment" value="ja">
|
||||||
|
<label for="equipment">Ich benötige spezielles Equipment.</label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Teilnahmeformat:</legend>
|
||||||
|
<input type="radio" id="online" name="format" value="online" required>
|
||||||
|
<label for="online">Online</label><br>
|
||||||
|
|
||||||
|
<input type="radio" id="praesenz" name="format" value="praesenz">
|
||||||
|
<label for="praesenz">Präsenz</label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<button type="submit">Jetzt anmelden</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
1.1) Antonette
|
||||||
|
1.2) 10
|
||||||
|
1.3) sunt aut facere repellat provident occaecati excepturi optio reprehenderit
|
||||||
|
1.4) 5
|
||||||
|
1.5) Ja
|
||||||
|
1.6) curl https://jsonplaceholder.typicode.com/posts?userId=2
|
||||||
|
|
||||||
|
|
||||||
|
2.1)68eb4a0b-6c49-44e9-aec8-5af947d22141
|
||||||
|
curl https://hp-api.onrender.com/api/characters/staff
|
||||||
|
|
||||||
|
2.2) curl https://hp-api.onrender.com/api/character/68eb4a0b-6c49-44e9-aec8-5af947d22141
|
||||||
|
2.3) blond
|
||||||
|
|
||||||
|
3) siehe Datei staudenpflanzen.json
|
||||||
|
|
||||||
|
4.1)
|
||||||
|
{
|
||||||
|
"name": "Alex",
|
||||||
|
"alter": 30,
|
||||||
|
"wohnort": "Berlin"
|
||||||
|
}
|
||||||
|
|
||||||
|
4.2)
|
||||||
|
{
|
||||||
|
"produktname": "Kopfhörer",
|
||||||
|
"preis": 98.99,
|
||||||
|
"verfügbarkeit": "Ja",
|
||||||
|
"farben":["schwarz", "weiß"]
|
||||||
|
}
|
||||||
|
|
||||||
|
4.3)
|
||||||
|
{
|
||||||
|
"benutzername": "maria1999",
|
||||||
|
"passwort": "abc123",
|
||||||
|
"rolle": "Admin",
|
||||||
|
"adresse": {
|
||||||
|
"straße": "Bauernring 15",
|
||||||
|
"stadt": "Weilbach",
|
||||||
|
"plz": 12345
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
4.4)
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"titel": "Task1",
|
||||||
|
"erledigt": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"titel": "Task2",
|
||||||
|
"erledigt": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
4.5)
|
||||||
|
{
|
||||||
|
"titel": "Blabla",
|
||||||
|
"autor": "Blubb",
|
||||||
|
"inhalt": "Nix",
|
||||||
|
"kommentar": {
|
||||||
|
"autor": "Niemand",
|
||||||
|
"text": "Auch nix!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.0.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Simple Greeting API",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "http://localhost:8080"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/hello": {
|
||||||
|
"get": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"in": "query",
|
||||||
|
"description": "Name",
|
||||||
|
"required": false,
|
||||||
|
"schema": {"type": "string"}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"summary": "Returns a greeting",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Greeting response in plain text.",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"example": "Hello!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"requestBody":{
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"text/plain":{
|
||||||
|
"schema":{"type": "string"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": "Returns a plain text greeting",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Plain text greeting response",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"example": "Hello!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/hello-json": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Returns a greeting using a JSON body",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": { "type": "string" },
|
||||||
|
"age": { "type": "integer" }
|
||||||
|
},
|
||||||
|
"required": ["name", "age"]
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"name": "Florian",
|
||||||
|
"age": 23
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Greeting response in plain text",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": { "type": "string" },
|
||||||
|
"example": "Hello Florian, you are 23!" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"_id": "6909f3da83629c03e8adedd7",
|
||||||
|
"name": "Lavendel",
|
||||||
|
"botanischer_name": "Lavandula angustifolia",
|
||||||
|
"standort": "Sonnig, trocken",
|
||||||
|
"besonderheiten": "Duftend, bienenfreundlich, winterhart"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "6909f3db83629c03e8adedd9",
|
||||||
|
"name": "Funkie",
|
||||||
|
"botanischer_name": "Hosta",
|
||||||
|
"standort": "Halbschatten bis Schatten",
|
||||||
|
"besonderheiten": "Dekoratives Laub, schneckenanfällig, robust"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "6909f3db83629c03e8adedda",
|
||||||
|
"name": "Sonnenhut",
|
||||||
|
"botanischer_name": "Echinacea purpurea",
|
||||||
|
"standort": "Sonnig",
|
||||||
|
"besonderheiten": "Heilpflanze, zieht Schmetterlinge, schneckenanfällig"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "6909f3dc83629c03e8adeddb",
|
||||||
|
"name": "Tränendes Herz",
|
||||||
|
"botanischer_name": "Lamprocapnos spectabilis",
|
||||||
|
"standort": "Halbschatten",
|
||||||
|
"besonderheiten": "Herzförmige Blüten, romantisch, giftig"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
openapi: 3.0.0
|
||||||
|
info:
|
||||||
|
title: Workshop-Anmeldung API
|
||||||
|
version: 1.0.0
|
||||||
|
servers:
|
||||||
|
- url: http://localhost:8080
|
||||||
|
paths:
|
||||||
|
/registrierung:
|
||||||
|
post:
|
||||||
|
summary: Anmeldung zu einem Workshop
|
||||||
|
description: API für Anmeldedaten eines den Workshops.
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/x-www-form-urlencoded:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/WorkshopForm'
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/WorkshopForm'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Erfolgreiche Anmeldung
|
||||||
|
'400':
|
||||||
|
description: Ungültige Eingabe
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
WorkshopForm:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
vorname:
|
||||||
|
type: string
|
||||||
|
example: "Max"
|
||||||
|
nachname:
|
||||||
|
type: string
|
||||||
|
example: "Mustermann"
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
format: email
|
||||||
|
example: "max@beispiel.de"
|
||||||
|
handy:
|
||||||
|
type: string
|
||||||
|
example: "+491751234567"
|
||||||
|
kurs:
|
||||||
|
type: string
|
||||||
|
example: "Webentwicklung Basics"
|
||||||
|
session:
|
||||||
|
type: string
|
||||||
|
enum: ["vormittag", "nachmittag", "abend", "wochenende"]
|
||||||
|
example: "abend"
|
||||||
|
agb:
|
||||||
|
type: string
|
||||||
|
enum: ["ja", "on"]
|
||||||
|
example: "on"
|
||||||
|
newsletter:
|
||||||
|
type: string
|
||||||
|
enum: ["ja", "on"]
|
||||||
|
example: "ja"
|
||||||
|
equipment:
|
||||||
|
type: string
|
||||||
|
enum: ["ja", "on"]
|
||||||
|
example: "ja"
|
||||||
|
format:
|
||||||
|
type: string
|
||||||
|
enum: ["online", "praesenz"]
|
||||||
|
example: "online"
|
||||||
|
required:
|
||||||
|
- vorname
|
||||||
|
- nachname
|
||||||
|
- email
|
||||||
|
- agb
|
||||||
|
- format
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Book struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Titel string `json:"titel"`
|
||||||
|
Autor string `json:"autor"`
|
||||||
|
Read bool `json:"read"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Library struct {
|
||||||
|
Books []Book `json:"books"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// fügt ein Buch der Library hinzu
|
||||||
|
func (l *Library) Add(titel, autor string) {
|
||||||
|
id := len(l.Books) + 1
|
||||||
|
newBook := Book{ID: id, Titel: titel, Autor: autor, Read: false}
|
||||||
|
l.Books = append(l.Books, newBook)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Markiert ein Buch als gelesen
|
||||||
|
func (l *Library) Read(id int) {
|
||||||
|
for i := range l.Books {
|
||||||
|
if l.Books[i].ID == id {
|
||||||
|
l.Books[i].Read = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listet alle Bücher auf
|
||||||
|
func (l *Library) List() {
|
||||||
|
if len(l.Books) == 0 {
|
||||||
|
fmt.Println("Keine Bücher vorhanden.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, b := range l.Books {
|
||||||
|
status := "ungelesen"
|
||||||
|
if b.Read {
|
||||||
|
status = "gelesen"
|
||||||
|
}
|
||||||
|
fmt.Printf("%d: %s (%s) – %s\n", b.ID, b.Titel, b.Autor, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liste als JSON speichern
|
||||||
|
func (l *Library) Save(filename string) error {
|
||||||
|
|
||||||
|
data, err := json.MarshalIndent(l, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = os.WriteFile(filename, data, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON aus Datei laden
|
||||||
|
func Load(filename string) (*Library, error) {
|
||||||
|
data, err := os.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return &Library{}, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var l Library
|
||||||
|
jsonErr := json.Unmarshal(data, &l)
|
||||||
|
return &l, jsonErr
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"books": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"titel": "Testbuch",
|
||||||
|
"autor": "Testautor",
|
||||||
|
"read": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"titel": "Test2",
|
||||||
|
"autor": "222",
|
||||||
|
"read": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"titel": "Test3",
|
||||||
|
"autor": "EEEE",
|
||||||
|
"read": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
module kommandozeilenprogramm
|
||||||
|
|
||||||
|
go 1.24.5
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
// fmt für ausgaben, os für Kommandozeilenargumente, strconv um strings in ints umzuwandeln
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// prüfen, ob mind. 1 Kommando übergeben wurde
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
fmt.Println("Bitte einen Befehl eingeben")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
filename := "books.json"
|
||||||
|
|
||||||
|
library, err := Load(filename)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Fehler beim Laden der JSON-Datai:", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch os.Args[1] {
|
||||||
|
|
||||||
|
case "add":
|
||||||
|
// Wenn Argumente kleiner 4, Hilfe ausgeben
|
||||||
|
if len(os.Args) < 4 {
|
||||||
|
fmt.Println("Benutze: add / Titel / Autor ")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// sonst titel = Argument 2 und autor = Argument 3
|
||||||
|
titel := os.Args[2]
|
||||||
|
autor := os.Args[3]
|
||||||
|
|
||||||
|
library.Add(titel, autor)
|
||||||
|
|
||||||
|
if err := library.Save(filename); err != nil {
|
||||||
|
fmt.Println("Fehler beim Speichern:", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Buch hinzugefügt.")
|
||||||
|
|
||||||
|
case "list":
|
||||||
|
library.List()
|
||||||
|
|
||||||
|
case "read":
|
||||||
|
if len(os.Args) < 3 {
|
||||||
|
fmt.Println("Benutze: read / ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id, convErr := strconv.Atoi(os.Args[2])
|
||||||
|
if convErr != nil {
|
||||||
|
fmt.Println("Die ID muss eine Zahl sein.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
library.Read(id)
|
||||||
|
|
||||||
|
if err := library.Save(filename); err != nil {
|
||||||
|
fmt.Println("Fehler beim Speichern:", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Buch als gelesen markiert.")
|
||||||
|
|
||||||
|
default:
|
||||||
|
fmt.Println("Kein bekanntes Kommando(add/list/red")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Struct Unmarshal, Felder müssen exportiert sein (Großbuchstabe) und opt. mit json Tag (8.2)
|
||||||
|
|
||||||
|
type WorkshopForm struct {
|
||||||
|
Vorname string `json:"vorname"`
|
||||||
|
Nachname string `json:"nachname"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Handy string `json:"handy"`
|
||||||
|
Kurs string `json:"kurs"`
|
||||||
|
Session string `json:"session"`
|
||||||
|
Agb string `json:"agb"`
|
||||||
|
Newsletter string `json:"newsletter"`
|
||||||
|
Equipment string `json:"equipment"`
|
||||||
|
Format string `json:"format"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler Funktion anlegen
|
||||||
|
// w = Antwort an Browser, r=Anfrage vom Client
|
||||||
|
func workshopHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
// Prüfen auf POST, Fehler falls andere Methode
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// ließt den Body des Requests ein und befüllt FormValue(), sofern keine Fehler auftauchen
|
||||||
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Fehler beim Einlesen des Formulars", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Wenn Felder die als required markiert wurden leer sind: Fehlermeldung
|
||||||
|
vorname := r.FormValue("vorname")
|
||||||
|
if vorname == "" {
|
||||||
|
http.Error(w, "Vorname fehlt", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
nachname := r.FormValue("nachname")
|
||||||
|
if nachname == "" {
|
||||||
|
http.Error(w, "Nachname fehlt", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
email := r.FormValue("email")
|
||||||
|
if email == "" {
|
||||||
|
http.Error(w, "E-Mail fehlt", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handy := r.FormValue("handy")
|
||||||
|
|
||||||
|
// Checkboxen auslesen
|
||||||
|
|
||||||
|
agb := r.FormValue("agb")
|
||||||
|
if agb == "" {
|
||||||
|
http.Error(w, "AGBs müssen akzeptiert werden", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// newsletter und equipment beliben leer, wenn nicht angehakt
|
||||||
|
newsletter := r.FormValue("newsletter")
|
||||||
|
|
||||||
|
equipment := r.FormValue("equipment")
|
||||||
|
|
||||||
|
// Radio Buttons
|
||||||
|
|
||||||
|
format := r.FormValue("format")
|
||||||
|
if format == "" {
|
||||||
|
http.Error(w, "Wählen sie ein Kursformat", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dropdown
|
||||||
|
|
||||||
|
session := r.FormValue("session")
|
||||||
|
if session == "" {
|
||||||
|
http.Error(w, "Wählen sie eine Zeit aus", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Vorname: ", vorname)
|
||||||
|
fmt.Println("Nachname: ", nachname)
|
||||||
|
fmt.Println("E-Mail: : ", email)
|
||||||
|
fmt.Println("Telefon: ", handy)
|
||||||
|
fmt.Println("Newsletter:", newsletter)
|
||||||
|
fmt.Println("Equipment:", equipment)
|
||||||
|
fmt.Println("Format:", format)
|
||||||
|
fmt.Println("Session:", session)
|
||||||
|
|
||||||
|
fmt.Fprintln(w, "POST Request funktioniert")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erweiterung um Json Daten zu empfangen (Aufgabe 8.2)
|
||||||
|
func jsonHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
//Nur POST
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// lesen und unmarshal
|
||||||
|
// Variable für die Daten aus der Form
|
||||||
|
var workshopForm WorkshopForm
|
||||||
|
|
||||||
|
// Prüfung auf gültiges json, falls Fehler 400
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&workshopForm)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Json ungültig", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(workshopForm)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Anfrage an Pfad in HTML /registrierung, worshop Handler wird aufgerufen
|
||||||
|
http.HandleFunc("/registrierung", workshopHandler)
|
||||||
|
http.HandleFunc("/registrierung-json", jsonHandler)
|
||||||
|
|
||||||
|
fmt.Println("Server läuft auf http://localhost:8080")
|
||||||
|
http.ListenAndServe(":8080", nil)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("hello world")
|
||||||
|
|
||||||
|
fmt.Println("go" + "lang")
|
||||||
|
|
||||||
|
fmt.Println("1+1=", 1+1)
|
||||||
|
|
||||||
|
fmt.Println("7.0/3.0 =", 7.0/3.0)
|
||||||
|
|
||||||
|
fmt.Println("True && False", true && false)
|
||||||
|
fmt.Println("True || False", true || false)
|
||||||
|
fmt.Println(!true)
|
||||||
|
|
||||||
|
/* hello world
|
||||||
|
golang
|
||||||
|
1+1= 2
|
||||||
|
7.0/3.0 = 2.3333333333333335
|
||||||
|
True && False false
|
||||||
|
True || False true
|
||||||
|
false */
|
||||||
|
|
||||||
|
var a = "initial"
|
||||||
|
var b, c int = 1, 2
|
||||||
|
var d = true
|
||||||
|
var e int
|
||||||
|
// shorthand für Deklaration + Initialisierung
|
||||||
|
f := "apple"
|
||||||
|
|
||||||
|
fmt.Println(a)
|
||||||
|
fmt.Println(b)
|
||||||
|
fmt.Println(c)
|
||||||
|
fmt.Println(d)
|
||||||
|
fmt.Println(e)
|
||||||
|
fmt.Println(f)
|
||||||
|
|
||||||
|
// initial , 1, 2, true, 0, apple
|
||||||
|
|
||||||
|
fmt.Println("---------------------------------")
|
||||||
|
|
||||||
|
constants()
|
||||||
|
|
||||||
|
fmt.Println("---------------------------------")
|
||||||
|
|
||||||
|
fors()
|
||||||
|
|
||||||
|
fmt.Println("---------------------------------")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const s string = "constant"
|
||||||
|
|
||||||
|
func constants() {
|
||||||
|
|
||||||
|
fmt.Println(s)
|
||||||
|
const n = 500000000
|
||||||
|
const d = 3e20 / n
|
||||||
|
fmt.Println(int64(d))
|
||||||
|
fmt.Println(math.Sin(n))
|
||||||
|
|
||||||
|
// constant,600000000000,-0.28470407323754404
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func fors() {
|
||||||
|
|
||||||
|
i := 1
|
||||||
|
for i <= 3 {
|
||||||
|
fmt.Println(i)
|
||||||
|
i = i + 1
|
||||||
|
//123
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
for j := 0; j < 3; j++ {
|
||||||
|
fmt.Println(j)
|
||||||
|
//0 1 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
for i := range 3 {
|
||||||
|
fmt.Println("range", i)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
for {
|
||||||
|
fmt.Println("loop")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
for n := range 6 {
|
||||||
|
if n%2 == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Println(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
module kekse
|
||||||
|
|
||||||
|
go 1.24.5
|
||||||
|
|
||||||
|
require github.com/google/uuid v1.6.0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// create Cookie HTTP Handler
|
||||||
|
func createHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
//UUID erzeugen
|
||||||
|
id := uuid.NewString()
|
||||||
|
|
||||||
|
// Keks erstellen
|
||||||
|
|
||||||
|
cookie := &http.Cookie{
|
||||||
|
Name: "keks",
|
||||||
|
Value: id,
|
||||||
|
Path: "/",
|
||||||
|
}
|
||||||
|
|
||||||
|
// keks setzten
|
||||||
|
http.SetCookie(w, cookie)
|
||||||
|
|
||||||
|
// Ausgabe Browser
|
||||||
|
fmt.Fprintf(w, "Keks erstellt: %s\n", id)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// show Cookie, falls vorhanden
|
||||||
|
func showHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
cookie, err := r.Cookie("keks")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(w, "Kein Cookie vorhanden")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "Keks gefunden: %s\n", cookie.Value)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete Cookie
|
||||||
|
func deleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
cookie, err := r.Cookie("keks")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Kein Cookie gefunden, löschen nicht möglich", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Maxage - 1 löscht Cookie
|
||||||
|
cookie.MaxAge = -1
|
||||||
|
// schickt neuen Set Cookie Header an Browser
|
||||||
|
http.SetCookie(w, cookie)
|
||||||
|
fmt.Fprintln(w, "Cookie gelöscht")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
// Endpunkte registrieren
|
||||||
|
|
||||||
|
http.HandleFunc("/create-cookie", createHandler)
|
||||||
|
http.HandleFunc("/show-cookie", showHandler)
|
||||||
|
http.HandleFunc("/delete-cookie", deleteHandler)
|
||||||
|
|
||||||
|
fmt.Println("Server läuft auf http://localhost:8080")
|
||||||
|
http.ListenAndServe(":8080", nil)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Struct Unmarshal, Felder müssen exportiert sein (Großbuchstabe) und opt. mit json Tag (8.2)
|
||||||
|
|
||||||
|
type WorkshopForm struct {
|
||||||
|
Vorname string `json:"vorname"`
|
||||||
|
Nachname string `json:"nachname"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Handy string `json:"handy"`
|
||||||
|
Kurs string `json:"kurs"`
|
||||||
|
Session string `json:"session"`
|
||||||
|
Agb string `json:"agb"`
|
||||||
|
Newsletter string `json:"newsletter"`
|
||||||
|
Equipment string `json:"equipment"`
|
||||||
|
Format string `json:"format"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler Funktion anlegen
|
||||||
|
// w = Antwort an Browser, r=Anfrage vom Client
|
||||||
|
func workshopHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
// Prüfen auf POST, Fehler falls andere Methode
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// ließt den Body des Requests ein und befüllt FormValue(), sofern keine Fehler auftauchen
|
||||||
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Fehler beim Einlesen des Formulars", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Wenn Felder die als required markiert wurden leer sind: Fehlermeldung
|
||||||
|
vorname := r.FormValue("vorname")
|
||||||
|
if vorname == "" {
|
||||||
|
http.Error(w, "Vorname fehlt", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
nachname := r.FormValue("nachname")
|
||||||
|
if nachname == "" {
|
||||||
|
http.Error(w, "Nachname fehlt", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
email := r.FormValue("email")
|
||||||
|
if email == "" {
|
||||||
|
http.Error(w, "E-Mail fehlt", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handy := r.FormValue("handy")
|
||||||
|
|
||||||
|
// Checkboxen auslesen
|
||||||
|
|
||||||
|
agb := r.FormValue("agb")
|
||||||
|
if agb == "" {
|
||||||
|
http.Error(w, "AGBs müssen akzeptiert werden", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// newsletter und equipment beliben leer, wenn nicht angehakt
|
||||||
|
newsletter := r.FormValue("newsletter")
|
||||||
|
|
||||||
|
equipment := r.FormValue("equipment")
|
||||||
|
|
||||||
|
// Radio Buttons
|
||||||
|
|
||||||
|
format := r.FormValue("format")
|
||||||
|
if format == "" {
|
||||||
|
http.Error(w, "Wählen sie ein Kursformat", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dropdown
|
||||||
|
|
||||||
|
session := r.FormValue("session")
|
||||||
|
if session == "" {
|
||||||
|
http.Error(w, "Wählen sie eine Zeit aus", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Vorname: ", vorname)
|
||||||
|
fmt.Println("Nachname: ", nachname)
|
||||||
|
fmt.Println("E-Mail: : ", email)
|
||||||
|
fmt.Println("Telefon: ", handy)
|
||||||
|
fmt.Println("Newsletter:", newsletter)
|
||||||
|
fmt.Println("Equipment:", equipment)
|
||||||
|
fmt.Println("Format:", format)
|
||||||
|
fmt.Println("Session:", session)
|
||||||
|
|
||||||
|
fmt.Fprintln(w, "POST Request funktioniert")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erweiterung um Json Daten zu empfangen (Aufgabe 8.2)
|
||||||
|
func jsonHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
//Nur POST
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// lesen und unmarshal
|
||||||
|
// Variable für die Daten aus der Form
|
||||||
|
var workshopForm WorkshopForm
|
||||||
|
|
||||||
|
// Prüfung auf gültiges json, falls Fehler 400
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&workshopForm)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Json ungültig", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(workshopForm)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Anfrage an Pfad in HTML /registrierung, worshop Handler wird aufgerufen
|
||||||
|
http.HandleFunc("/registrierung", workshopHandler)
|
||||||
|
http.HandleFunc("/registrierung-json", jsonHandler)
|
||||||
|
|
||||||
|
fmt.Println("Server läuft auf http://localhost:8080")
|
||||||
|
http.ListenAndServe(":8080", nil)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
openapi: 3.0.0
|
||||||
|
info:
|
||||||
|
title: Workshop-Anmeldung API
|
||||||
|
version: 1.0.0
|
||||||
|
|
||||||
|
servers:
|
||||||
|
- url: http://localhost:8080
|
||||||
|
|
||||||
|
paths:
|
||||||
|
/registrierung:
|
||||||
|
post:
|
||||||
|
summary: Anmeldung zu einem Workshop (Formular)
|
||||||
|
description: API für Anmeldedaten eines Workshops per HTML-Formular.
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/x-www-form-urlencoded:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/WorkshopForm'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Erfolgreiche Anmeldung (Formulardaten angenommen)
|
||||||
|
'400':
|
||||||
|
description: Ungültige Eingabe (fehlende oder fehlerhafte Formulardaten)
|
||||||
|
|
||||||
|
/registrierung-json:
|
||||||
|
post:
|
||||||
|
summary: Anmeldung zu einem Workshop (JSON)
|
||||||
|
description: API für Anmeldedaten eines Workshops im JSON-Format.
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/WorkshopForm'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Erfolgreiche Anmeldung (JSON-Daten zurückgegeben)
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/WorkshopForm'
|
||||||
|
'400':
|
||||||
|
description: Ungültige JSON-Eingabe
|
||||||
|
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
WorkshopForm:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
vorname:
|
||||||
|
type: string
|
||||||
|
example: "Max"
|
||||||
|
nachname:
|
||||||
|
type: string
|
||||||
|
example: "Mustermann"
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
format: email
|
||||||
|
example: "max@beispiel.de"
|
||||||
|
handy:
|
||||||
|
type: string
|
||||||
|
example: "+491751234567"
|
||||||
|
kurs:
|
||||||
|
type: string
|
||||||
|
example: "Webentwicklung Basics"
|
||||||
|
session:
|
||||||
|
type: string
|
||||||
|
enum: ["vormittag", "nachmittag", "abend", "wochenende"]
|
||||||
|
example: "abend"
|
||||||
|
agb:
|
||||||
|
type: string
|
||||||
|
enum: ["ja", "on"]
|
||||||
|
example: "on"
|
||||||
|
newsletter:
|
||||||
|
type: string
|
||||||
|
enum: ["ja", "on"]
|
||||||
|
example: "ja"
|
||||||
|
equipment:
|
||||||
|
type: string
|
||||||
|
enum: ["ja", "on"]
|
||||||
|
example: "ja"
|
||||||
|
format:
|
||||||
|
type: string
|
||||||
|
enum: ["online", "praesenz"]
|
||||||
|
example: "online"
|
||||||
|
required:
|
||||||
|
- vorname
|
||||||
|
- nachname
|
||||||
|
- email
|
||||||
|
- agb
|
||||||
|
- format
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handler Funktion login
|
||||||
|
func loginHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprintln(w, "Sie sind eingeloggt")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler Funktion Logout
|
||||||
|
func logoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprintln(w, "Sie sind ausgeloggt")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
http.HandleFunc("/login", loginHandler)
|
||||||
|
http.HandleFunc("/logout", logoutHandler)
|
||||||
|
|
||||||
|
http.ListenAndServe(":8080", nil)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
########################################
|
||||||
|
# AUFGABE 1 – Routing (/login, /logout)
|
||||||
|
# Server vorher starten im Routing-Ordner:
|
||||||
|
# cd /workspaces/lab-development-imb/web/08/labor/08_loesungen/Routing
|
||||||
|
# go run main.go
|
||||||
|
########################################
|
||||||
|
|
||||||
|
# Login testen
|
||||||
|
curl 'http://localhost:8080/login'
|
||||||
|
|
||||||
|
# Logout testen
|
||||||
|
curl 'http://localhost:8080/logout'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# AUFGABE 2 – JSON-Daten empfangen
|
||||||
|
# Server vorher starten im JSON-Ordner:
|
||||||
|
# cd "/workspaces/lab-development-imb/web/08/labor/08_loesungen/JSONEmpfangen"
|
||||||
|
# go run main.go
|
||||||
|
########################################
|
||||||
|
|
||||||
|
# 2.1 Formular-Endpunkt /registrierung
|
||||||
|
|
||||||
|
# Erfolgreicher POST mit Formulardaten (Status 200)
|
||||||
|
curl -X POST 'http://localhost:8080/registrierung' \
|
||||||
|
-d 'vorname=Max' \
|
||||||
|
-d 'nachname=Mustermann' \
|
||||||
|
-d 'email=max@example.com' \
|
||||||
|
-d 'handy=01701234567' \
|
||||||
|
-d 'kurs=Webentwicklung Basics' \
|
||||||
|
-d 'format=online' \
|
||||||
|
-d 'session=abend' \
|
||||||
|
-d 'agb=on'
|
||||||
|
|
||||||
|
# Fehlerfall provozieren (z.B. Vorname fehlt → Status 400)
|
||||||
|
curl -X POST 'http://localhost:8080/registrierung' \
|
||||||
|
-d 'nachname=Mustermann' \
|
||||||
|
-d 'email=max@example.com' \
|
||||||
|
-d 'format=online' \
|
||||||
|
-d 'session=abend' \
|
||||||
|
-d 'agb=on'
|
||||||
|
|
||||||
|
|
||||||
|
# 2.2 JSON-Endpunkt /registrierung-json
|
||||||
|
|
||||||
|
# Erfolgreicher JSON-POST (Status 200, JSON wird zurückgegeben)
|
||||||
|
curl -X POST 'http://localhost:8080/registrierung-json' \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{
|
||||||
|
"vorname": "Max",
|
||||||
|
"nachname": "Mustermann",
|
||||||
|
"email": "max@example.com",
|
||||||
|
"handy": "01701234567",
|
||||||
|
"kurs": "Webentwicklung Basics",
|
||||||
|
"session": "abend",
|
||||||
|
"agb": "on",
|
||||||
|
"newsletter": "ja",
|
||||||
|
"equipment": "ja",
|
||||||
|
"format": "online"
|
||||||
|
}'
|
||||||
|
|
||||||
|
# Fehlerfall: ungültiges JSON (Status 400, "Json ungültig")
|
||||||
|
curl -X POST 'http://localhost:8080/registrierung-json' \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d 'ich bin kein gültiges json'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# AUFGABE 3 – Cookies mit UUID
|
||||||
|
# Server vorher starten im Cookies-Ordner:
|
||||||
|
# cd /workspaces/lab-development-imb/web/08/labor/08_loesungen/Cookies
|
||||||
|
# go run main.go
|
||||||
|
########################################
|
||||||
|
|
||||||
|
# 3.1 Cookie erzeugen (/create-cookie)
|
||||||
|
# Setzt Cookie "keks=<UUID>" und zeigt die UUID an.
|
||||||
|
# Gleichzeitig speichern wir das Cookie in cookies.txt
|
||||||
|
curl -i --cookie-jar cookies.txt 'http://localhost:8080/create-cookie'
|
||||||
|
|
||||||
|
# 3.2 Cookie anzeigen (/show-cookie)
|
||||||
|
# Liest Cookie "keks" aus cookies.txt und zeigt den Wert an.
|
||||||
|
curl -i --cookie cookies.txt 'http://localhost:8080/show-cookie'
|
||||||
|
|
||||||
|
# 3.3 Cookie löschen (/delete-cookie)
|
||||||
|
# Setzt MaxAge = -1 und löscht den Cookie.
|
||||||
|
curl -i --cookie cookies.txt 'http://localhost:8080/delete-cookie'
|
||||||
|
|
||||||
|
# 3.4 Optional: prüfen, dass er wirklich weg ist
|
||||||
|
curl -i --cookie cookies.txt 'http://localhost:8080/show-cookie'
|
||||||
|
# Erwartet: "Kein Cookie vorhanden"
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
// Produktarray
|
||||||
|
const produkte = [
|
||||||
|
{ produkt: "Joghurt", preis: 2.49 },
|
||||||
|
{ produkt: "Brot", preis: 3.29 },
|
||||||
|
{ produkt: "Käse", preis: 8.99 },
|
||||||
|
{ produkt: "Duschgel", preis: 2.79 }
|
||||||
|
];
|
||||||
|
|
||||||
|
// neues Array
|
||||||
|
|
||||||
|
const rabattProdukte = produkte.map(p => {
|
||||||
|
return {
|
||||||
|
produkt: p.produkt,
|
||||||
|
preis: (p.preis * 0.9).toFixed(2) // Preis um 10% reduziert und gerundet
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ausgabe
|
||||||
|
console.log(rabattProdukte);
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
module db_insert
|
||||||
|
|
||||||
|
go 1.24.5
|
||||||
|
|
||||||
|
require github.com/lib/pq v1.10.9
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
|
|
@ -0,0 +1,166 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
_ "github.com/lib/pq"
|
||||||
|
)
|
||||||
|
|
||||||
|
// INSERT
|
||||||
|
|
||||||
|
type insertHandler int
|
||||||
|
|
||||||
|
func (ihandler insertHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// auf Post prüfen
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Nur Post ist erlaubt", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Formulardaten einlesen
|
||||||
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "gesendetes Formular ungültig", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
name := r.FormValue("name")
|
||||||
|
alter := r.FormValue("alter")
|
||||||
|
hobbies := r.Form["hobby"]
|
||||||
|
|
||||||
|
// alter und name sollten vorhanden sein
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
http.Error(w, "Name fehlt", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if alter == "" {
|
||||||
|
http.Error(w, "Alter fehlt", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hobbies mit Komma separiert zusammenfügen
|
||||||
|
alleHobbies := strings.Join(hobbies, ", ")
|
||||||
|
|
||||||
|
//DB Verbindung öffnen
|
||||||
|
connStr := "user=devuser password=devpass dbname=devdb host=localhost port=5432 sslmode=disable"
|
||||||
|
|
||||||
|
db, err := sql.Open("postgres", connStr)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Datenbank nicht erreichbar", err)
|
||||||
|
http.Error(w, "Server Fehler", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
//Verbindung testen
|
||||||
|
err = db.Ping()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Datenbank nicht erreichbar", err)
|
||||||
|
http.Error(w, "Interner Server Error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("Verbindung erfolgreich hergestellt")
|
||||||
|
|
||||||
|
//Insert
|
||||||
|
|
||||||
|
query := `INSERT INTO personen (name, hobbies, alter) VALUES ($1, $2, $3)`
|
||||||
|
_, err = db.Exec(query, name, alleHobbies, alter)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Fehler beim Einfügen der Daten", err)
|
||||||
|
http.Error(w, "Interner Server Fehler", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(w, "Datensatz erfolgreich eingefügt")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// UPDATE
|
||||||
|
|
||||||
|
type updateHandler int
|
||||||
|
|
||||||
|
func (uhandler updateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// nur POST erlauben
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Nur Post ist erlaubt", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formulardaten einlesen
|
||||||
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "gesendetes Formular ungültig", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
name := r.FormValue("name")
|
||||||
|
alter := r.FormValue("alter")
|
||||||
|
hobbies := r.Form["hobby"]
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
http.Error(w, "Name fehlt", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if alter == "" {
|
||||||
|
http.Error(w, "Alter fehlt", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hobbies zusammenfügen
|
||||||
|
alleHobbies := strings.Join(hobbies, ", ")
|
||||||
|
|
||||||
|
// DB-Verbindung
|
||||||
|
connStr := "user=devuser dbname=devdb host=localhost port=5432 sslmode=disable"
|
||||||
|
db, err := sql.Open("postgres", connStr)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Datenbank nicht erreichbar", err)
|
||||||
|
http.Error(w, "Server Fehler", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
err = db.Ping()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Datenbank nicht erreichbar", err)
|
||||||
|
http.Error(w, "Interner Server Fehler", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update-Query
|
||||||
|
query := `UPDATE personen SET hobbies = $1, alter = $2 WHERE name = $3`
|
||||||
|
res, err := db.Exec(query, alleHobbies, alter, name)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Fehler beim Update", err)
|
||||||
|
http.Error(w, "Interner Server Fehler", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rowsAffected, _ := res.RowsAffected()
|
||||||
|
if rowsAffected == 0 {
|
||||||
|
http.Error(w, "Kein Datensatz mit diesem Namen gefunden", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(w, "Datensatz erfolgreich aktualisiert")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
var ihandler insertHandler
|
||||||
|
var uhandler updateHandler
|
||||||
|
|
||||||
|
http.Handle("/insert", ihandler) // Insert-Endpunkt
|
||||||
|
http.Handle("/update", uhandler) // Update-Endpunkt
|
||||||
|
|
||||||
|
log.Println("Server startet auf http://localhost:8080")
|
||||||
|
log.Fatal(http.ListenAndServe("localhost:8080", nil))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
const zahlen = [38, 0, 226, 384, 111, 500383];
|
||||||
|
|
||||||
|
for (let i = 0; i < zahlen.length; i++){
|
||||||
|
if (zahlen[i] === 0){
|
||||||
|
console.log("Null");
|
||||||
|
} else {
|
||||||
|
console.log(zahlen[i] % 2 === 0 ? "Gerade Zahl" : "Ungerade Zahl")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
const headline = document.getElementById("headline");
|
||||||
|
const adventButton = document.getElementById("adventButton");
|
||||||
|
const imageContainer = document.getElementById("imageContainer")
|
||||||
|
|
||||||
|
adventButton.addEventListener("click", () =>{
|
||||||
|
|
||||||
|
//Überschrift ändern
|
||||||
|
headline.textContent = "Einen fröhlichen ersten Advent";
|
||||||
|
|
||||||
|
//Adventskranz erscheint
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src ="Adventskranz.png";
|
||||||
|
img.alt = "Adventskranz";
|
||||||
|
|
||||||
|
imageContainer.appendChild(img);
|
||||||
|
|
||||||
|
//Button verschwindet
|
||||||
|
adventButton.style.display="none";
|
||||||
|
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<title>Advent</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 id="headline">Alle Jahre wieder...</h1>
|
||||||
|
|
||||||
|
<button id="adventButton">Erste 🕯️ anzünden</button>
|
||||||
|
|
||||||
|
<div id="imageContainer"></div>
|
||||||
|
|
||||||
|
<script src="01.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
After Width: | Height: | Size: 288 KiB |
|
|
@ -0,0 +1,44 @@
|
||||||
|
const helden = {
|
||||||
|
"Chase": "Chase ist auf Spur!",
|
||||||
|
"Marshall": "Ich bin startklar!",
|
||||||
|
"Skye": "Diese Pfote hebt ab!",
|
||||||
|
"Rocky": "Wegwerfen? Kommt nicht in die Tüte!",
|
||||||
|
"Rubble": "Rubble ist zur Stelle!",
|
||||||
|
"Zuma": "Los geht’s ins Wasser!",
|
||||||
|
"Everest": "Eis und Schnee – ich bin bereit!",
|
||||||
|
"Tracker": "Ich höre alles!",
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
const formular = document.getElementById("pawFormular");
|
||||||
|
|
||||||
|
const meldung = document.getElementById("meldung");
|
||||||
|
|
||||||
|
const spruch = document.getElementById("spruch");
|
||||||
|
|
||||||
|
const name = document.getElementById("name");
|
||||||
|
|
||||||
|
|
||||||
|
formular.addEventListener("submit", ev =>{
|
||||||
|
ev.preventDefault(); // verhindert neuladen
|
||||||
|
const eingabe = name.value.trim();
|
||||||
|
|
||||||
|
let gefunden = false;
|
||||||
|
|
||||||
|
for(let h in helden){
|
||||||
|
if(h.toLowerCase() === eingabe.toLowerCase()){
|
||||||
|
gefunden = true;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!eingabe || !gefunden){
|
||||||
|
meldung.textContent = "Bitte gib einen echten Paw Patrol Helden an";
|
||||||
|
spruch.textContent = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
meldung.textContent = "Gute Wahl " + eingabe + " ist dabei!";
|
||||||
|
spruch.textContent = helden[eingabe];
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Paw Patrol - Helfer auf vier Pfoten</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Lieblings-Fellfreund</h1>
|
||||||
|
<form id="pawFormular">
|
||||||
|
<label for="name">Gib hier den Namen ein: </label>
|
||||||
|
<input type="text" id="name" name="fellfreund">
|
||||||
|
<button type="submit">Spruch ausgeben</button>
|
||||||
|
</form>
|
||||||
|
<p id="meldung"></p>
|
||||||
|
<h2 id="spruch"></h2>
|
||||||
|
|
||||||
|
<script src="paw.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<title>Buntes HTML</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Jetzt wird es bunt</h1>
|
||||||
|
<h2>Alles in Blau-Tönen</h2>
|
||||||
|
<span id="dark">Dieser Text ist darkblue.</span>
|
||||||
|
<br>
|
||||||
|
<span id="light">Dieser Text ist lightskyblue.</span>
|
||||||
|
<h2>Alles in Violett-Tönen</h2>
|
||||||
|
<p class="pastell">Dieser Absatz ist pink.</p>
|
||||||
|
<p class="neon">Dieser Absatz ist magenta.</p>
|
||||||
|
<h2>Alles in Grün-Tönen</h2>
|
||||||
|
<p class="frosch">
|
||||||
|
<span class="blatt">Hier ist alles greenyellow.</span>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<span class="blatt">Auch der Bereich zwischen dem Text.</span>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
body{
|
||||||
|
background-color: slateblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1{
|
||||||
|
color: lightcoral;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2{
|
||||||
|
color: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dark{
|
||||||
|
color: darkblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#light{
|
||||||
|
color: lightskyblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pastell{
|
||||||
|
color: pink;
|
||||||
|
}
|
||||||
|
|
||||||
|
.neon{
|
||||||
|
color: magenta;
|
||||||
|
}
|
||||||
|
|
||||||
|
.frosch{
|
||||||
|
color: greenyellow;
|
||||||
|
background-color: greenyellow;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Colors</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<input type="color" id="color" name="color">
|
||||||
|
<label for="color">Farbauswahl</label>
|
||||||
|
<script src="color.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
const colorInput = document.getElementById("color");
|
||||||
|
|
||||||
|
colorInput.addEventListener("input", ev =>{
|
||||||
|
const colorSelected = ev.target.value;
|
||||||
|
|
||||||
|
document.body.style.backgroundColor = colorSelected;
|
||||||
|
|
||||||
|
alert("Ihre Farbwahl: " + colorSelected);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Tagesschau - Maschinenbau-Bilanz</title>
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p class="headline">Schlechte Jahresbilanz</p>
|
||||||
|
<h1>Maschinenbauer warnen die Politik</h1>
|
||||||
|
<p class="meta">Stand: 09.12.2025 12:32 Uhr</p>
|
||||||
|
<p class="summary">Der Branchenverband der Maschinenbauer zieht eine schlechte Jahresbilanz 2025. Der VDMA verlangt Reformen. Sonst
|
||||||
|
würden noch mehr Unternehmen abwandern. Vor allem der Mittelstand leidet unter den Standortbedingungen.</p>
|
||||||
|
<p class="meta">Von Axel J, SWR</p>
|
||||||
|
<p>
|
||||||
|
Julia Schnitzler schaut von ihrem Büro auf die Landstraße, die direkt an ihrem Unternehmen entlang führt. Von
|
||||||
|
hier
|
||||||
|
aus gehen die Spezialanlagen des Herstellers Strassburger Filter in alle Welt. Julia Schnitzler ist hier
|
||||||
|
geschäftsführende Gesellschafterin.
|
||||||
|
</p>
|
||||||
|
<p>"Wir sind aufgrund unserer Expertise international führend, aber es wird immer
|
||||||
|
schwerer. Der Standort Deutschland macht uns zu schaffen. Auch international wird das Geschäftsklima immer
|
||||||
|
rauer",
|
||||||
|
fasst die Geschäftsfrau ein ernüchterndes Jahr zusammen. "Unsere Exporte sind um mehr als zehn Prozent
|
||||||
|
zurückgegangen." Die Firma fertigt Filtrationssysteme für die Bereiche Pharma, Chemie und Kosmetik. Die Exporte
|
||||||
|
gehen vor allem nach Südostasien oder auch nach Nordamerika.
|
||||||
|
</p>
|
||||||
|
<h2>Druck durch chinesische Konkurrenz</h2>
|
||||||
|
<p>Im rheinhessischen Westhofen hat der Betrieb 50 Angestellte. Auch im chinesischen
|
||||||
|
Shanghai arbeiten zwei Spezialisten für das deutsche Unternehmen. China war lange ein starker Markt für den
|
||||||
|
deutschen Filterbauer. "Das hat sich geändert: Die Nachfrage ist zurückgegangen. Es gibt immer mehr chinesische
|
||||||
|
Wettbewerber, die in ihrem heimischen Markt bevorzugt werden", sagt Schnitzler. Qualitativ sei man noch ein
|
||||||
|
gutes
|
||||||
|
Stück voraus. Dafür seien die Chinesen bei den Preisen kaum noch zu schlagen. "Chinesische Firmen haben viel
|
||||||
|
niedrigere Energiepreise. Auch deshalb bieten sie Produkte an, die teils bis zu 75 Prozent billiger als unsere
|
||||||
|
Anlagen sind."</p>
|
||||||
|
<p>Die US-Zölle verschärften die Krise. "Dadurch wird alles noch komplizierter - und unsicherer. Viele
|
||||||
|
unserer Kunden warten erstmal ab. Wer weiß schon, was sich morgen wieder ändert." Pläne zur Verlagerung des
|
||||||
|
Betriebes in die USA habe sie nicht. Aber Schnitzler stellt fest: "Es wird einem in den USA aufgrund der neuen
|
||||||
|
Gesetzeslage inzwischen sehr einfach gemacht, eine Niederlassung zu gründen."
|
||||||
|
</p>
|
||||||
|
<p>Daheim setzen der Firma die
|
||||||
|
Standortbedingungen immer mehr zu. Vor allem die fehlenden Fachkräfte sind ein Problem. Beim Thema
|
||||||
|
Bürokratieabbau
|
||||||
|
schüttelt Julia Schnitzler fast schon resigniert den Kopf. "Alle reden davon, aber es wird immer mehr. Ständig
|
||||||
|
gibt
|
||||||
|
es neue Richtlinien", sagt die geschäftsführende Gesellschafterin "Ein Beispiel: Wenn wir ein bestimmtes Bauteil
|
||||||
|
in
|
||||||
|
einen Filter verbauen, ist das für die Verwaltung eine Kleinigkeit. Liefern wir es aber als Ersatzteil separat
|
||||||
|
aus,
|
||||||
|
entsteht ein enormer Dokumentationsaufwand. Das kostet Zeit, bindet Mitarbeiter und wird immer teurer. Dieses
|
||||||
|
Geld
|
||||||
|
fehlt dann woanders."
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="meta"><span class="source">Quelle</span>: www.tagesschau.de, abgerufen am 9.12.2025</p>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
html {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Open Sans', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2 {
|
||||||
|
color: #005CA9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headline {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: darkgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-style: italic;
|
||||||
|
color: lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
1. Termine:
|
||||||
|
Hintergrundfarbe: keine
|
||||||
|
Schriftfarbe: standard (schwarz)
|
||||||
|
Unterstrichen? nein
|
||||||
|
2. 10k-Lauf:
|
||||||
|
Hintergrundfarbe: orange
|
||||||
|
Schriftfarbe: yellowgreen
|
||||||
|
Unterstrichen? nein
|
||||||
|
3. Elternabend:
|
||||||
|
Hintergrundfarbe: red
|
||||||
|
Schriftfarbe: yellowgreen
|
||||||
|
Unterstrichen? ja!
|
||||||
|
4. Wocheneinkauf:
|
||||||
|
Hintergrundfarbe: orange
|
||||||
|
Schriftfarbe: purple
|
||||||
|
Unterstrichen? nein
|
||||||
|
5. Yoga:
|
||||||
|
Hintergrundfarbe: orange
|
||||||
|
Schriftfarbe: purple
|
||||||
|
Unterstrichen?
|
||||||
|
6. Handball-Training:
|
||||||
|
Hintergrundfarbe: blue
|
||||||
|
Schriftfarbe: white
|
||||||
|
Unterstrichen? nein
|
||||||
|
7. Mathearbeit:
|
||||||
|
Hintergrundfarbe: blue
|
||||||
|
Schriftfarbe: white
|
||||||
|
Unterstrichen? nein
|
||||||
|
8. Fußball-Training:
|
||||||
|
Hintergrundfarbe: blue
|
||||||
|
Schriftfarbe: violet
|
||||||
|
Unterstrichen? nein
|
||||||
|
9. FCB vs. Eintracht:
|
||||||
|
Hintergrundfarbe: orange
|
||||||
|
Schriftfarbe: turquoise
|
||||||
|
Unterstrichen? nein
|
||||||
|
10. Pizza-Tag!:
|
||||||
|
Hintergrundfarbe: keine
|
||||||
|
Schriftfarbe: brown
|
||||||
|
Unterstrichen? nein
|
||||||
|
|
||||||
|
|
||||||
|
*Hintergrundfarbe*, *Schriftfarbe* und *unterstrichen/nicht unterstrichen*
|
||||||
|
After Width: | Height: | Size: 1.3 MiB |
|
|
@ -0,0 +1,115 @@
|
||||||
|
.styled-select {
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.styled-checkbox {
|
||||||
|
appearance: none;
|
||||||
|
width: 1.2rem;
|
||||||
|
height: 1.2rem;
|
||||||
|
border: 1px solid #000000;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
|
||||||
|
/* richtet sich mittig zur Textzeile/Nachbarelementen aus */
|
||||||
|
vertical-align: middle;
|
||||||
|
/* dient als Anker für absolute Kinder */
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.styled-checkbox:checked {
|
||||||
|
background-color: #000000;
|
||||||
|
border-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.styled-checkbox:checked::after {
|
||||||
|
/* Häkchen-Symbol */
|
||||||
|
content: "\2713";
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 1rem;
|
||||||
|
|
||||||
|
|
||||||
|
/* Position relativ zum nächsten positionierten Eltern-Element */
|
||||||
|
position: absolute;
|
||||||
|
/* obere Kante in die Mitte (50%) des Eltern-Elements setzen */
|
||||||
|
top: 50%;
|
||||||
|
/* linke Kante in die Mitte (50%) des Eltern-Elements setzen */
|
||||||
|
left: 50%;
|
||||||
|
/* sich selbst um 50% der eigenen Breite/Höhe zurückschieben → exakt zentriert */
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.styled-radio {
|
||||||
|
appearance: none;
|
||||||
|
width: 1.2rem;
|
||||||
|
height: 1.2rem;
|
||||||
|
border: 1px solid #000;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
|
||||||
|
/* richtet sich mittig zur Textzeile/Nachbarelementen aus */
|
||||||
|
vertical-align: middle;
|
||||||
|
/* dient als Anker für absolute Kinder */
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.styled-radio:checked {
|
||||||
|
border-color: #ffffff;
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.styled-radio:checked::after {
|
||||||
|
content: "";
|
||||||
|
width: 0.5rem;
|
||||||
|
height: 0.5rem;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
/* Position relativ zum nächsten positionierten Eltern-Element */
|
||||||
|
position: absolute;
|
||||||
|
/* obere Kante in die Mitte (50%) des Eltern-Elements setzen */
|
||||||
|
top: 50%;
|
||||||
|
/* linke Kante in die Mitte (50%) des Eltern-Elements setzen */
|
||||||
|
left: 50%;
|
||||||
|
/* sich selbst um 50% der eigenen Breite/Höhe zurückschieben → exakt zentriert */
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: oblique;
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
body{
|
||||||
|
background-image: url(img/background.jpg);
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
margin: 20px;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding-right: 2rem;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
border-color: #1440a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
form{
|
||||||
|
backdrop-filter: blur;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="stylesheet" href="styles_workshop.css">
|
||||||
|
<title>Workshop-Anmeldung</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Workshop-Anmeldung</h1>
|
||||||
|
<form action="https://web-637691723779.europe-west2.run.app/registrierung" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Persönliche Angaben:</legend>
|
||||||
|
<label for="vorname">Vorname:</label><br>
|
||||||
|
<input type="text" name="vorname" id="vorname" placeholder="Vorname" required><br>
|
||||||
|
|
||||||
|
<label for="nachname">Nachname:</label><br>
|
||||||
|
<input type="text" name="nachname" id="nachname" placeholder="Nachname" required><br>
|
||||||
|
|
||||||
|
<label for="email">E-Mail:</label><br>
|
||||||
|
<input type="email" name="email" id="email" autocomplete="email"><br>
|
||||||
|
|
||||||
|
<label for="telefon">Handynummer:</label><br>
|
||||||
|
<input type="tel" name="telefon" id="telefon" pattern="^01[5-7][0-9]{7,10}$"><br><br>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Kursauswahl:</legend>
|
||||||
|
<label for="kurs">Kurs:</label><br>
|
||||||
|
<input type="text" name="kurs" id="kurs" value="Webentwicklung Basics" readonly disabled><br><br>
|
||||||
|
|
||||||
|
<label for="sessions">Bevorzugte Sessions:</label><br>
|
||||||
|
<select id="sessions" name="sessions" class="styled-select" multiple size="4">
|
||||||
|
<option value="vormittag">Vormittag</option>
|
||||||
|
<option value="nachmittag">Nachmittag</option>
|
||||||
|
<option value="abendsession">Abend</option>
|
||||||
|
<option value="wochenende">Wochenende</option>
|
||||||
|
</select><br>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Zusätzliche Optionen:</legend>
|
||||||
|
<input type="checkbox" id="agb" name="agb" class="styled-checkbox" required>
|
||||||
|
<label for="agb">Ich akzeptiere die Teilnahmebedingungen.</label><br>
|
||||||
|
|
||||||
|
<input type="checkbox" id="newsletter" name="newsletter" value="ja" class="styled-checkbox" >
|
||||||
|
<label for="newsletter">Newsletter abonnieren.</label><br>
|
||||||
|
|
||||||
|
<input type="checkbox" id="equipment" name="equipment" value="ja" class="styled-checkbox" >
|
||||||
|
<label for="equipment">Ich benötige spezielles Equipment.</label><br>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Teilnahmeformat:</legend>
|
||||||
|
Format wählen:<br>
|
||||||
|
<input type="radio" id="online" name="format" value="online" class="styled-radio" required>
|
||||||
|
<label for="online">Online</label><br>
|
||||||
|
|
||||||
|
<input type="radio" id="praesenz" name="format" value="praesenz" class="styled-radio">
|
||||||
|
<label for="praesenz">Präsenz</label><br>
|
||||||
|
</fieldset>
|
||||||
|
<br>
|
||||||
|
<input type="submit" value="Jetzt anmelden">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<!DOcTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" method="POST">
|
||||||
|
<title>Anamesebogen</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Anamesebogen</h1>
|
||||||
|
<h2>Bitte ausfüllen</h2>
|
||||||
|
<form>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Persönliches</legend>
|
||||||
|
<label for="name">Name:</label>
|
||||||
|
<input type="text" name="name" id="name" required><br><br>
|
||||||
|
<label for="vorname">Vorname:</label>
|
||||||
|
<input type="text" name="vorname" id="vorname" required><br><br>
|
||||||
|
<label for="gebdatum">Geburtsdatum</label>
|
||||||
|
<input type="date" name="gebdatum" id="gebdatum" required><br><br>
|
||||||
|
<label for="gender">Geschlecht</label>
|
||||||
|
<select name="gender" id="gender" required><br><br>
|
||||||
|
<option value="Weiblich">weiblich</option>
|
||||||
|
<option value="männlich">männlich</option>
|
||||||
|
<option value="divers">divers</option>
|
||||||
|
<option value="ka">keine Angabe</option>
|
||||||
|
</select>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Körperdaten</legend>
|
||||||
|
<label for="gewicht">Gewicht (kg):</label>
|
||||||
|
<input type="number" name="gewicht" id="gewicht"><br><br>
|
||||||
|
<label for="groesse">Größe (cm):</label>
|
||||||
|
<input type="number" name="groesse" id="groesse"><br><br>
|
||||||
|
</fieldset>
|
||||||
|
<button type="submit">Absenden</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ist ein Struct sowas wie eine Klasse in Java ?
|
||||||
|
type Klient struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Vorname string `json:"vorname"`
|
||||||
|
Gebdatum time.Time `json:"gebdatum"`
|
||||||
|
Geschlecht string `json:"gender"`
|
||||||
|
Gewicht int `json:"gewicht"`
|
||||||
|
Groesse int `json:"groesse"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func anameseHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Methode ungültig", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// ist ka dann eine Art Objekt von der Klasse KLient?
|
||||||
|
var k Klient
|
||||||
|
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&k)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Kein gültiges Json", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if k.Name == "" || k.Vorname == "" || k.Geschlecht == "" {
|
||||||
|
http.Error(w, "Pflichtfelder sind leer", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if k.Gebdatum.IsZero() {
|
||||||
|
http.Error(w, "Geburtsdatum fehlt", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if k.Gewicht == 0 || k.Groesse == 0 {
|
||||||
|
warnings = append(warnings, "BMI kann nicht berechnet werden")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erfolg und Warnung zurückgeben wnn genu wird die response varibale genutzt?
|
||||||
|
response := map[string]interface{}{
|
||||||
|
"message:": "Klient erfolgreich angelegt",
|
||||||
|
"warnings": warnings,
|
||||||
|
}
|
||||||
|
|
||||||
|
//ok response habe ich hier gefunden, aber den Rest dieses Codes verstehe ich gerade nich
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
json.NewEncoder(w).Encode(response)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
openapi: 3.0.x
|
||||||
|
info:
|
||||||
|
title: Anamese API
|
||||||
|
version: 1.0.0
|
||||||
|
description: API für Anamesebogen
|
||||||
|
servers:
|
||||||
|
- url: http://localhost:8080
|
||||||
|
paths:
|
||||||
|
/anamese:
|
||||||
|
post:
|
||||||
|
summary: Daten erfassen
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Klient'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Klient erfolgreich angelegt
|
||||||
|
'400':
|
||||||
|
description: Eingaben ungültig
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Klient:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
vorname:
|
||||||
|
type: string
|
||||||
|
gebdatum:
|
||||||
|
type: date
|
||||||
|
gender:
|
||||||
|
type: string
|
||||||
|
enum: [weiblich, männluch, divers, ka]
|
||||||
|
gewicht:
|
||||||
|
type: number
|
||||||
|
groesse:
|
||||||
|
type: number
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- vorname
|
||||||
|
- gebdatum
|
||||||
|
- gender
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
openapi: 3.0.x
|
||||||
|
info:
|
||||||
|
title: Wichteln
|
||||||
|
version: 1.0.0
|
||||||
|
description: API für Wichtelaktion
|
||||||
|
servers:
|
||||||
|
- url: http://localhost:8080
|
||||||
|
paths:
|
||||||
|
/wichtelaktion:
|
||||||
|
post:
|
||||||
|
summary: Aktion anlegen
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
adminEmail:
|
||||||
|
type: string
|
||||||
|
format: email
|
||||||
|
startDate:
|
||||||
|
type: string
|
||||||
|
format: date
|
||||||
|
endDate:
|
||||||
|
type: string
|
||||||
|
format: date
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- adminEmail
|
||||||
|
- startDate
|
||||||
|
- endDate
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Aktion erfolgreich erstellt
|
||||||
|
'400':
|
||||||
|
description: Aktion konnte nicht erstellt werden
|
||||||
|
/wichtelaktion/{id}/invite:
|
||||||
|
post:
|
||||||
|
summary: Teilnehmer einladen und Tokens generieren
|
||||||
|
parameters:
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
emails:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
reqired:
|
||||||
|
- emails
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Teilnehmer erfolgreich eingeladen
|
||||||
|
'400':
|
||||||
|
description: Teilnehmer konnten nicht eingeladen werden
|
||||||
|
/wichtelaktion/{id}/:
|
||||||
|
put:
|
||||||
|
summary: Wichtelaktion bearbeiten
|
||||||
|
parameters:
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responseBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||