diff --git a/assets/css/custom.css b/assets/css/custom.css
index e69de29..a9b6183 100644
--- a/assets/css/custom.css
+++ b/assets/css/custom.css
@@ -0,0 +1,215 @@
+
+body {
+ background: #f0f4f8;
+ color: #1b1b2f;
+ font-family: 'Gill Sans', 'Gill Sans MT', 'Calibri', 'Trebuchet MS', sans-serif;
+ line-height: 1.6;
+ margin-bottom: 1rem;
+ padding: 0;
+}
+
+/* Navigation Styles */
+.navbar {
+ background: linear-gradient(90deg, #1b1b2f, #4a6fa5)
+}
+.navbar .nav-link {
+ color: #fff;
+ transition: color 0.3s, background-color 0.3s;
+ margin: 0 5px;
+}
+.navbar .nav-link:hover {
+ background-color: #ffd166;
+ color: #1b1b2f;
+ border-radius: 6px;
+ padding: 5px 10px;
+}
+
+.navbar .nav-link.active {
+ background-color: #ffd166;
+ color: #1b1b2f;
+ font-weight: bold;
+ border-radius: 6px;
+ padding: 5px 10px;
+}
+
+/* Main content styles */
+.container-dashboard {
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: 20px;
+ padding: 20px;
+}
+/* Cards/Scores styles */
+.container > div:not(.modal) {
+ background-color:#ffffff;
+ border-radius: 12px;
+ box-shadow: 0 4px 15px rgba(0,0,0,0.1);
+ padding: 25px;
+ font-size: 30px;
+ flex: 1 1 100%;
+ text-align: center;
+ transition: transform 0.3s, box-shadow 0.3s;
+}
+.container > div:not(.modal):hover {
+ transform: translateY(-5px);
+ box-shadow: 0 10px 25px rgba(0,0,0,0.2);
+}
+
+/* Keep Bootstrap modal sizing/layout intact */
+#password-modal {
+ padding: 0;
+ background: transparent;
+ box-shadow: none;
+ border-radius: 0;
+ font-size: 1rem;
+}
+
+#password-modal .modal-dialog {
+ max-width: 560px;
+}
+
+/* Überschriften und Abstände */
+h1, h2, h3, h4, h5, h6 {
+ margin-top: 1rem;
+ margin-bottom: 20px;
+ color: #1b1b2f;
+}
+p {
+ margin-top: 0.5rem;
+ margin-bottom: 1rem;
+ color: #333;
+}
+/* Button Styles */
+.btn {
+ background-color: #4a6fa5;
+ color: #fff;
+ border: none;
+ padding: 10px 20px;
+ border-radius: 6px;
+ cursor: pointer;
+ font-size: 16px;
+ transition: background-color 0.3s;
+}
+.btn:hover {
+ background-color: #2b4a7c;
+}
+.btn-danger {
+ background-color: #a84848;
+ color: #fff;
+ border: none;
+ padding: 10px 20px;
+ border-radius: 6px;
+ cursor: pointer;
+ font-size: 16px;
+ transition: background-color 0.3s;
+}
+.btn-danger:hover {
+ background-color: #8a3b3b;
+}
+#page-wrapper {
+ display: flex;
+ min-height: 100vh;
+ font-family: 'Segoe UI', sans-serif;
+}
+/* Sidebar Styles */
+#sidebar {
+ width: 240px;
+ min-height: auto;
+ background: linear-gradient(180deg, #1b1b2f, #4a6fa5);
+ color: white;
+ padding: 25px;
+}
+#sidebar .nav-link {
+ margin: 0.5rem 0;
+ transition: color 0.3s, background-color 0.3s;
+ color: white;
+ padding: 5px 10px;
+ border-radius: 6x;
+}
+#sidebar .nav-link:hover {
+ color: #1b1b2f;
+ border-radius: 6px;
+}
+#sidebar .nav-link.active {
+ color: #1b1b2f;
+ font-weight: bold;
+ background-color: #ffd166;
+ border-radius: 6px;
+ padding: 5px 10px;
+}
+#logo-img {
+ max-width: 500px;
+ width: 100%;
+ height: auto;
+}
+#main-area {
+ flex: 1;
+ background: #f3f4f6;
+ display: flex;
+ flex-direction: column;
+}
+/* Topbar Styles */
+#topbar {
+ height: 70px;
+ background: white;
+ padding: 0px 30px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+}
+#main-content {
+ background-color: #f0f4f8;
+ padding: 30px;
+}
+/* Card Styles */
+.card {
+ background: white;
+ border-radius: 12px;
+ box-shadow: 0 5px 15px rgba(0,0,0,0.08);
+ padding: 25px;
+ margin-bottom: 20px;
+}
+.card h2 {
+ margin-bottom: 10px;
+}
+
+/* Responsive Styles */
+@media (max-width: 768px) {
+ body {
+ font-size: 0.9rem;
+ }
+ .container > div:not(.modal) {
+ flex: 1 1 calc(50% - 40px);
+ }
+ #page-wrapper {
+ flex-direction: column;
+ }
+ #sidebar {
+ width: 100%;
+ display: flex;
+ overflow-x: auto;
+ }
+ #sidebar .nav-link {
+ flex: 0 0 auto;
+ margin: 0 10px;
+ }
+}
+@media (min-width: 1200px) {
+ body {
+ font-size: 1.1rem;
+ }
+ .container > div:not(.modal) {
+ flex: 1 1 calc(25% - 40px);
+ }
+ p.columns{
+ column-count: 2;
+ column-gap: 2rem;
+ }
+ #sidebar .nav-link {
+ flex: 0 0 auto;
+ margin: 0 15px;
+ }
+
+}
+
diff --git a/image/Logo_loremIpsum.png b/image/Logo_loremIpsum.png
new file mode 100644
index 0000000..2e2b42c
Binary files /dev/null and b/image/Logo_loremIpsum.png differ
diff --git a/image/icon_l.png b/image/icon_l.png
new file mode 100644
index 0000000..84ae9f7
Binary files /dev/null and b/image/icon_l.png differ
diff --git a/image/icon_loremIpsum.png b/image/icon_loremIpsum.png
new file mode 100644
index 0000000..012b05d
Binary files /dev/null and b/image/icon_loremIpsum.png differ
diff --git a/image/icon_loremIpsum2.png b/image/icon_loremIpsum2.png
new file mode 100644
index 0000000..df644c9
Binary files /dev/null and b/image/icon_loremIpsum2.png differ
diff --git a/index.html b/index.html
index 5ea1fd1..d9b72dd 100644
--- a/index.html
+++ b/index.html
@@ -1,21 +1,65 @@
- My Web Page
+
+ Lorem Ipsum - Das Spiel
+
+
+
- Hello From Main Page
- Go to Main Page
- Go to Second Page
-
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/js/login.js b/js/login.js
new file mode 100644
index 0000000..73aaf38
--- /dev/null
+++ b/js/login.js
@@ -0,0 +1,288 @@
+(function () {
+ const AUTH_STORAGE_KEY = "loremIpsumAuth";
+
+ function readAuth() {
+ const raw = localStorage.getItem(AUTH_STORAGE_KEY);
+ if (!raw) {
+ return null;
+ }
+
+ try {
+ const parsed = JSON.parse(raw);
+ if (!parsed.username || !parsed.password) {
+ return null;
+ }
+ return parsed;
+ } catch {
+ return null;
+ }
+ }
+
+ function saveAuth(username, password) {
+ localStorage.setItem(
+ AUTH_STORAGE_KEY,
+ JSON.stringify({ username: username, password: password }),
+ );
+ }
+
+ function clearAuth() {
+ localStorage.removeItem(AUTH_STORAGE_KEY);
+ }
+
+ function updateHeaderUsername() {
+ const usernameDisplay = document.getElementById("username-display");
+ const navbarLogin = document.getElementById("navbar-login");
+ const auth = readAuth();
+
+ if (usernameDisplay) {
+ usernameDisplay.textContent = auth ? "User: " + auth.username : "User: Guest";
+ }
+
+ if (navbarLogin) {
+ navbarLogin.textContent = auth ? auth.username : "Login / Registrieren";
+ }
+ }
+
+ function setFeedback(message, type) {
+ const feedback = document.getElementById("auth-feedback");
+ if (!feedback) {
+ return;
+ }
+
+ feedback.className = "alert alert-" + type;
+ feedback.textContent = message;
+ feedback.classList.remove("d-none");
+ }
+
+ function updateSessionBox() {
+ const sessionText = document.getElementById("current-session-text");
+ const logoutButton = document.getElementById("logout-button");
+ const deleteAccountButton = document.getElementById("delete-account-button");
+ const currentSessionBox = document.getElementById("current-session-box");
+ const authFormsRow = document.getElementById("auth-forms-row");
+
+ if (!sessionText || !logoutButton || !deleteAccountButton || !currentSessionBox || !authFormsRow) {
+ return;
+ }
+
+ const auth = readAuth();
+ if (auth) {
+ sessionText.textContent = "Eingeloggt als " + auth.username + ".";
+ logoutButton.disabled = false;
+ deleteAccountButton.disabled = false;
+ currentSessionBox.classList.remove("d-none");
+ authFormsRow.classList.add("d-none");
+ } else {
+ sessionText.textContent = "Nicht eingeloggt.";
+ logoutButton.disabled = true;
+ deleteAccountButton.disabled = true;
+ currentSessionBox.classList.add("d-none");
+ authFormsRow.classList.remove("d-none");
+ }
+ }
+
+ function getUserService() {
+ if (!window.config || !window.UserService) {
+ return null;
+ }
+
+ return new window.UserService(window.config);
+ }
+
+ async function handleLoginSubmit(event) {
+ event.preventDefault();
+
+ const userService = getUserService();
+ if (!userService) {
+ setFeedback("User-Service konnte nicht geladen werden.", "danger");
+ return;
+ }
+
+ const usernameInput = document.getElementById("login-username");
+ const passwordInput = document.getElementById("login-password");
+ const username = usernameInput.value.trim();
+ const password = passwordInput.value.trim();
+
+ if (!username || !password) {
+ setFeedback("Bitte Username und Passwort eingeben.", "warning");
+ return;
+ }
+
+ const result = await userService.getUser(username, password);
+ if (result.ok) {
+ saveAuth(username, password);
+ setFeedback("Login erfolgreich.", "success");
+ updateSessionBox();
+ updateHeaderUsername();
+ setTimeout(function() {
+ if (typeof window.loadPage === "function") {
+ window.loadPage("home", "nav-home");
+ }
+ }, 500);
+ return;
+ }
+
+ if (result.status === 401) {
+ setFeedback("Login fehlgeschlagen: Username oder Passwort ist falsch.", "danger");
+ return;
+ }
+
+ setFeedback("Login fehlgeschlagen (Status " + result.status + ").", "danger");
+ }
+
+ async function handleRegisterSubmit(event) {
+ event.preventDefault();
+
+ const userService = getUserService();
+ if (!userService) {
+ setFeedback("User-Service konnte nicht geladen werden.", "danger");
+ return;
+ }
+
+ const usernameInput = document.getElementById("register-username");
+ const username = usernameInput.value.trim();
+
+ if (!username) {
+ setFeedback("Bitte einen Username eingeben.", "warning");
+ return;
+ }
+
+ const result = await userService.postUser(username);
+ if (result.ok && result.body) {
+ const createdName = result.body.name || username;
+ const createdPassword = result.body.password || "";
+
+ saveAuth(createdName, createdPassword);
+ updateSessionBox();
+ updateHeaderUsername();
+
+ // Modal mit Daten füllen und anzeigen
+ const modalUsername = document.getElementById("modal-username");
+ const modalPassword = document.getElementById("modal-password");
+ if (modalUsername) modalUsername.textContent = createdName;
+ if (modalPassword) modalPassword.textContent = createdPassword;
+
+ const passwordModalElement = document.getElementById("password-modal");
+ if (passwordModalElement) {
+ const passwordModal = new window.bootstrap.Modal(passwordModalElement);
+
+ // Listener für Modals-Schließen: zur Startseite navigieren
+ passwordModalElement.addEventListener("hidden.bs.modal", function handleClose() {
+ if (typeof window.loadPage === "function") {
+ window.loadPage("home", "nav-home");
+ }
+ passwordModalElement.removeEventListener("hidden.bs.modal", handleClose);
+ });
+
+ passwordModal.show();
+ } else {
+ // Fallback wenn Modal nicht gefunden
+ setFeedback(
+ "Account erstellt. Username: " + createdName + ", Passwort: " + createdPassword,
+ "success",
+ );
+ setTimeout(function() {
+ if (typeof window.loadPage === "function") {
+ window.loadPage("home", "nav-home");
+ }
+ }, 1500);
+ }
+
+ const loginUsernameInput = document.getElementById("login-username");
+ const loginPasswordInput = document.getElementById("login-password");
+ if (loginUsernameInput && loginPasswordInput) {
+ loginUsernameInput.value = createdName;
+ loginPasswordInput.value = createdPassword;
+ }
+
+ return;
+ }
+
+ if (result.status === 400) {
+ const errorMessage = result.body && result.body.message
+ ? result.body.message
+ : "Dieser Username existiert bereits.";
+ setFeedback(errorMessage, "danger");
+ return;
+ }
+
+ setFeedback(
+ "Account konnte nicht erstellt werden (Status " + result.status + ").",
+ "danger",
+ );
+ }
+
+ function handleLogout() {
+ clearAuth();
+ setFeedback("Du wurdest ausgeloggt.", "info");
+ updateSessionBox();
+ updateHeaderUsername();
+ }
+
+ async function handleDeleteAccount() {
+ const auth = readAuth();
+ if (!auth) {
+ setFeedback("Du bist nicht eingeloggt.", "warning");
+ return;
+ }
+
+ const wantsDelete = window.confirm(
+ "Möchtest du den Account \"" + auth.username + "\" wirklich löschen?",
+ );
+ if (!wantsDelete) {
+ return;
+ }
+
+ const userService = getUserService();
+ if (!userService) {
+ setFeedback("User-Service konnte nicht geladen werden.", "danger");
+ return;
+ }
+
+ const result = await userService.deleteUser(auth.username, auth.password);
+ if (result.ok) {
+ clearAuth();
+ updateSessionBox();
+ updateHeaderUsername();
+ setFeedback("Account wurde gelöscht.", "success");
+ return;
+ }
+
+ if (result.status === 401) {
+ setFeedback("Account konnte nicht gelöscht werden: nicht autorisiert.", "danger");
+ return;
+ }
+
+ setFeedback(
+ "Account konnte nicht gelöscht werden (Status " + result.status + ").",
+ "danger",
+ );
+ }
+
+ function initLoginPage() {
+ const loginForm = document.getElementById("login-form");
+ const registerForm = document.getElementById("register-form");
+ const logoutButton = document.getElementById("logout-button");
+ const deleteAccountButton = document.getElementById("delete-account-button");
+
+ if (!loginForm || !registerForm || !logoutButton || !deleteAccountButton) {
+ return;
+ }
+
+ loginForm.addEventListener("submit", handleLoginSubmit);
+ registerForm.addEventListener("submit", handleRegisterSubmit);
+ logoutButton.addEventListener("click", handleLogout);
+ deleteAccountButton.addEventListener("click", handleDeleteAccount);
+
+ updateSessionBox();
+ updateHeaderUsername();
+ }
+
+ window.initLoginPage = initLoginPage;
+ window.AppAuth = {
+ getAuth: readAuth,
+ clearAuth: clearAuth,
+ };
+
+ document.addEventListener("DOMContentLoaded", updateHeaderUsername);
+})();
diff --git a/js/navigation.js b/js/navigation.js
new file mode 100644
index 0000000..6111ac0
--- /dev/null
+++ b/js/navigation.js
@@ -0,0 +1,49 @@
+document.addEventListener("DOMContentLoaded", () => {
+ function setActiveMenu(id) {
+ //Alle Sidebar-Links zurücksetzen
+ document.querySelectorAll("#sidebar .nav-link").forEach(link => link.classList.remove("active"));
+ // Alle Navbar-Links zurücksetzen
+ document.querySelectorAll(".navbar-nav .nav-link").forEach(link => link.classList.remove("active"));
+
+ //Aktiven Link setzen
+ const activeLink = document.getElementById(id);
+ if (activeLink) activeLink.classList.add("active");
+ }
+ window.loadPage = function loadPage(page, menuId) {
+ fetch("pages/" + page + ".html")
+ .then(response => {
+ if (!response.ok) {
+ throw new Error("HTTP " + response.status);
+ }
+ return response.text();
+ })
+ .then(data => {
+ document.getElementById("main-content").innerHTML = data;
+ setActiveMenu(menuId);
+ if (page === "login" && typeof window.initLoginPage === "function") {
+ window.initLoginPage();
+ }
+ })
+ .catch(error => {
+ console.error("Fehler beim Laden von " + page + ":", error);
+ document.getElementById("main-content").innerHTML = "Fehler beim Laden der Seite: " + error.message + "
";
+ });
+ };
+
+ const navHome = document.getElementById("nav-home");
+ const navPlay = document.getElementById("nav-play");
+ const navMyScores = document.getElementById("nav-my-scores");
+ const navLeaderboard = document.getElementById("nav-leaderboard");
+ const navbarLogin = document.getElementById("navbar-login");
+ const navbarMessages = document.getElementById("navbar-messages");
+
+ if (navHome) navHome.onclick = (e) => { e.preventDefault(); loadPage("home", "nav-home"); };
+ if (navPlay) navPlay.onclick = (e) => { e.preventDefault(); loadPage("play", "nav-play"); };
+ if (navMyScores) navMyScores.onclick = (e) => { e.preventDefault(); loadPage("scores", "nav-my-scores"); };
+ if (navLeaderboard) navLeaderboard.onclick = (e) => { e.preventDefault(); loadPage("leaderboard", "nav-leaderboard"); };
+ if (navbarLogin) navbarLogin.onclick = (e) => { e.preventDefault(); loadPage("login", "navbar-login"); };
+ if (navbarMessages) navbarMessages.onclick = (e) => { e.preventDefault(); loadPage("messages", "navbar-messages"); };
+
+ //Startseite laden
+ loadPage("home", "nav-home");
+});
\ No newline at end of file
diff --git a/pages/home.html b/pages/home.html
new file mode 100644
index 0000000..731056c
--- /dev/null
+++ b/pages/home.html
@@ -0,0 +1,8 @@
+
+
Willkommen beim Lorem Ipsum Game
+
Teste deine Fähigkeiten im Umgang mit Lorem Ipsum Texten! Je schneller und genauer du bist, desto höher ist dein Score.
+ Viel Spaß beim Spielen!
+
+
Wähle eine Option aus der Navigation, um zu starten.
+
+
\ No newline at end of file
diff --git a/pages/leaderboard.html b/pages/leaderboard.html
new file mode 100644
index 0000000..7fbb136
--- /dev/null
+++ b/pages/leaderboard.html
@@ -0,0 +1,5 @@
+
+
Leaderboard
+
+
Hier kannst du die besten Spieler und ihre Scores sehen.
+
diff --git a/pages/login.html b/pages/login.html
new file mode 100644
index 0000000..3f0b3ae
--- /dev/null
+++ b/pages/login.html
@@ -0,0 +1,73 @@
+
+
+
Account
+
+
+
+
+
+
Aktuelle Sitzung
+
Nicht eingeloggt.
+
+ Logout
+ Account löschen
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Username:
+ Passwort:
+
+
Bitte speichere das Passwort. Du benötigst es zum Einloggen.
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/messages.html b/pages/messages.html
new file mode 100644
index 0000000..cf65402
--- /dev/null
+++ b/pages/messages.html
@@ -0,0 +1,6 @@
+
+
Nachrichten
+
+
Hier kannst du deine Nachrichten ansehen und verwalten.
+
+
\ No newline at end of file
diff --git a/pages/play.html b/pages/play.html
new file mode 100644
index 0000000..a28877a
--- /dev/null
+++ b/pages/play.html
@@ -0,0 +1,7 @@
+
+
Spiel Starten
+
Hier kannst du das Spiel starten. Viel Erfolg!
+
+
Spiel starten
+
+
\ No newline at end of file
diff --git a/pages/scores.html b/pages/scores.html
new file mode 100644
index 0000000..78eb95e
--- /dev/null
+++ b/pages/scores.html
@@ -0,0 +1,6 @@
+
+
Meine Scores
+
+
Hier kannst du deine bisherigen Scores einsehen.
+
+
\ No newline at end of file