/** * 🔐 AUTHENTIFIZIERUNG & USER MANAGEMENT 🔐 * ========================================== * Verarbeitet Login, Registrierung, JWT-Tokens und Lehrer-Klassenzuweisung. * Mit automatischem Offline-Fallback (LocalStorage), falls kein Server läuft. */ (function () { window.AUTH = { token: localStorage.getItem("auth_token") || null, user: JSON.parse(localStorage.getItem("auth_user") || "null"), async register(name, email, password, role = "student") { try { const res = await fetch("/api/auth/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name, email, password, role }) }); const data = await res.json(); if (!res.ok) throw new Error(data.error || "Registrierung fehlgeschlagen"); this.setSession(data.token, data.user); return { success: true, user: data.user }; } catch (err) { // Fallback für statische Offline-Nutzung if (err.message.includes("Failed to fetch")) { const mockUser = { id: Date.now(), name, email, role, xp: 0, level: 1 }; this.setSession("offline_token_" + Date.now(), mockUser); return { success: true, user: mockUser, offline: true }; } return { success: false, error: err.message }; } }, async login(email, password) { try { const res = await fetch("/api/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }) }); const data = await res.json(); if (!res.ok) throw new Error(data.error || "Anmeldung fehlgeschlagen"); this.setSession(data.token, data.user); return { success: true, user: data.user }; } catch (err) { if (err.message.includes("Failed to fetch")) { const mockUser = { id: 1, name: email.split("@")[0], email, role: "student", xp: 150, level: 2 }; this.setSession("offline_token", mockUser); return { success: true, user: mockUser, offline: true }; } return { success: false, error: err.message }; } }, logout() { this.token = null; this.user = null; localStorage.removeItem("auth_token"); localStorage.removeItem("auth_user"); window.location.reload(); }, setSession(token, user) { this.token = token; this.user = user; localStorage.setItem("auth_token", token); localStorage.setItem("auth_user", JSON.stringify(user)); this.updateUI(); }, async fetchMe() { if (!this.token) return null; try { const res = await fetch("/api/auth/me", { headers: { Authorization: `Bearer ${this.token}` } }); if (res.ok) { const data = await res.json(); this.user = data.user; localStorage.setItem("auth_user", JSON.stringify(data.user)); this.updateUI(); return data.user; } } catch (e) {} return this.user; }, updateUI() { const userBadge = document.getElementById("nav-auth-user"); const loginBtn = document.getElementById("nav-btn-login"); const registerBtn = document.getElementById("nav-btn-register"); const teacherLink = document.getElementById("nav-teacher-link"); if (this.user) { if (userBadge) { userBadge.style.display = "inline-flex"; userBadge.innerHTML = `👤 ${this.user.name} ${this.user.xp || 0} XP`; } if (loginBtn) loginBtn.style.display = "none"; if (registerBtn) { registerBtn.innerText = "Abmelden"; registerBtn.onclick = (e) => { e.preventDefault(); this.logout(); }; } if (teacherLink && this.user.role === "teacher") { teacherLink.style.display = "inline-flex"; } } else { if (userBadge) userBadge.style.display = "none"; if (loginBtn) loginBtn.style.display = "inline-flex"; if (registerBtn) { registerBtn.innerText = "Konto erstellen"; registerBtn.onclick = () => window.openAuthModal("register"); } if (teacherLink) teacherLink.style.display = "none"; } } }; // Auth Modal UI window.openAuthModal = function (mode = "login") { let modal = document.getElementById("auth-modal-overlay"); if (!modal) { modal = document.createElement("div"); modal.id = "auth-modal-overlay"; modal.className = "certificate-overlay"; modal.innerHTML = `
Melde dich an, um deinen Code und deine XP in der Cloud zu speichern.