/** * 🔐 AUTHENTIFIZIERUNG, USER MANAGEMENT & SINGLE-USER-MODUS 🔐 * ============================================================== * Unterstützt: * 1. 🚀 Single-User Gast-Modus (1-Klick Start ohne Registrierung, 100% offline-fähig) * 2. 🎓 Solo-Selbstlerner Konto (Cloud-Save, Streaks, XP & Zertifikate ohne Klassenbindung) * 3. 🏫 Schulklassen-Modus (Schüler & Lehrer mit Lernmatrix) */ (function () { function escapeHtml(text) { if (!text) return ""; return String(text).replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); } window.AUTH = { token: localStorage.getItem("auth_token") || null, user: JSON.parse(localStorage.getItem("auth_user") || "null"), // 1. GAST / SINGLE-USER MODUS (Sofort loslegen ohne Login) startGuestSoloMode() { const guestUser = { id: "solo_guest", name: "Solo-Entwickler", email: "gast@lokal", role: "solo", xp: 0, level: 1, isGuest: true }; this.setSession("guest_token_" + Date.now(), guestUser); if (document.getElementById("auth-modal-overlay")) { document.getElementById("auth-modal-overlay").remove(); } this.updateUI(); return guestUser; }, // 2. REGISTRIERUNG async register(name, email, password, role = "solo") { 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 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 }; } }, // 3. LOGIN 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) { const mockUser = { id: 1, name: email.split("@")[0], email, role: "solo", xp: 150, level: 2 }; this.setSession("offline_token", mockUser); return { success: true, user: mockUser, offline: true }; } }, 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 || (this.user && this.user.isGuest)) return this.user; 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"); const soloModeBadge = document.getElementById("solo-mode-indicator"); if (this.user) { if (userBadge) { userBadge.style.display = "inline-flex"; const roleLabel = this.user.role === "teacher" ? "👨‍🏫 Lehrer" : (this.user.role === "solo" ? "🎓 Solo" : "🎒 Schüler"); userBadge.innerHTML = `👤 ${escapeHtml(this.user.name)} (${roleLabel}) ${this.user.xp || 0} XP`; } if (loginBtn) loginBtn.style.display = "none"; if (registerBtn) { registerBtn.innerText = this.user.isGuest ? "Konto anlegen" : "Abmelden"; registerBtn.onclick = (e) => { e.preventDefault(); if (this.user.isGuest) { window.openAuthModal("register"); } else { this.logout(); } }; } if (teacherLink) { teacherLink.style.display = this.user.role === "teacher" ? "inline-flex" : "none"; } if (soloModeBadge) { soloModeBadge.style.display = (this.user.role === "solo" || this.user.isGuest) ? "inline-block" : "none"; } } 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"; if (soloModeBadge) soloModeBadge.style.display = "inline-block"; } } }; // Auth Modal UI mit Single-User & Gast-Option 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 = `

🔑 Anmelden

Speichere deinen Code, XP und Zertifikate dauerhaft in der Cloud.

🚀 Single-User Modus (Sofort starten)

Lerne im eigenen Tempo – ohne Registrierung, ohne Klasse.

ODER MIT KONTO
Noch kein Konto? Jetzt registrieren →
`; document.body.appendChild(modal); } const titleEl = document.getElementById("auth-modal-title"); const nameField = document.getElementById("auth-field-name"); const roleField = document.getElementById("auth-field-role"); const submitBtn = document.getElementById("auth-submit-btn"); const toggleLink = document.getElementById("auth-toggle-mode"); const errorMsg = document.getElementById("auth-error-msg"); const form = document.getElementById("auth-form"); let isRegister = mode === "register"; function updateModalMode() { if (isRegister) { titleEl.innerText = "✨ Neues Konto erstellen"; nameField.style.display = "block"; roleField.style.display = "block"; submitBtn.innerText = "Konto registrieren"; toggleLink.innerText = "Bereits registriert? Hier anmelden →"; } else { titleEl.innerText = "🔑 Anmelden"; nameField.style.display = "none"; roleField.style.display = "none"; submitBtn.innerText = "Anmelden"; toggleLink.innerText = "Noch kein Konto? Jetzt registrieren →"; } errorMsg.style.display = "none"; } updateModalMode(); toggleLink.onclick = (e) => { e.preventDefault(); isRegister = !isRegister; updateModalMode(); }; form.onsubmit = async (e) => { e.preventDefault(); errorMsg.style.display = "none"; const email = document.getElementById("auth-input-email").value.trim(); const password = document.getElementById("auth-input-password").value; const name = document.getElementById("auth-input-name")?.value.trim() || email.split("@")[0]; const role = document.getElementById("auth-select-role")?.value || "solo"; submitBtn.disabled = true; submitBtn.innerText = "Bitte warten..."; let result; if (isRegister) { result = await window.AUTH.register(name, email, password, role); } else { result = await window.AUTH.login(email, password); } submitBtn.disabled = false; submitBtn.innerText = isRegister ? "Konto registrieren" : "Anmelden"; if (result.success) { document.getElementById("auth-modal-overlay")?.remove(); alert(`Willkommen, ${result.user.name}! 🚀`); } else { errorMsg.innerText = result.error || "Ein Fehler ist aufgetreten"; errorMsg.style.display = "block"; } }; }; document.addEventListener("DOMContentLoaded", () => { window.AUTH.updateUI(); window.AUTH.fetchMe(); }); })();