| <!DOCTYPE html> |
| <html lang="de"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>NoahsKI - Einstellungen ⚙️</title> |
| <style> |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap'); |
| |
| * { |
| margin: 0; |
| padding: 0; |
| box-sizing: border-box; |
| } |
| |
| body { |
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); |
| min-height: 100vh; |
| color: #1f2937; |
| padding: 20px; |
| } |
| |
| .container { |
| max-width: 1200px; |
| margin: 0 auto; |
| } |
| |
| |
| .header { |
| background: rgba(255, 255, 255, 0.1); |
| backdrop-filter: blur(20px); |
| border-radius: 20px; |
| padding: 30px; |
| margin-bottom: 30px; |
| border: 1px solid rgba(255, 255, 255, 0.2); |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| } |
| |
| .logo-section { |
| display: flex; |
| align-items: center; |
| gap: 20px; |
| } |
| |
| .logo-img { |
| width: 60px; |
| height: 60px; |
| background: white; |
| border-radius: 15px; |
| padding: 10px; |
| box-shadow: 0 4px 15px rgba(0,0,0,0.1); |
| } |
| |
| .logo-text h1 { |
| color: white; |
| font-size: 32px; |
| font-weight: 800; |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.1); |
| } |
| |
| .logo-text p { |
| color: rgba(255,255,255,0.9); |
| font-size: 14px; |
| } |
| |
| .back-btn { |
| background: white; |
| color: #8b5cf6; |
| border: none; |
| padding: 12px 24px; |
| border-radius: 10px; |
| font-weight: 600; |
| cursor: pointer; |
| transition: all 0.3s; |
| } |
| |
| .back-btn:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 5px 15px rgba(0,0,0,0.2); |
| } |
| |
| |
| .tabs { |
| background: rgba(255, 255, 255, 0.1); |
| backdrop-filter: blur(20px); |
| border-radius: 15px; |
| padding: 10px; |
| margin-bottom: 30px; |
| display: flex; |
| gap: 10px; |
| border: 1px solid rgba(255, 255, 255, 0.2); |
| } |
| |
| .tab-btn { |
| flex: 1; |
| background: transparent; |
| color: white; |
| border: none; |
| padding: 15px 20px; |
| border-radius: 10px; |
| font-weight: 600; |
| cursor: pointer; |
| transition: all 0.3s; |
| } |
| |
| .tab-btn.active { |
| background: white; |
| color: #8b5cf6; |
| box-shadow: 0 4px 15px rgba(0,0,0,0.1); |
| } |
| |
| .tab-btn:not(.active):hover { |
| background: rgba(255,255,255,0.1); |
| } |
| |
| |
| .tab-content { |
| display: none; |
| } |
| |
| .tab-content.active { |
| display: block; |
| } |
| |
| .card { |
| background: rgba(255, 255, 255, 0.95); |
| backdrop-filter: blur(20px); |
| border-radius: 20px; |
| padding: 30px; |
| margin-bottom: 20px; |
| border: 1px solid rgba(255, 255, 255, 0.2); |
| box-shadow: 0 8px 32px rgba(0,0,0,0.1); |
| } |
| |
| .card h2 { |
| color: #1f2937; |
| font-size: 24px; |
| margin-bottom: 20px; |
| display: flex; |
| align-items: center; |
| gap: 10px; |
| } |
| |
| .card h3 { |
| color: #4b5563; |
| font-size: 18px; |
| margin: 20px 0 15px 0; |
| } |
| |
| .form-group { |
| margin-bottom: 20px; |
| } |
| |
| .form-group label { |
| display: block; |
| color: #374151; |
| font-weight: 500; |
| margin-bottom: 8px; |
| font-size: 14px; |
| } |
| |
| .form-group input, |
| .form-group select, |
| .form-group textarea { |
| width: 100%; |
| padding: 12px 16px; |
| border: 2px solid #e5e7eb; |
| border-radius: 12px; |
| font-family: 'Inter', sans-serif; |
| font-size: 14px; |
| font-weight: 500; |
| transition: all 0.3s ease; |
| background: #fafbfc; |
| } |
| |
| .form-group input:focus, |
| .form-group select:focus, |
| .form-group textarea:focus { |
| outline: none; |
| border-color: #8b5cf6; |
| background: white; |
| box-shadow: 0 0 0 4px rgba(139, 92, 246, 0.15), inset 0 0 0 1px rgba(139, 92, 246, 0.1); |
| } |
| |
| .form-group textarea { |
| resize: vertical; |
| min-height: 100px; |
| font-weight: 400; |
| } |
| |
| |
| .toggle-group { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| padding: 15px 0; |
| border-bottom: 1px solid #e5e7eb; |
| } |
| |
| .toggle-group:last-child { |
| border-bottom: none; |
| } |
| |
| .toggle-label { |
| flex: 1; |
| } |
| |
| .toggle-label strong { |
| display: block; |
| color: #1f2937; |
| margin-bottom: 4px; |
| } |
| |
| .toggle-label span { |
| color: #6b7280; |
| font-size: 13px; |
| } |
| |
| .toggle-switch { |
| position: relative; |
| width: 50px; |
| height: 26px; |
| } |
| |
| .toggle-switch input { |
| opacity: 0; |
| width: 0; |
| height: 0; |
| } |
| |
| .toggle-slider { |
| position: absolute; |
| cursor: pointer; |
| top: 0; |
| left: 0; |
| right: 0; |
| bottom: 0; |
| background-color: #cbd5e1; |
| transition: 0.3s; |
| border-radius: 34px; |
| } |
| |
| .toggle-slider:before { |
| position: absolute; |
| content: ""; |
| height: 20px; |
| width: 20px; |
| left: 3px; |
| bottom: 3px; |
| background-color: white; |
| transition: 0.3s; |
| border-radius: 50%; |
| } |
| |
| input:checked + .toggle-slider { |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| } |
| |
| input:checked + .toggle-slider:before { |
| transform: translateX(24px); |
| } |
| |
| |
| .btn { |
| padding: 12px 24px; |
| border: none; |
| border-radius: 10px; |
| font-weight: 600; |
| cursor: pointer; |
| transition: all 0.3s; |
| font-size: 14px; |
| } |
| |
| .btn-primary { |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| color: white; |
| box-shadow: 0 6px 20px rgba(139, 92, 246, 0.3); |
| } |
| |
| .btn-primary:hover { |
| transform: translateY(-3px); |
| box-shadow: 0 8px 28px rgba(139, 92, 246, 0.45); |
| } |
| |
| .btn-primary:active { |
| transform: translateY(-1px); |
| } |
| |
| .btn-secondary { |
| background: #e5e7eb; |
| color: #1f2937; |
| } |
| |
| .btn-secondary:hover { |
| background: #d1d5db; |
| } |
| |
| .btn-danger { |
| background: #ef4444; |
| color: white; |
| } |
| |
| .btn-danger:hover { |
| background: #dc2626; |
| } |
| |
| .btn-group { |
| display: flex; |
| gap: 10px; |
| margin-top: 20px; |
| } |
| |
| |
| .stats-grid { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); |
| gap: 20px; |
| margin-bottom: 20px; |
| } |
| |
| .stat-card { |
| background: linear-gradient(135deg, rgba(139, 92, 246, 0.1) 0%, rgba(236, 72, 153, 0.1) 100%); |
| padding: 25px; |
| border-radius: 15px; |
| border: 2px solid rgba(139, 92, 246, 0.2); |
| } |
| |
| .stat-card h3 { |
| color: #6b7280; |
| font-size: 14px; |
| margin: 0 0 10px 0; |
| font-weight: 500; |
| } |
| |
| .stat-value { |
| color: #8b5cf6; |
| font-size: 32px; |
| font-weight: 800; |
| margin-bottom: 5px; |
| } |
| |
| .stat-label { |
| color: #9ca3af; |
| font-size: 12px; |
| } |
| |
| |
| .status-badge { |
| display: inline-block; |
| padding: 6px 12px; |
| border-radius: 20px; |
| font-size: 12px; |
| font-weight: 600; |
| } |
| |
| .status-active { |
| background: #d1fae5; |
| color: #065f46; |
| } |
| |
| .status-inactive { |
| background: #fee2e2; |
| color: #991b1b; |
| } |
| |
| |
| .alert { |
| padding: 15px 20px; |
| border-radius: 10px; |
| margin-bottom: 20px; |
| display: flex; |
| align-items: center; |
| gap: 10px; |
| } |
| |
| .alert-success { |
| background: #d1fae5; |
| color: #065f46; |
| border: 1px solid #6ee7b7; |
| } |
| |
| .alert-error { |
| background: #fee2e2; |
| color: #991b1b; |
| border: 1px solid #fca5a5; |
| } |
| |
| .alert-info { |
| background: #dbeafe; |
| color: #1e40af; |
| border: 1px solid #93c5fd; |
| } |
| |
| |
| .token-display { |
| background: #f3f4f6; |
| padding: 15px; |
| border-radius: 10px; |
| font-family: 'Courier New', monospace; |
| font-size: 13px; |
| word-break: break-all; |
| color: #374151; |
| margin-top: 10px; |
| } |
| |
| |
| .loading { |
| text-align: center; |
| padding: 40px; |
| } |
| |
| .spinner { |
| border: 4px solid #f3f4f6; |
| border-top: 4px solid #8b5cf6; |
| border-radius: 50%; |
| width: 40px; |
| height: 40px; |
| animation: spin 1s linear infinite; |
| margin: 0 auto 20px; |
| } |
| |
| @keyframes spin { |
| 0% { transform: rotate(0deg); } |
| 100% { transform: rotate(360deg); } |
| } |
| |
| |
| @media (max-width: 768px) { |
| .container { |
| padding: 10px; |
| } |
| |
| .header { |
| flex-direction: column; |
| gap: 20px; |
| } |
| |
| .tabs { |
| flex-direction: column; |
| } |
| |
| .stats-grid { |
| grid-template-columns: 1fr; |
| } |
| } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| |
| <div class="header"> |
| <div class="logo-section"> |
| <img src="/static/logo.png" alt="NoahsKI Logo" class="logo-img"> |
| <div class="logo-text"> |
| <h1>NoahsKI</h1> |
| <p>Deine persönliche KI - Einstellungen</p> |
| </div> |
| </div> |
| <button class="back-btn" onclick="location.href='/'">← Zurück zur App</button> |
| </div> |
| |
| |
| <div class="tabs"> |
| <button class="tab-btn active" onclick="switchTab('profile')">👤 Profil</button> |
| <button class="tab-btn" onclick="switchTab('discord')">✨ Bot Konfiguration</button> |
| <button class="tab-btn" onclick="switchTab('preferences')">⚙️ Einstellungen</button> |
| <button class="tab-btn" onclick="switchTab('stats')">📊 Statistiken</button> |
| <button class="tab-btn" onclick="switchTab('security')">🔒 Sicherheit</button> |
| </div> |
| |
| |
| <div id="profile-tab" class="tab-content active"> |
| <div class="card"> |
| <h2>👤 Profil Informationen</h2> |
| <div class="form-group"> |
| <label>Benutzername</label> |
| <input type="text" id="username" placeholder="Dein Benutzername"> |
| </div> |
| <div class="form-group"> |
| <label>E-Mail Adresse</label> |
| <input type="email" id="email" readonly style="background: #f3f4f6;"> |
| </div> |
| <div class="form-group"> |
| <label>Mitglied seit</label> |
| <input type="text" id="member-since" readonly style="background: #f3f4f6;"> |
| </div> |
| <div class="btn-group"> |
| <button class="btn btn-primary" onclick="saveProfile()">💾 Profil speichern</button> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div id="discord-tab" class="tab-content"> |
| <div class="card"> |
| <h2>✨ Bot Konfiguration</h2> |
| <p style="color: #6b7280; margin-bottom: 20px;"> |
| Konfiguriere deinen persönlichen Bot, der die NoahsKI Engine nutzt! |
| </p> |
| |
| <div class="alert alert-info"> |
| <span>ℹ️</span> |
| <div> |
| <strong>So funktioniert's:</strong><br> |
| 1. Konfiguriere die Bot-Einstellungen unten<br> |
| 2. Gib deinen Bot Token ein (falls erforderlich)<br> |
| 3. Aktiviere den Bot und speichere die Einstellungen<br> |
| 4. Der Bot ist bereit und antwortet auf Befehle! |
| </div> |
| </div> |
| |
| <div class="toggle-group"> |
| <div class="toggle-label"> |
| <strong>Bot aktivieren</strong> |
| <span>Aktiviere deinen persönlichen Bot</span> |
| </div> |
| <label class="toggle-switch"> |
| <input type="checkbox" id="discord-enabled" onchange="toggleDiscordSettings()"> |
| <span class="toggle-slider"></span> |
| </label> |
| </div> |
| |
| <div id="discord-settings" style="display: none; margin-top: 20px;"> |
| <h3>Bot Konfiguration</h3> |
| |
| <div class="form-group"> |
| <label>Bot Token</label> |
| <input type="password" id="discord-token" placeholder="Dein Bot Token (optional)"> |
| <small style="color: #6b7280; display: block; margin-top: 5px;"> |
| 🔐 Dein Token wird sicher verschlüsselt gespeichert |
| </small> |
| </div> |
| |
| <div class="form-group"> |
| <label>Bot Prefix</label> |
| <input type="text" id="discord-prefix" placeholder="!" maxlength="5" value="!"> |
| <small style="color: #6b7280; display: block; margin-top: 5px;"> |
| Das Zeichen, mit dem Bot-Befehle starten (z.B. !, ?, $, ~) |
| </small> |
| </div> |
| |
| <div class="form-group"> |
| <label>Bot Status</label> |
| <select id="discord-status"> |
| <option value="online">🟢 Online</option> |
| <option value="idle">🟡 Abwesend</option> |
| <option value="dnd">🔴 Nicht stören</option> |
| <option value="invisible">⚫ Unsichtbar</option> |
| </select> |
| </div> |
| |
| <div class="form-group"> |
| <label>Bot Aktivität</label> |
| <input type="text" id="discord-activity" placeholder="z.B. mit NoahsKI" value="mit NoahsKI"> |
| </div> |
| |
| <div class="alert alert-success"> |
| <span>✅</span> |
| <div> |
| <strong>Verfügbare Kommandos:</strong><br> |
| `!help` - Zeige alle Befehle | `!ask <Frage>` - Stelle Fragen<br> |
| `!image <Beschr.>` - Generiere Bilder | `!code <Request>` - Generiere Code<br> |
| `!translate <Text>` - Übersetze Text | `!joke` - Höre einen Witz<br> |
| `!summarize <Text>` - Fasse zusammen | `!quote` - Inspirierendes Zitat<br> |
| `!info <Thema>` - Info zu Themen | `!languages` - Unterstützte Sprachen |
| </div> |
| </div> |
| |
| <div class="btn-group"> |
| <button class="btn btn-primary" onclick="saveDiscordBot()">💾 Bot Einstellungen speichern</button> |
| <button class="btn btn-secondary" onclick="testDiscordBot()">🧪 Bot testen</button> |
| </div> |
| </div> |
| </div> |
| |
| <div class="card" id="bot-status-card" style="display: none;"> |
| <h2>✨ Bot Status</h2> |
| <div class="stats-grid"> |
| <div class="stat-card"> |
| <h3>Bot Status</h3> |
| <div class="stat-value" id="bot-status"> |
| <span class="status-badge status-inactive">Inaktiv</span> |
| </div> |
| <div class="stat-label">Aktueller Status</div> |
| </div> |
| <div class="stat-card"> |
| <h3>Server</h3> |
| <div class="stat-value" id="bot-servers">0</div> |
| <div class="stat-label">Verbundene Server</div> |
| </div> |
| <div class="stat-card"> |
| <h3>Nachrichten</h3> |
| <div class="stat-value" id="bot-messages">0</div> |
| <div class="stat-label">Heute verarbeitet</div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div id="preferences-tab" class="tab-content"> |
| <div class="card"> |
| <h2>⚙️ Persönliche Einstellungen</h2> |
| |
| <div class="form-group"> |
| <label>Design / Theme</label> |
| <select id="theme"> |
| <option value="dark">🌙 Dunkel</option> |
| <option value="light">☀️ Hell</option> |
| <option value="auto">🔄 Automatisch</option> |
| </select> |
| </div> |
| |
| <div class="form-group"> |
| <label>Sprache</label> |
| <select id="language"> |
| <option value="de">🇩🇪 Deutsch</option> |
| <option value="en">🇬🇧 English</option> |
| <option value="es">🇪🇸 Español</option> |
| <option value="fr">🇫🇷 Français</option> |
| <option value="it">🇮🇹 Italiano</option> |
| </select> |
| </div> |
| |
| <h3>Benachrichtigungen</h3> |
| |
| <div class="toggle-group"> |
| <div class="toggle-label"> |
| <strong>Push Benachrichtigungen</strong> |
| <span>Erhalte Benachrichtigungen über wichtige Ereignisse</span> |
| </div> |
| <label class="toggle-switch"> |
| <input type="checkbox" id="notifications" checked> |
| <span class="toggle-slider"></span> |
| </label> |
| </div> |
| |
| <div class="toggle-group"> |
| <div class="toggle-label"> |
| <strong>E-Mail Benachrichtigungen</strong> |
| <span>Erhalte E-Mails über wichtige Updates</span> |
| </div> |
| <label class="toggle-switch"> |
| <input type="checkbox" id="email-notifications" checked> |
| <span class="toggle-slider"></span> |
| </label> |
| </div> |
| |
| <div class="toggle-group"> |
| <div class="toggle-label"> |
| <strong>Benachrichtigungen</strong> |
| <span>Erhalte Benachrichtigungen über Bot-Dinge</span> |
| </div> |
| <label class="toggle-switch"> |
| <input type="checkbox" id="discord-notifications"> |
| <span class="toggle-slider"></span> |
| </label> |
| </div> |
| |
| <h3>KI Einstellungen</h3> |
| |
| <div class="form-group"> |
| <label>Kreativität</label> |
| <input type="range" id="creativity" min="0" max="100" value="70" |
| oninput="document.getElementById('creativity-value').innerText = this.value + '%'" |
| style="width: 100%;"> |
| <div style="text-align: right; color: #6b7280; font-size: 13px; margin-top: 5px;"> |
| <span id="creativity-value">70%</span> |
| </div> |
| </div> |
| |
| <div class="form-group"> |
| <label>Antwortlänge</label> |
| <select id="response-length"> |
| <option value="short">Kurz</option> |
| <option value="medium" selected>Mittel</option> |
| <option value="long">Lang</option> |
| <option value="detailed">Sehr detailliert</option> |
| </select> |
| </div> |
| |
| <div class="toggle-group"> |
| <div class="toggle-label"> |
| <strong>Code-Syntax-Highlighting</strong> |
| <span>Aktiviere Syntax-Highlighting für Code-Blöcke</span> |
| </div> |
| <label class="toggle-switch"> |
| <input type="checkbox" id="syntax-highlighting" checked> |
| <span class="toggle-slider"></span> |
| </label> |
| </div> |
| |
| <div class="btn-group"> |
| <button class="btn btn-primary" onclick="savePreferences()">💾 Einstellungen speichern</button> |
| <button class="btn btn-secondary" onclick="resetSettings()">🔄 Zurücksetzen</button> |
| <button class="btn btn-secondary" onclick="exportSettings()">📤 Exportieren</button> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div id="stats-tab" class="tab-content"> |
| <div class="card"> |
| <h2>📊 Deine Statistiken</h2> |
| <div class="stats-grid"> |
| <div class="stat-card"> |
| <h3>Account Alter</h3> |
| <div class="stat-value" id="account-age">0</div> |
| <div class="stat-label">Tage</div> |
| </div> |
| <div class="stat-card"> |
| <h3>Letzte Anmeldung</h3> |
| <div class="stat-value" style="font-size: 18px;" id="last-login">-</div> |
| <div class="stat-label">Datum</div> |
| </div> |
| <div class="stat-card"> |
| <h3>Aktive Sessions</h3> |
| <div class="stat-value" id="active-sessions">0</div> |
| <div class="stat-label">Geräte</div> |
| </div> |
| <div class="stat-card"> |
| <h3>Nachrichten</h3> |
| <div class="stat-value" id="total-messages">0</div> |
| <div class="stat-label">Gesendet (geschätzt)</div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="card"> |
| <h2>🎯 Nutzungsstatistiken</h2> |
| <div class="stats-grid"> |
| <div class="stat-card"> |
| <h3>Bilder generiert</h3> |
| <div class="stat-value">0</div> |
| <div class="stat-label">Insgesamt</div> |
| </div> |
| <div class="stat-card"> |
| <h3>Web-Suchen</h3> |
| <div class="stat-value">0</div> |
| <div class="stat-label">Durchgeführt</div> |
| </div> |
| <div class="stat-card"> |
| <h3>Code generiert</h3> |
| <div class="stat-value">0</div> |
| <div class="stat-label">Zeilen</div> |
| </div> |
| <div class="stat-card"> |
| <h3>Sprachen</h3> |
| <div class="stat-value">0</div> |
| <div class="stat-label">Verwendet</div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div id="security-tab" class="tab-content"> |
| <div class="card"> |
| <h2>🔒 Sicherheit & Passwort</h2> |
| |
| <h3>Passwort ändern</h3> |
| <div class="form-group"> |
| <label>Aktuelles Passwort</label> |
| <input type="password" id="current-password" placeholder="Aktuelles Passwort"> |
| </div> |
| <div class="form-group"> |
| <label>Neues Passwort</label> |
| <input type="password" id="new-password" placeholder="Neues Passwort (min. 6 Zeichen)"> |
| </div> |
| <div class="form-group"> |
| <label>Neues Passwort bestätigen</label> |
| <input type="password" id="confirm-password" placeholder="Neues Passwort bestätigen"> |
| </div> |
| <div class="btn-group"> |
| <button class="btn btn-primary" onclick="changePassword()">🔐 Passwort ändern</button> |
| </div> |
| </div> |
| |
| <div class="card"> |
| <h2>⚠️ Gefahrenzone</h2> |
| <div class="alert alert-error"> |
| <span>⚠️</span> |
| <div> |
| <strong>Achtung:</strong> Diese Aktionen können nicht rückgängig gemacht werden! |
| </div> |
| </div> |
| |
| <div class="btn-group"> |
| <button class="btn btn-danger" onclick="deleteAccount()">🗑️ Account löschen</button> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <script> |
| let userEmail = ''; |
| |
| |
| function getAuthToken() { |
| |
| let token = localStorage.getItem('auth_token'); |
| if (token) { |
| console.log('Token found in localStorage'); |
| return token; |
| } |
| |
| |
| const cookies = document.cookie.split(';'); |
| for (let cookie of cookies) { |
| const [name, value] = cookie.trim().split('='); |
| if (name === 'auth_token' && value) { |
| console.log('Token found in cookies, saving to localStorage'); |
| localStorage.setItem('auth_token', value); |
| return value; |
| } |
| } |
| |
| console.warn('No auth token found in localStorage or cookies'); |
| return null; |
| } |
| |
| |
| function switchTab(tabName) { |
| |
| document.querySelectorAll('.tab-content').forEach(tab => { |
| tab.classList.remove('active'); |
| }); |
| |
| |
| document.querySelectorAll('.tab-btn').forEach(btn => { |
| btn.classList.remove('active'); |
| }); |
| |
| |
| document.getElementById(tabName + '-tab').classList.add('active'); |
| |
| |
| event.target.classList.add('active'); |
| |
| |
| if (tabName === 'stats') { |
| loadStats(); |
| } |
| } |
| |
| |
| function toggleDiscordSettings() { |
| const enabled = document.getElementById('discord-enabled').checked; |
| document.getElementById('discord-settings').style.display = enabled ? 'block' : 'none'; |
| document.getElementById('bot-status-card').style.display = enabled ? 'block' : 'none'; |
| } |
| |
| |
| async function loadUserData() { |
| try { |
| const token = localStorage.getItem('auth_token'); |
| const response = await fetch('/api/auth/user', { |
| headers: { |
| 'Authorization': `Bearer ${token}` |
| } |
| }); |
| |
| if (response.ok) { |
| const data = await response.json(); |
| const user = data.user; |
| userEmail = user.email; |
| |
| |
| document.getElementById('email').value = user.email; |
| document.getElementById('username').value = user.username || ''; |
| document.getElementById('member-since').value = new Date(user.created_at * 1000).toLocaleDateString('de-DE'); |
| |
| |
| document.getElementById('theme').value = user.theme || 'dark'; |
| document.getElementById('language').value = user.language || 'de'; |
| document.getElementById('notifications').checked = user.notifications !== false; |
| |
| |
| document.getElementById('discord-enabled').checked = user.discord_bot_enabled || false; |
| document.getElementById('discord-prefix').value = user.discord_bot_prefix || '!'; |
| document.getElementById('discord-status').value = user.discord_bot_status || 'online'; |
| toggleDiscordSettings(); |
| } |
| } catch (error) { |
| console.error('Error loading user data:', error); |
| } |
| } |
| |
| |
| async function loadStats() { |
| try { |
| const token = localStorage.getItem('auth_token'); |
| const response = await fetch('/api/auth/stats', { |
| headers: { |
| 'Authorization': `Bearer ${token}` |
| } |
| }); |
| |
| if (response.ok) { |
| const stats = await response.json(); |
| |
| document.getElementById('account-age').textContent = stats.account_age_days || 0; |
| document.getElementById('active-sessions').textContent = stats.active_sessions || 0; |
| |
| if (stats.last_login) { |
| const date = new Date(stats.last_login * 1000); |
| document.getElementById('last-login').textContent = date.toLocaleString('de-DE'); |
| } |
| } |
| } catch (error) { |
| console.error('Error loading stats:', error); |
| } |
| } |
| |
| |
| async function saveProfile() { |
| try { |
| const token = getAuthToken(); |
| if (!token) { |
| alert('Nicht authentifiziert! Bitte neu anmelden.'); |
| return; |
| } |
| |
| const username = document.getElementById('username').value; |
| if (!username || username.trim().length === 0) { |
| alert('Benutzername erforderlich!'); |
| return; |
| } |
| |
| const settings = { username }; |
| |
| const response = await fetch('/api/auth/update-settings', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Authorization': `Bearer ${token}` |
| }, |
| body: JSON.stringify(settings) |
| }); |
| |
| const data = await response.json(); |
| |
| if (response.ok && data.success) { |
| alert('Profil erfolgreich gespeichert!'); |
| console.log('Profile saved:', data); |
| } else { |
| alert(`Fehler: ${data.message || 'Speichern fehlgeschlagen'}`); |
| console.error('Save error:', data); |
| } |
| } catch (error) { |
| console.error('Error saving profile:', error); |
| alert(`Fehler beim Speichern: ${error.message}`); |
| } |
| } |
| |
| |
| async function saveDiscordBot() { |
| try { |
| const token = getAuthToken(); |
| if (!token) { |
| alert('Nicht authentifiziert! Bitte neu anmelden.'); |
| return; |
| } |
| |
| const enabled = document.getElementById('discord-enabled').checked; |
| const settings = { discord_bot_enabled: enabled }; |
| |
| if (enabled) { |
| const tokenValue = document.getElementById('discord-token').value; |
| if (!tokenValue || tokenValue.trim().length === 0) { |
| alert('Discord Token erforderlich!'); |
| return; |
| } |
| settings.discord_bot_token = tokenValue; |
| } |
| |
| settings.discord_bot_prefix = document.getElementById('discord-prefix').value || '!'; |
| settings.discord_bot_status = document.getElementById('discord-status').value || 'online'; |
| |
| const response = await fetch('/api/auth/update-settings', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Authorization': `Bearer ${token}` |
| }, |
| body: JSON.stringify(settings) |
| }); |
| |
| const data = await response.json(); |
| |
| if (response.ok && data.success) { |
| alert(`Discord Bot ${enabled ? 'aktiviert' : 'deaktiviert'}!`); |
| console.log('Discord settings saved:', data); |
| } else { |
| alert(`Fehler: ${data.message || 'Speichern fehlgeschlagen'}`); |
| console.error('Save error:', data); |
| } |
| } catch (error) { |
| console.error('Error saving Discord bot:', error); |
| alert('❌ Fehler beim Speichern'); |
| } |
| } |
| |
| |
| async function testDiscordBot() { |
| alert('🧪 Bot Test-Funktion wird implementiert...'); |
| } |
| |
| |
| async function savePreferences() { |
| try { |
| const token = getAuthToken(); |
| if (!token) { |
| alert('❌ Nicht authentifiziert! Bitte neu anmelden.'); |
| return; |
| } |
| |
| const theme = document.getElementById('theme').value; |
| const language = document.getElementById('language').value; |
| const notifications = document.getElementById('notifications').checked; |
| |
| let successCount = 0; |
| let hasError = false; |
| |
| |
| if (theme) { |
| try { |
| const themeResponse = await fetch('/api/settings/apply-theme', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Authorization': `Bearer ${token}` |
| }, |
| body: JSON.stringify({ theme: theme }) |
| }); |
| |
| if (themeResponse.ok) { |
| successCount++; |
| console.log('✅ Theme applied:', theme); |
| } |
| } catch (e) { |
| console.error('Theme error:', e); |
| hasError = true; |
| } |
| } |
| |
| |
| if (language) { |
| try { |
| const langResponse = await fetch('/api/settings/apply-language', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Authorization': `Bearer ${token}` |
| }, |
| body: JSON.stringify({ language: language }) |
| }); |
| |
| if (langResponse.ok) { |
| successCount++; |
| console.log('✅ Language applied:', language); |
| } |
| } catch (e) { |
| console.error('Language error:', e); |
| hasError = true; |
| } |
| } |
| |
| |
| const settings = { |
| theme: theme, |
| language: language, |
| notifications: notifications |
| }; |
| |
| const response = await fetch('/api/auth/update-settings', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Authorization': `Bearer ${token}` |
| }, |
| body: JSON.stringify(settings) |
| }); |
| |
| const data = await response.json(); |
| |
| if (response.ok && data.success) { |
| successCount++; |
| if (hasError) { |
| alert('⚠️ Einige Einstellungen gespeichert, andere fehlgeschlagen'); |
| } else { |
| alert('✅ Alle Einstellungen gespeichert!'); |
| } |
| console.log('Preferences saved:', data); |
| } else { |
| alert(`Fehler: ${data.message || 'Speichern fehlgeschlagen'}`); |
| console.error('Save error:', data); |
| } |
| } catch (error) { |
| console.error('Error saving preferences:', error); |
| alert('❌ Fehler beim Speichern'); |
| } |
| } |
| |
| |
| async function changePassword() { |
| const current = document.getElementById('current-password').value; |
| const newPass = document.getElementById('new-password').value; |
| const confirm = document.getElementById('confirm-password').value; |
| |
| if (!current || !newPass || !confirm) { |
| alert('❌ Bitte alle Felder ausfüllen'); |
| return; |
| } |
| |
| if (newPass !== confirm) { |
| alert('❌ Passwörter stimmen nicht überein'); |
| return; |
| } |
| |
| if (newPass.length < 6) { |
| alert('❌ Passwort muss mindestens 6 Zeichen haben'); |
| return; |
| } |
| |
| try { |
| const token = getAuthToken(); |
| if (!token) { |
| alert('❌ Nicht authentifiziert! Bitte neu anmelden.'); |
| return; |
| } |
| |
| const response = await fetch('/api/auth/change-password', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Authorization': `Bearer ${token}` |
| }, |
| body: JSON.stringify({ |
| current_password: current, |
| new_password: newPass |
| }) |
| }); |
| |
| const data = await response.json(); |
| |
| if (response.ok && data.success) { |
| alert('✅ Passwort erfolgreich geändert!'); |
| document.getElementById('current-password').value = ''; |
| document.getElementById('new-password').value = ''; |
| document.getElementById('confirm-password').value = ''; |
| console.log('Password changed successfully'); |
| } else { |
| alert(`Fehler: ${data.message || 'Passwort-Änderung fehlgeschlagen'}`); |
| console.error('Password change error:', data); |
| } |
| } catch (error) { |
| console.error('Error changing password:', error); |
| alert(`Fehler beim Ändern des Passworts: ${error.message}`); |
| } |
| } |
| |
| |
| async function deleteAccount() { |
| if (!confirm('⚠️ Bist du sicher? Diese Aktion kann nicht rückgängig gemacht werden!')) { |
| return; |
| } |
| |
| if (!confirm('⚠️ Wirklich ALLE Daten löschen? Letzte Warnung!')) { |
| return; |
| } |
| |
| try { |
| const token = localStorage.getItem('auth_token'); |
| const response = await fetch('/api/auth/delete-account', { |
| method: 'POST', |
| headers: { |
| 'Authorization': `Bearer ${token}` |
| } |
| }); |
| |
| if (response.ok) { |
| alert('✅ Account gelöscht'); |
| localStorage.removeItem('auth_token'); |
| location.href = '/login'; |
| } else { |
| alert('❌ Fehler beim Löschen'); |
| } |
| } catch (error) { |
| console.error('Error deleting account:', error); |
| alert('❌ Fehler beim Löschen'); |
| } |
| } |
| |
| |
| async function resetSettings() { |
| if (!confirm('⚠️ Alle Einstellungen auf Standard zurücksetzen?')) { |
| return; |
| } |
| |
| try { |
| const token = getAuthToken(); |
| if (!token) { |
| alert('❌ Nicht authentifiziert!'); |
| return; |
| } |
| |
| const response = await fetch('/api/settings/reset', { |
| method: 'POST', |
| headers: { |
| 'Authorization': `Bearer ${token}` |
| } |
| }); |
| |
| const data = await response.json(); |
| |
| if (response.ok && data.success) { |
| alert('✅ Einstellungen zurückgesetzt!'); |
| loadSettings(); |
| location.reload(); |
| } else { |
| alert(`Fehler: ${data.message || 'Zurücksetzen fehlgeschlagen'}`); |
| } |
| } catch (error) { |
| console.error('Error resetting settings:', error); |
| alert('❌ Fehler beim Zurücksetzen'); |
| } |
| } |
| |
| |
| async function exportSettings() { |
| try { |
| const token = getAuthToken(); |
| if (!token) { |
| alert('❌ Nicht authentifiziert!'); |
| return; |
| } |
| |
| const response = await fetch('/api/settings/export', { |
| headers: { |
| 'Authorization': `Bearer ${token}` |
| } |
| }); |
| |
| const data = await response.json(); |
| |
| if (response.ok && data.success) { |
| |
| const json = JSON.stringify(data, null, 2); |
| const blob = new Blob([json], { type: 'application/json' }); |
| const url = URL.createObjectURL(blob); |
| const a = document.createElement('a'); |
| a.href = url; |
| a.download = `noahski-settings-${new Date().toISOString().split('T')[0]}.json`; |
| a.click(); |
| URL.revokeObjectURL(url); |
| alert('✅ Einstellungen exportiert!'); |
| } else { |
| alert(`Fehler: ${data.message || 'Export fehlgeschlagen'}`); |
| } |
| } catch (error) { |
| console.error('Error exporting settings:', error); |
| alert('❌ Fehler beim Exportieren'); |
| } |
| } |
| |
| |
| async function loadSettings() { |
| try { |
| const token = localStorage.getItem('auth_token'); |
| const response = await fetch('/api/auth/get-settings', { |
| headers: { |
| 'Authorization': `Bearer ${token}` |
| } |
| }); |
| |
| if (response.ok) { |
| const data = await response.json(); |
| const settings = data.settings || {}; |
| |
| |
| if (settings.theme) document.getElementById('theme').value = settings.theme; |
| if (settings.language) document.getElementById('language').value = settings.language; |
| if (settings.notifications_enabled !== undefined) document.getElementById('notifications').checked = settings.notifications_enabled; |
| |
| |
| if (settings.discord_bot) { |
| document.getElementById('discord-enabled').checked = settings.discord_bot.enabled || false; |
| if (settings.discord_bot.prefix) document.getElementById('discord-prefix').value = settings.discord_bot.prefix; |
| if (settings.discord_bot.status) document.getElementById('discord-status').value = settings.discord_bot.status; |
| } |
| |
| toggleDiscordSettings(); |
| console.log('✅ Settings loaded successfully'); |
| } else { |
| console.warn('Could not load settings'); |
| } |
| } catch (error) { |
| console.error('Error loading settings:', error); |
| } |
| } |
| |
| |
| window.onload = () => { |
| |
| const token = getAuthToken(); |
| if (!token) { |
| console.warn('No auth token found - user may need to login again'); |
| } |
| |
| loadUserData(); |
| loadStats(); |
| loadSettings(); |
| }; |
| </script> |
| </body> |
| </html> |
|
|