A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2372 lines
137 KiB
HTML
2372 lines
137 KiB
HTML
|
||
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>BreakPilot – Arbeitsblatt Studio</title>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<link rel="stylesheet" href="/static/css/studio.css">
|
||
</head>
|
||
<body>
|
||
<div class="app-root">
|
||
<header class="topbar">
|
||
<div class="brand">
|
||
<div class="brand-logo">BP</div>
|
||
<div>
|
||
<div class="brand-text-main">BreakPilot</div>
|
||
<div class="brand-text-sub">Studio</div>
|
||
</div>
|
||
</div>
|
||
<nav class="top-nav" style="display:none;">
|
||
<div class="top-nav-item active" data-screen="1"></div>
|
||
<div class="top-nav-item" data-screen="2"></div>
|
||
</nav>
|
||
<div class="top-actions">
|
||
<div class="language-selector">
|
||
<select id="language-select" class="lang-select">
|
||
<option value="de">🇩🇪 Deutsch</option>
|
||
<option value="tr">🇹🇷 Türkçe</option>
|
||
<option value="ar">🇸🇦 العربية</option>
|
||
<option value="ru">🇷🇺 Русский</option>
|
||
<option value="uk">🇺🇦 Українська</option>
|
||
<option value="pl">🇵🇱 Polski</option>
|
||
<option value="en">🇬🇧 English</option>
|
||
</select>
|
||
</div>
|
||
<button class="theme-toggle" id="theme-toggle" title="Dark/Light Mode">
|
||
<span class="theme-toggle-icon" id="theme-icon">🌙</span>
|
||
<span id="theme-label">Dark</span>
|
||
</button>
|
||
<button class="btn btn-sm btn-ghost" id="btn-admin" title="Admin Panel">⚙️</button>
|
||
<button class="btn btn-sm btn-ghost" id="btn-login" data-i18n="login">Login / Anmeldung</button>
|
||
<!-- Notification Bell (shown when logged in) -->
|
||
<div class="notification-bell" id="notification-bell">
|
||
<button class="notification-bell-btn" id="notification-bell-btn" title="Benachrichtigungen">
|
||
🔔
|
||
</button>
|
||
<span class="notification-badge hidden" id="notification-badge">0</span>
|
||
<div class="notification-panel" id="notification-panel">
|
||
<div class="notification-panel-header">
|
||
<span class="notification-panel-title">Benachrichtigungen</span>
|
||
<div class="notification-panel-actions">
|
||
<button class="notification-panel-action" onclick="markAllNotificationsRead()" title="Alle als gelesen markieren">✓ Alle</button>
|
||
<button class="notification-panel-action" onclick="showNotificationPreferences()" title="Einstellungen">⚙️</button>
|
||
</div>
|
||
</div>
|
||
<div class="notification-list" id="notification-list">
|
||
<div class="notification-empty">
|
||
<div class="notification-empty-icon">🔔</div>
|
||
<div>Keine Benachrichtigungen</div>
|
||
</div>
|
||
</div>
|
||
<div class="notification-footer">
|
||
<button class="notification-footer-btn" onclick="loadMoreNotifications()">Mehr laden</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- User Dropdown (shown when logged in) -->
|
||
<div class="auth-user-dropdown">
|
||
<button class="auth-user-btn" id="auth-user-btn">
|
||
<div class="auth-user-avatar">BP</div>
|
||
<span>▼</span>
|
||
</button>
|
||
<div class="auth-user-menu" id="auth-user-menu">
|
||
<div class="auth-user-menu-header">
|
||
<div class="auth-user-menu-name">Benutzer</div>
|
||
<div class="auth-user-menu-email">user@example.com</div>
|
||
</div>
|
||
<button class="auth-user-menu-item" onclick="showProfileModal()">👤 Profil</button>
|
||
<button class="auth-user-menu-item" onclick="showSessionsModal()">🔐 Aktive Sitzungen</button>
|
||
<button class="auth-user-menu-item danger" onclick="logout()">🚪 Abmelden</button>
|
||
</div>
|
||
</div>
|
||
<div class="pill" data-i18n="mvp_local">MVP · Lokal auf deinem Mac</div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="main-layout">
|
||
<aside class="sidebar">
|
||
<!-- UNTERRICHT -->
|
||
<div>
|
||
<div class="sidebar-section-title">Unterricht</div>
|
||
<div class="sidebar-menu">
|
||
<div class="sidebar-item active" id="sidebar-studio" onclick="showStudioPanel()">
|
||
<div class="sidebar-item-label">
|
||
<span>Arbeitsblatt-Studio</span>
|
||
</div>
|
||
<div class="sidebar-item-badge">aktiv</div>
|
||
</div>
|
||
</div>
|
||
<!-- Sub-Navigation für Arbeitsblatt-Studio -->
|
||
<div class="sidebar-sub-menu" id="studio-sub-menu">
|
||
<div class="sidebar-sub-item active" id="sub-worksheets" onclick="showWorksheetTab()">
|
||
Arbeitsblätter
|
||
</div>
|
||
<div class="sidebar-sub-item" id="sub-tiles" onclick="showTilesTab()">
|
||
Lernkacheln
|
||
</div>
|
||
</div>
|
||
<div class="sidebar-menu">
|
||
<div class="sidebar-item" id="sidebar-correction" onclick="showCorrectionPanel()">
|
||
<div class="sidebar-item-label">
|
||
<span>Klausur-Korrektur</span>
|
||
</div>
|
||
<div class="sidebar-item-badge" style="background: #f59e0b;">Phase 1</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- LEISTUNGSBEWERTUNG -->
|
||
<div>
|
||
<div class="sidebar-section-title">Leistungsbewertung</div>
|
||
<div class="sidebar-menu">
|
||
<div class="sidebar-item" id="sidebar-exams" onclick="showExamsPanel()">
|
||
<div class="sidebar-item-label">
|
||
<span>Klausuren & Tests</span>
|
||
</div>
|
||
<div class="sidebar-item-badge" style="background: #6366f1;">neu</div>
|
||
</div>
|
||
<div class="sidebar-item" id="sidebar-grades" onclick="showGradesPanel()">
|
||
<div class="sidebar-item-label">
|
||
<span>Notenspiegel</span>
|
||
</div>
|
||
</div>
|
||
<div class="sidebar-item" id="sidebar-gradebook" onclick="showGradebookPanel()">
|
||
<div class="sidebar-item-label">
|
||
<span>Klassenbuch</span>
|
||
</div>
|
||
</div>
|
||
<div class="sidebar-item" id="sidebar-certificates" onclick="showCertificatesPanel()">
|
||
<div class="sidebar-item-label">
|
||
<span>Zeugnisse</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- VERWALTUNG -->
|
||
<div>
|
||
<div class="sidebar-section-title">Verwaltung</div>
|
||
<div class="sidebar-menu">
|
||
<div class="sidebar-item" id="sidebar-classes" onclick="showClassesPanel()">
|
||
<div class="sidebar-item-label">
|
||
<span>Klassen & Schüler</span>
|
||
</div>
|
||
</div>
|
||
<div class="sidebar-item" id="sidebar-subjects" onclick="showSubjectsPanel()">
|
||
<div class="sidebar-item-label">
|
||
<span>Fächer</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- KOMMUNIKATION -->
|
||
<div>
|
||
<div class="sidebar-section-title">Elternkommunikation</div>
|
||
<div class="sidebar-menu">
|
||
<div class="sidebar-item" id="sidebar-messenger" onclick="showMessengerPanel()">
|
||
<div class="sidebar-item-label">
|
||
<span>Matrix Messenger</span>
|
||
</div>
|
||
<div class="sidebar-item-badge" style="background: #10b981;">aktiv</div>
|
||
</div>
|
||
<div class="sidebar-item" id="sidebar-video" onclick="showVideoPanel()">
|
||
<div class="sidebar-item-label">
|
||
<span>Jitsi Videokonferenz</span>
|
||
</div>
|
||
</div>
|
||
<div class="sidebar-item" id="sidebar-letters" onclick="showLettersPanel()">
|
||
<div class="sidebar-item-label">
|
||
<span>Elternbriefe</span>
|
||
</div>
|
||
<div class="sidebar-item-badge">neu</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<div class="sidebar-section-title">Lerneinheiten (lokal)</div>
|
||
<div class="unit-form">
|
||
<input class="unit-input" id="unit-student" placeholder="Schüler/in">
|
||
<input class="unit-input" id="unit-subject" placeholder="Fach">
|
||
<input class="unit-input" id="unit-grade" placeholder="Klasse (z.B. 7a)">
|
||
<input class="unit-input" id="unit-title" placeholder="Lerneinheit / Thema">
|
||
<button type="button" class="btn btn-sm btn-primary btn-unit-add" id="btn-add-unit">Anlegen</button>
|
||
<ul class="unit-list" id="unit-list"></ul>
|
||
<button type="button" class="btn btn-sm btn-ghost" id="btn-attach-current-to-lu">Aktuelles Arbeitsblatt hinzufügen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<div class="sidebar-section-title">Dateien hochladen</div>
|
||
<div class="upload-inline">
|
||
<input type="file" id="file-input" multiple>
|
||
<button type="button" class="btn btn-sm btn-primary" id="btn-upload-inline">Hochladen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<div class="sidebar-section-title">Speicherort</div>
|
||
<div class="sidebar-footer">
|
||
CI / Brandbook: Farben kommen bereits aus Variablen und sind später leicht anpassbar.
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<main class="content">
|
||
<!-- Screen 1: Eingangsdateien & Alt/Neu-Vergleich -->
|
||
<section class="panel" id="panel-compare" style="display:flex;">
|
||
<div class="panel-header">
|
||
<div>
|
||
<div class="panel-title">Arbeitsblätter & Vergleich</div>
|
||
<div class="panel-subtitle">Links Scan · Rechts neu aufgebautes Arbeitsblatt</div>
|
||
<div class="panel-subtitle" id="unit-heading-screen1">Keine Lerneinheit ausgewählt</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<button type="button" class="btn btn-sm btn-primary" id="btn-toggle-filter" style="font-size: 10px;">
|
||
Nur Lerneinheit
|
||
</button>
|
||
<span class="small-pill" id="eingang-count">0 Dateien</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="panel-body">
|
||
<ul class="file-list" id="eingang-list"></ul>
|
||
|
||
<div class="inline-process">
|
||
<button type="button" class="btn btn-sm btn-primary" id="btn-full-process">
|
||
Arbeitsblätter neu aufbauen
|
||
</button>
|
||
</div>
|
||
|
||
<div class="preview-container" id="preview-container">
|
||
<div class="preview-placeholder">
|
||
Lade Arbeitsblätter hoch und klicke auf „Arbeitsblätter neu aufbauen".<br>
|
||
Dann kannst du mit den Pfeilen durch die Scans und die bereinigten Versionen blättern.<br>
|
||
Mit Doppelklick öffnest du das Dokument im Vollbild.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Screen 2: Kacheln -->
|
||
<section class="panel" id="panel-tiles" style="display:none;">
|
||
<div class="panel-tools-header">
|
||
<div>
|
||
<div class="panel-title"><span id="unit-heading-screen2">Keine Lerneinheit ausgewählt</span> – Bitte wähle Deine Lernkacheln aus, die Du verwenden möchtest.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="panel-body">
|
||
<div class="card-toggle-bar">
|
||
<button class="toggle-pill active" data-tile="mindmap">Mindmap</button>
|
||
<button class="toggle-pill active" data-tile="qa">Frage–Antwort</button>
|
||
<button class="toggle-pill active" data-tile="mc">Multiple Choice</button>
|
||
<button class="toggle-pill active" data-tile="cloze">Lückentext</button>
|
||
</div>
|
||
|
||
<div class="cards-grid">
|
||
<!-- Mindmap Lernposter -->
|
||
<div class="card card-half" data-tile="mindmap">
|
||
<div class="card-header">
|
||
<div class="card-title">Mindmap Lernposter</div>
|
||
<div class="card-badge" id="mindmap-badge">Bereit</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<div>Erstellt eine kindgerechte Mindmap mit dem Hauptthema in der Mitte und allen Fachbegriffen in farbigen Kategorien. Perfekt zum Ausdrucken als A3-Poster!</div>
|
||
<div id="mindmap-preview" class="mindmap-preview"></div>
|
||
<div class="card-actions" style="flex-wrap:wrap;gap:6px;">
|
||
<button class="btn btn-sm btn-primary" id="btn-mindmap-generate">Mindmap erstellen</button>
|
||
<button class="btn btn-sm btn-ghost" id="btn-mindmap-show" style="display:none;">Ansehen</button>
|
||
<button class="btn btn-sm btn-ghost" id="btn-mindmap-print" style="display:none;">A3 Drucken</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Frage–Antwort mit Leitner-System -->
|
||
<div class="card card-half" data-tile="qa">
|
||
<div class="card-header">
|
||
<div class="card-title">Frage–Antwort-Blatt</div>
|
||
<div class="card-badge" id="qa-badge">Bereit</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<div>Frage-Antwort-Paare mit Leitner-Box System. Wiederholung nach Schwierigkeitsgrad für nachhaltiges Lernen.</div>
|
||
<div id="qa-preview" class="mc-preview"></div>
|
||
<div class="card-actions" style="flex-wrap:wrap;gap:6px;">
|
||
<button class="btn btn-sm btn-primary" id="btn-qa-generate">Q&A generieren</button>
|
||
<button class="btn btn-sm btn-ghost" id="btn-qa-learn" style="display:none;">Lernen starten</button>
|
||
<button class="btn btn-sm btn-ghost" id="btn-qa-print" style="display:none;">Drucken</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Multiple Choice -->
|
||
<div class="card card-half" data-tile="mc">
|
||
<div class="card-header">
|
||
<div class="card-title">Multiple Choice Test</div>
|
||
<div class="card-badge" id="mc-badge">Bereit</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<div>Erzeugt passende MC-Aufgaben zur ursprünglichen Schwierigkeit (z. B. Klasse 7), ohne das Niveau zu verändern.</div>
|
||
<div id="mc-preview" class="mc-preview"></div>
|
||
<div class="card-actions" style="flex-wrap:wrap;gap:6px;">
|
||
<button class="btn btn-sm btn-primary" id="btn-mc-generate">MC generieren</button>
|
||
<button class="btn btn-sm btn-ghost" id="btn-mc-show" style="display:none;">Quiz starten</button>
|
||
<button class="btn btn-sm btn-ghost" id="btn-mc-print" style="display:none;">Drucken</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Lückentext -->
|
||
<div class="card card-half" data-tile="cloze">
|
||
<div class="card-header">
|
||
<div class="card-title">Lückentext</div>
|
||
<div class="card-badge" id="cloze-badge">Bereit</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<div>Erzeugt Lückentexte mit mehreren sinnvollen Lücken pro Satz. Inkl. Übersetzung für Eltern.</div>
|
||
<div class="cloze-language-select" style="margin-top:8px;">
|
||
<label style="font-size:11px;color:var(--bp-text-muted);">Übersetzung:</label>
|
||
<select id="cloze-language" class="unit-input" style="padding:4px 8px;font-size:11px;width:auto;">
|
||
<option value="tr">Türkisch</option>
|
||
<option value="ar">Arabisch</option>
|
||
<option value="ru">Russisch</option>
|
||
<option value="uk">Ukrainisch</option>
|
||
<option value="pl">Polnisch</option>
|
||
<option value="en">Englisch</option>
|
||
<option value="fr">Französisch</option>
|
||
<option value="es">Spanisch</option>
|
||
</select>
|
||
</div>
|
||
<div id="cloze-preview" class="cloze-preview"></div>
|
||
<div class="card-actions" style="flex-wrap:wrap;gap:6px;">
|
||
<button class="btn btn-sm btn-primary" id="btn-cloze-generate">Lückentext generieren</button>
|
||
<button class="btn btn-sm btn-ghost" id="btn-cloze-show" style="display:none;">Übung starten</button>
|
||
<button class="btn btn-sm btn-ghost" id="btn-cloze-print" style="display:none;">Drucken</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Screen 4: Klausur-Korrektur -->
|
||
<section class="panel" id="panel-correction" style="display:none;">
|
||
<div class="panel-header">
|
||
<div>
|
||
<div class="panel-title">Klausur-Korrektur</div>
|
||
<div class="panel-subtitle">OCR, Bewertung & Feedback - Phase 1: Training</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<span class="small-pill" id="correction-status" style="background: #f59e0b;">In Entwicklung</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="panel-body" style="display: flex; gap: 20px; height: calc(100vh - 220px);">
|
||
<!-- Left: Upload & Exam List -->
|
||
<div style="width: 320px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px;">
|
||
<!-- Upload Area -->
|
||
<div class="card" style="padding: 16px;">
|
||
<div style="font-weight: 600; margin-bottom: 12px;">Klausur hochladen</div>
|
||
<div style="border: 2px dashed var(--bp-border); border-radius: 8px; padding: 24px; text-align: center; cursor: pointer;"
|
||
onclick="document.getElementById('exam-file-input').click()">
|
||
<div style="font-size: 32px; margin-bottom: 8px;">📄</div>
|
||
<div style="color: var(--bp-text-muted);">Klausur-Scans hochladen</div>
|
||
<div style="font-size: 12px; color: var(--bp-text-muted);">PDF, JPG, PNG (max 50MB)</div>
|
||
</div>
|
||
<input type="file" id="exam-file-input" multiple accept=".pdf,.jpg,.jpeg,.png" style="display: none;" onchange="handleExamUpload(event)">
|
||
|
||
<div style="margin-top: 12px;">
|
||
<select class="unit-input" id="exam-subject" style="width: 100%; margin-bottom: 8px;">
|
||
<option value="">Fach auswahlen...</option>
|
||
<option value="mathematik">Mathematik</option>
|
||
<option value="deutsch">Deutsch</option>
|
||
<option value="englisch">Englisch</option>
|
||
<option value="physik">Physik</option>
|
||
<option value="chemie">Chemie</option>
|
||
<option value="biologie">Biologie</option>
|
||
<option value="geschichte">Geschichte</option>
|
||
<option value="erdkunde">Erdkunde</option>
|
||
</select>
|
||
<input class="unit-input" id="exam-class" placeholder="Klasse (z.B. 7a)" style="width: 100%; margin-bottom: 8px;">
|
||
<input class="unit-input" id="exam-title" placeholder="Titel (z.B. 2. Klassenarbeit)" style="width: 100%;">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Exam List -->
|
||
<div class="card" style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border); font-weight: 600; display: flex; justify-content: space-between;">
|
||
<span>Meine Klausuren</span>
|
||
<span class="small-pill" id="exam-count">0</span>
|
||
</div>
|
||
<div id="exam-list" style="flex: 1; overflow-y: auto; padding: 8px;">
|
||
<div style="text-align: center; color: var(--bp-text-muted); padding: 20px;">
|
||
<div style="font-size: 24px; margin-bottom: 8px;">📋</div>
|
||
<div>Noch keine Klausuren</div>
|
||
<div style="font-size: 12px;">Lade Scans hoch um zu starten</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Center: Processing & Preview -->
|
||
<div style="flex: 1; display: flex; flex-direction: column; gap: 12px;">
|
||
<!-- Processing Pipeline -->
|
||
<div class="card" style="padding: 16px;">
|
||
<div style="font-weight: 600; margin-bottom: 12px;">Verarbeitungs-Pipeline</div>
|
||
<div style="display: flex; gap: 12px; align-items: center;">
|
||
<div class="pipeline-step" id="step-upload">
|
||
<div class="pipeline-icon">📤</div>
|
||
<div class="pipeline-label">Upload</div>
|
||
</div>
|
||
<div class="pipeline-arrow">→</div>
|
||
<div class="pipeline-step" id="step-preprocess">
|
||
<div class="pipeline-icon">🔧</div>
|
||
<div class="pipeline-label">Vorverarbeitung</div>
|
||
</div>
|
||
<div class="pipeline-arrow">→</div>
|
||
<div class="pipeline-step" id="step-ocr">
|
||
<div class="pipeline-icon">👁</div>
|
||
<div class="pipeline-label">OCR</div>
|
||
</div>
|
||
<div class="pipeline-arrow">→</div>
|
||
<div class="pipeline-step" id="step-segment">
|
||
<div class="pipeline-icon">📐</div>
|
||
<div class="pipeline-label">Segmentierung</div>
|
||
</div>
|
||
<div class="pipeline-arrow">→</div>
|
||
<div class="pipeline-step" id="step-grade">
|
||
<div class="pipeline-icon">✏️</div>
|
||
<div class="pipeline-label">Bewertung</div>
|
||
</div>
|
||
<div class="pipeline-arrow">→</div>
|
||
<div class="pipeline-step" id="step-review">
|
||
<div class="pipeline-icon">👀</div>
|
||
<div class="pipeline-label">Review</div>
|
||
</div>
|
||
</div>
|
||
<div style="margin-top: 12px;">
|
||
<div class="progress-bar" style="height: 8px; background: var(--bp-border); border-radius: 4px; overflow: hidden;">
|
||
<div id="pipeline-progress" style="width: 0%; height: 100%; background: #10b981; transition: width 0.3s;"></div>
|
||
</div>
|
||
<div style="display: flex; justify-content: space-between; margin-top: 4px; font-size: 12px; color: var(--bp-text-muted);">
|
||
<span id="pipeline-status">Warte auf Upload...</span>
|
||
<span id="pipeline-percent">0%</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Preview Area -->
|
||
<div class="card" style="flex: 1; display: flex; flex-direction: column; overflow: hidden;">
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border); display: flex; justify-content: space-between; align-items: center;">
|
||
<span style="font-weight: 600;">Vorschau & Ergebnisse</span>
|
||
<div style="display: flex; gap: 8px;">
|
||
<button class="btn btn-sm btn-ghost" onclick="prevExamPage()" title="Vorige Seite">◀</button>
|
||
<span id="exam-page-indicator">Seite 1/1</span>
|
||
<button class="btn btn-sm btn-ghost" onclick="nextExamPage()" title="Nachste Seite">▶</button>
|
||
</div>
|
||
</div>
|
||
<div id="exam-preview" style="flex: 1; display: flex; justify-content: center; align-items: center; background: var(--bp-bg-secondary); overflow: auto;">
|
||
<div style="text-align: center; color: var(--bp-text-muted);">
|
||
<div style="font-size: 48px; margin-bottom: 12px;">📝</div>
|
||
<div style="font-size: 18px; margin-bottom: 8px;">Klausur-Korrektur</div>
|
||
<div style="font-size: 14px;">Wahle eine Klausur aus oder lade neue Scans hoch</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Right: Results & Actions -->
|
||
<div style="width: 320px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px;">
|
||
<!-- OCR Results -->
|
||
<div class="card" style="padding: 16px;">
|
||
<div style="font-weight: 600; margin-bottom: 12px;">OCR-Ergebnisse</div>
|
||
<div id="ocr-results" style="max-height: 200px; overflow-y: auto; font-size: 13px; color: var(--bp-text-muted);">
|
||
<div style="text-align: center; padding: 20px;">
|
||
<div>Noch keine OCR-Ergebnisse</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Grading -->
|
||
<div class="card" style="flex: 1; padding: 16px; overflow: hidden; display: flex; flex-direction: column;">
|
||
<div style="font-weight: 600; margin-bottom: 12px;">Bewertung</div>
|
||
<div id="grading-results" style="flex: 1; overflow-y: auto;">
|
||
<div style="text-align: center; padding: 20px; color: var(--bp-text-muted);">
|
||
<div>Bewertung erfolgt nach OCR</div>
|
||
</div>
|
||
</div>
|
||
<div style="margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--bp-border);">
|
||
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
|
||
<span>Gesamt:</span>
|
||
<span id="total-points" style="font-weight: 600;">--/-- Punkte</span>
|
||
</div>
|
||
<div style="display: flex; justify-content: space-between;">
|
||
<span>Note:</span>
|
||
<span id="calculated-grade" style="font-weight: 600; font-size: 18px;">--</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Actions -->
|
||
<div class="card" style="padding: 16px;">
|
||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||
<button class="btn btn-primary" id="btn-start-correction" onclick="startCorrectionJob()" disabled>
|
||
Korrektur starten
|
||
</button>
|
||
<button class="btn btn-ghost" id="btn-export-results" onclick="exportCorrectionResults()" disabled>
|
||
Ergebnisse exportieren
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Screen 5: Elternbriefe -->
|
||
<section class="panel" id="panel-letters" style="display:none;">
|
||
<div class="panel-header">
|
||
<div>
|
||
<div class="panel-title">Elternbriefe</div>
|
||
<div class="panel-subtitle">Briefe erstellen, Vorlagen verwalten und versenden</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<button class="btn btn-sm btn-primary" onclick="createNewLetter()">+ Neuer Brief</button>
|
||
</div>
|
||
</div>
|
||
<div class="panel-body" style="display: flex; gap: 20px; height: calc(100vh - 220px);">
|
||
<!-- Left: Templates & Recent Letters -->
|
||
<div style="width: 280px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px;">
|
||
<!-- Templates -->
|
||
<div class="card" style="padding: 12px;">
|
||
<div style="font-weight: 600; margin-bottom: 10px;">Vorlagen</div>
|
||
<div style="display: flex; flex-direction: column; gap: 6px;">
|
||
<div class="template-item" onclick="loadLetterTemplate('klassenfahrt')">
|
||
<span>🏕️</span> Klassenfahrt
|
||
</div>
|
||
<div class="template-item" onclick="loadLetterTemplate('krankheit')">
|
||
<span>🏥</span> Krankmeldung
|
||
</div>
|
||
<div class="template-item" onclick="loadLetterTemplate('elternabend')">
|
||
<span>📅</span> Elternabend
|
||
</div>
|
||
<div class="template-item" onclick="loadLetterTemplate('zeugnis')">
|
||
<span>📝</span> Zeugnis-Info
|
||
</div>
|
||
<div class="template-item" onclick="loadLetterTemplate('allgemein')">
|
||
<span>📄</span> Allgemein
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Recent Letters -->
|
||
<div class="card" style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border); font-weight: 600;">
|
||
Letzte Briefe
|
||
</div>
|
||
<div id="recent-letters-list" style="flex: 1; overflow-y: auto; padding: 8px;">
|
||
<div class="letter-item" onclick="loadLetter('letter-1')">
|
||
<div class="letter-info">
|
||
<div class="letter-title">Klassenfahrt Harz</div>
|
||
<div class="letter-date">15.12.2024</div>
|
||
</div>
|
||
<div class="letter-status sent">Versendet</div>
|
||
</div>
|
||
<div class="letter-item" onclick="loadLetter('letter-2')">
|
||
<div class="letter-info">
|
||
<div class="letter-title">Elternabend Einladung</div>
|
||
<div class="letter-date">10.12.2024</div>
|
||
</div>
|
||
<div class="letter-status draft">Entwurf</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Center: Letter Editor -->
|
||
<div style="flex: 1; display: flex; flex-direction: column; gap: 12px;">
|
||
<div class="card" style="flex: 1; display: flex; flex-direction: column; overflow: hidden;">
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border);">
|
||
<input type="text" id="letter-subject" class="unit-input" placeholder="Betreff des Briefes..." style="width: 100%; font-size: 16px; font-weight: 600;">
|
||
</div>
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border); display: flex; gap: 8px; flex-wrap: wrap;">
|
||
<select id="letter-class" class="unit-input" style="width: auto;">
|
||
<option value="">Klasse wählen...</option>
|
||
<option value="7a">Klasse 7a</option>
|
||
<option value="7b">Klasse 7b</option>
|
||
<option value="8a">Klasse 8a</option>
|
||
</select>
|
||
<select id="letter-language" class="unit-input" style="width: auto;">
|
||
<option value="de">Deutsch</option>
|
||
<option value="de-tr">Deutsch + Türkisch</option>
|
||
<option value="de-ar">Deutsch + Arabisch</option>
|
||
<option value="de-uk">Deutsch + Ukrainisch</option>
|
||
</select>
|
||
<button class="btn btn-sm btn-ghost" onclick="aiImproveLetter()">✨ KI verbessern</button>
|
||
</div>
|
||
<textarea id="letter-content" style="flex: 1; padding: 16px; border: none; resize: none; font-family: inherit; font-size: 14px; line-height: 1.6; background: var(--bp-bg);" placeholder="Liebe Eltern,
|
||
|
||
schreiben Sie hier Ihren Brief...
|
||
|
||
Mit freundlichen Grüßen"></textarea>
|
||
<div style="padding: 12px; border-top: 1px solid var(--bp-border); display: flex; justify-content: space-between; align-items: center;">
|
||
<div style="display: flex; gap: 8px;">
|
||
<button class="btn btn-sm btn-ghost" onclick="previewLetter()">👁️ Vorschau</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="saveDraft()">💾 Speichern</button>
|
||
</div>
|
||
<div style="display: flex; gap: 8px;">
|
||
<button class="btn btn-sm btn-ghost" onclick="printLetter()">🖨️ Drucken</button>
|
||
<button class="btn btn-sm btn-primary" onclick="sendLetter()">📧 Versenden</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Right: Recipients & Preview -->
|
||
<div style="width: 280px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px;">
|
||
<div class="card" style="padding: 16px;">
|
||
<div style="font-weight: 600; margin-bottom: 12px;">Empfänger</div>
|
||
<div id="letter-recipients" style="font-size: 13px;">
|
||
<div style="display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid var(--bp-border);">
|
||
<span>Gesamt</span>
|
||
<span id="recipients-total">0</span>
|
||
</div>
|
||
<div style="display: flex; justify-content: space-between; padding: 6px 0;">
|
||
<span>Mit E-Mail</span>
|
||
<span id="recipients-email">0</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="card" style="flex: 1; padding: 16px;">
|
||
<div style="font-weight: 600; margin-bottom: 12px;">Brief-Vorschau</div>
|
||
<div id="letter-preview-mini" style="font-size: 11px; color: var(--bp-text-muted); line-height: 1.5;">
|
||
Wählen Sie eine Vorlage oder schreiben Sie einen Brief, um die Vorschau zu sehen.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Screen 6: Jitsi Videokonferenz -->
|
||
<section class="panel" id="panel-video" style="display:none;">
|
||
<div class="panel-header">
|
||
<div>
|
||
<div class="panel-title">Jitsi Videokonferenz</div>
|
||
<div class="panel-subtitle">Elterngespräche und Klassenkonferenzen</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<span class="small-pill" id="jitsi-connection-status" style="background: #10b981;">Bereit</span>
|
||
</div>
|
||
</div>
|
||
<div class="panel-body" style="display: flex; gap: 20px; height: calc(100vh - 220px);">
|
||
<!-- Left: Meeting Controls -->
|
||
<div style="width: 280px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px;">
|
||
<div class="card" style="padding: 12px;">
|
||
<div style="font-weight: 600; margin-bottom: 10px;">Meeting starten</div>
|
||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||
<input type="text" id="meeting-name" class="unit-input" placeholder="Meeting-Name (optional)">
|
||
<button class="btn btn-sm btn-primary" onclick="startInstantMeeting()" style="width: 100%;">
|
||
<span style="margin-right: 6px;">📹</span> Sofort starten
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="card" style="padding: 12px;">
|
||
<div style="font-weight: 600; margin-bottom: 10px;">Geplante Meetings</div>
|
||
<div id="scheduled-meetings" style="display: flex; flex-direction: column; gap: 8px;">
|
||
<div class="meeting-item" onclick="joinScheduledMeeting('m1')">
|
||
<div class="meeting-info">
|
||
<div class="meeting-title">Elterngespräch Fam. Schmidt</div>
|
||
<div class="meeting-time">Di 16:00</div>
|
||
</div>
|
||
<button class="btn btn-sm btn-ghost">Beitreten</button>
|
||
</div>
|
||
<div class="meeting-item" onclick="joinScheduledMeeting('m2')">
|
||
<div class="meeting-info">
|
||
<div class="meeting-title">Elternvertreter 7a</div>
|
||
<div class="meeting-time">Mo 18:00</div>
|
||
</div>
|
||
<button class="btn btn-sm btn-ghost">Beitreten</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="card" style="padding: 12px;">
|
||
<div style="font-weight: 600; margin-bottom: 10px;">Meeting planen</div>
|
||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||
<input type="text" id="schedule-title" class="unit-input" placeholder="Titel">
|
||
<input type="datetime-local" id="schedule-datetime" class="unit-input">
|
||
<select id="schedule-participants" class="unit-input">
|
||
<option value="">Teilnehmer wählen...</option>
|
||
<option value="class-7a">Klasse 7a (alle Eltern)</option>
|
||
<option value="elternvertreter">Elternvertreter</option>
|
||
<option value="einzeln">Einzelne Eltern</option>
|
||
</select>
|
||
<button class="btn btn-sm btn-ghost" onclick="scheduleMeeting()" style="width: 100%;">
|
||
📅 Meeting planen
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Center: Jitsi Video Container -->
|
||
<div style="flex: 1; display: flex; flex-direction: column; gap: 12px;">
|
||
<div class="card" id="jitsi-main-container" style="flex: 1; display: flex; flex-direction: column; overflow: hidden;">
|
||
<div id="jitsi-placeholder" style="flex: 1; display: flex; justify-content: center; align-items: center; background: #1a1a2e;">
|
||
<div style="text-align: center; color: #888;">
|
||
<div style="font-size: 64px; margin-bottom: 16px;">📹</div>
|
||
<div style="font-size: 18px; margin-bottom: 8px;">Keine aktive Videokonferenz</div>
|
||
<div style="font-size: 13px;">Starten Sie ein Meeting oder treten Sie einem bei</div>
|
||
</div>
|
||
</div>
|
||
<div id="jitsi-iframe-container" style="flex: 1; display: none;">
|
||
<!-- Jitsi iframe wird hier eingefügt -->
|
||
</div>
|
||
<div id="jitsi-controls" style="padding: 12px; border-top: 1px solid var(--bp-border); display: none; justify-content: center; gap: 12px;">
|
||
<button class="btn btn-sm btn-ghost" onclick="toggleJitsiMute()">🔇 Stumm</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="toggleJitsiVideo()">📷 Video</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="shareJitsiScreen()">🖥️ Teilen</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="copyMeetingLink()">🔗 Link kopieren</button>
|
||
<button class="btn btn-sm btn-danger" onclick="leaveJitsiMeeting()">🚪 Verlassen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Right: Participants & Chat -->
|
||
<div style="width: 280px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px;">
|
||
<div class="card" style="padding: 16px;">
|
||
<div style="font-weight: 600; margin-bottom: 12px;">Teilnehmer</div>
|
||
<div id="jitsi-participants" style="font-size: 13px; color: var(--bp-text-muted);">
|
||
Keine aktive Konferenz
|
||
</div>
|
||
</div>
|
||
<div class="card" style="flex: 1; padding: 16px;">
|
||
<div style="font-weight: 600; margin-bottom: 12px;">Meeting-Chat</div>
|
||
<div id="jitsi-chat" style="flex: 1; font-size: 12px; color: var(--bp-text-muted);">
|
||
Chat ist während der Konferenz verfügbar
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Screen 7: Matrix Messenger -->
|
||
<section class="panel" id="panel-messenger" style="display:none;">
|
||
<div class="panel-header">
|
||
<div>
|
||
<div class="panel-title">Matrix Messenger</div>
|
||
<div class="panel-subtitle">Sichere Kommunikation mit Eltern</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<span class="small-pill" id="comm-status-pill" style="background: #10b981;">Verbunden</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="panel-body" style="display: flex; gap: 20px; height: calc(100vh - 220px);">
|
||
<!-- Left: Room/Chat List -->
|
||
<div style="width: 280px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px;">
|
||
<!-- Quick Actions -->
|
||
<div class="card" style="padding: 12px;">
|
||
<div style="font-weight: 600; margin-bottom: 10px;">Schnellaktionen</div>
|
||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||
<button class="btn btn-sm btn-primary" onclick="startQuickMeeting()" style="width: 100%;">
|
||
<span style="margin-right: 6px;">📹</span> Sofort-Videokonferenz
|
||
</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="createClassRoom()" style="width: 100%;">
|
||
<span style="margin-right: 6px;">📢</span> Klassen-Info-Raum
|
||
</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="scheduleParentMeeting()" style="width: 100%;">
|
||
<span style="margin-right: 6px;">📅</span> Elterngespräch planen
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Rooms List -->
|
||
<div class="card" style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border); font-weight: 600;">
|
||
Meine Räume
|
||
</div>
|
||
<div id="rooms-list" style="flex: 1; overflow-y: auto; padding: 8px;">
|
||
<div class="room-item active" onclick="selectRoom('class-7a')">
|
||
<div class="room-icon">📢</div>
|
||
<div class="room-info">
|
||
<div class="room-name">Klasse 7a - Info</div>
|
||
<div class="room-preview">Letzte Nachricht vor 2h</div>
|
||
</div>
|
||
<div class="room-badge">3</div>
|
||
</div>
|
||
<div class="room-item" onclick="selectRoom('eltern-mueller')">
|
||
<div class="room-icon">👥</div>
|
||
<div class="room-info">
|
||
<div class="room-name">Familie Müller (Max)</div>
|
||
<div class="room-preview">Danke für die Info!</div>
|
||
</div>
|
||
</div>
|
||
<div class="room-item" onclick="selectRoom('elternvertreter')">
|
||
<div class="room-icon">⭐</div>
|
||
<div class="room-info">
|
||
<div class="room-name">Elternvertreter 7a</div>
|
||
<div class="room-preview">Nächstes Treffen: Mo 18:00</div>
|
||
</div>
|
||
<div class="room-badge">1</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Center: Chat/Video Area -->
|
||
<div style="flex: 1; display: flex; flex-direction: column; gap: 12px;">
|
||
<!-- Chat Header -->
|
||
<div class="card" style="padding: 12px; display: flex; justify-content: space-between; align-items: center;">
|
||
<div>
|
||
<div style="font-weight: 600;" id="current-room-name">Klasse 7a - Info</div>
|
||
<div style="font-size: 12px; color: var(--bp-text-muted);" id="current-room-members">23 Eltern, 2 Lehrer</div>
|
||
</div>
|
||
<div style="display: flex; gap: 8px;">
|
||
<button class="btn btn-sm btn-ghost" onclick="startVideoCall()" title="Videoanruf starten">📹</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="showRoomInfo()" title="Raum-Info">ℹ️</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Chat Messages -->
|
||
<div class="card" style="flex: 1; display: flex; flex-direction: column; overflow: hidden;">
|
||
<div id="chat-messages" style="flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px;">
|
||
<!-- System Message -->
|
||
<div class="chat-system-msg">
|
||
<span>📢 Klassen-Info-Kanal - Nur Lehrer können schreiben</span>
|
||
</div>
|
||
|
||
<!-- Teacher Message -->
|
||
<div class="chat-msg chat-msg-self">
|
||
<div class="chat-msg-header">
|
||
<span class="chat-msg-sender">Frau Schneider</span>
|
||
<span class="chat-msg-time">Heute, 14:30</span>
|
||
</div>
|
||
<div class="chat-msg-content">
|
||
<strong>📢 Klassenarbeit Mathematik</strong><br><br>
|
||
Liebe Eltern,<br><br>
|
||
am Freitag, 20.12.2024 schreiben wir die 2. Klassenarbeit in Mathematik.<br>
|
||
Thema: Geometrie (Dreiecke, Vierecke, Flächenberechnung).<br><br>
|
||
Bitte sorgen Sie dafür, dass Ihr Kind Geodreieck und Zirkel dabei hat.
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Notification Message -->
|
||
<div class="chat-msg chat-msg-notification">
|
||
<div class="chat-msg-header">
|
||
<span class="chat-msg-sender">System</span>
|
||
<span class="chat-msg-time">Heute, 09:15</span>
|
||
</div>
|
||
<div class="chat-msg-content">
|
||
<strong>⚠️ Abwesenheitsmeldung</strong><br><br>
|
||
<strong>Max Müller</strong> war heute in der 3. Stunde nicht im Unterricht anwesend.<br><br>
|
||
<em>Bitte bestätigen Sie den Grund der Abwesenheit.</em>
|
||
</div>
|
||
<div class="chat-msg-actions">
|
||
<button class="btn btn-sm btn-ghost">✅ Entschuldigt</button>
|
||
<button class="btn btn-sm btn-ghost">📋 Arztbesuch</button>
|
||
<button class="btn btn-sm btn-ghost">❓ Sonstiges</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Message Input (only shown for writable rooms) -->
|
||
<div id="chat-input-area" style="padding: 12px; border-top: 1px solid var(--bp-border); display: flex; gap: 8px;">
|
||
<input type="text" id="chat-message-input" class="unit-input" placeholder="Nachricht an Eltern..." style="flex: 1;">
|
||
<button class="btn btn-sm btn-ghost" onclick="attachFile()" title="Datei anhängen">📎</button>
|
||
<button class="btn btn-sm btn-primary" onclick="sendMessage()">Senden</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Right: Video/Info Panel -->
|
||
<div style="width: 320px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px;">
|
||
<!-- Jitsi Video Embed -->
|
||
<div class="card" id="video-panel" style="display: none; flex: 1;">
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border); display: flex; justify-content: space-between; align-items: center;">
|
||
<span style="font-weight: 600;">📹 Videokonferenz</span>
|
||
<button class="btn btn-sm btn-ghost" onclick="closeVideo()">✕</button>
|
||
</div>
|
||
<div id="jitsi-container" style="flex: 1; min-height: 400px; background: #1a1a2e;">
|
||
<!-- Jitsi iframe will be inserted here -->
|
||
</div>
|
||
<div style="padding: 8px; display: flex; gap: 6px; justify-content: center;">
|
||
<button class="btn btn-sm btn-ghost" onclick="toggleMute()">🔇 Stumm</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="toggleVideo()">📷 Video</button>
|
||
<button class="btn btn-sm btn-danger" onclick="leaveCall()">🚪 Verlassen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Quick Info when no video -->
|
||
<div class="card" id="info-panel" style="padding: 16px;">
|
||
<div style="font-weight: 600; margin-bottom: 12px;">Service Status</div>
|
||
<div style="display: flex; flex-direction: column; gap: 8px; font-size: 13px;">
|
||
<div style="display: flex; justify-content: space-between;">
|
||
<span>Matrix Messenger</span>
|
||
<span id="matrix-status" style="color: #10b981;">● Online</span>
|
||
</div>
|
||
<div style="display: flex; justify-content: space-between;">
|
||
<span>Jitsi Video</span>
|
||
<span id="jitsi-status" style="color: #10b981;">● Bereit</span>
|
||
</div>
|
||
</div>
|
||
<hr style="margin: 12px 0; border-color: var(--bp-border);">
|
||
<div style="font-weight: 600; margin-bottom: 8px;">Nächste Termine</div>
|
||
<div style="font-size: 12px; color: var(--bp-text-muted);">
|
||
<div style="padding: 6px 0; border-bottom: 1px solid var(--bp-border);">
|
||
<div>📅 Mo 18:00 - Elternvertreter</div>
|
||
</div>
|
||
<div style="padding: 6px 0;">
|
||
<div>📅 Di 16:00 - Gespräch Fam. Schmidt</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Send Notification Card -->
|
||
<div class="card" style="padding: 16px;">
|
||
<div style="font-weight: 600; margin-bottom: 12px;">Benachrichtigung senden</div>
|
||
<select id="notification-type" class="unit-input" style="width: 100%; margin-bottom: 8px;">
|
||
<option value="announcement">📢 Ankündigung</option>
|
||
<option value="absence">⚠️ Abwesenheit melden</option>
|
||
<option value="grade">📊 Neue Note</option>
|
||
</select>
|
||
<button class="btn btn-sm btn-primary" onclick="openNotificationDialog()" style="width: 100%;">
|
||
Benachrichtigung erstellen
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Panel: Klausuren & Tests -->
|
||
<section class="panel" id="panel-exams" style="display:none;">
|
||
<div class="panel-header">
|
||
<div>
|
||
<div class="panel-title">Klausuren & Tests</div>
|
||
<div class="panel-subtitle">Erstellen, verwalten und Nachschreiber generieren</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<select class="unit-input" id="exams-class-select" style="width: 180px;" onchange="loadExams()">
|
||
<option value="">Klasse wählen...</option>
|
||
</select>
|
||
<select class="unit-input" id="exams-subject-select" style="width: 150px;" onchange="loadExams()">
|
||
<option value="">Fach wählen...</option>
|
||
</select>
|
||
<button class="btn btn-sm btn-primary" onclick="showCreateExamModal()">+ Klausur erstellen</button>
|
||
</div>
|
||
</div>
|
||
<div class="panel-body" style="display: flex; gap: 20px; height: calc(100vh - 220px);">
|
||
<div style="width: 350px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px;">
|
||
<div class="card" style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border); font-weight: 600; display: flex; justify-content: space-between;">
|
||
<span>Meine Klausuren</span>
|
||
<span class="small-pill" id="exams-count">0</span>
|
||
</div>
|
||
<div id="exams-list" style="flex: 1; overflow-y: auto; padding: 8px;">
|
||
<div style="text-align: center; color: var(--bp-text-muted); padding: 20px;">
|
||
<div style="font-size: 24px; margin-bottom: 8px;">📝</div>
|
||
<div>Noch keine Klausuren</div>
|
||
<div style="font-size: 12px;">Erstelle deine erste Klausur</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div style="flex: 1; display: flex; flex-direction: column; gap: 12px;">
|
||
<div class="card" style="flex: 1; overflow: auto; padding: 20px;">
|
||
<div id="exam-detail-placeholder" style="text-align: center; color: var(--bp-text-muted); padding: 40px;">
|
||
<div style="font-size: 48px; margin-bottom: 12px;">📋</div>
|
||
<div style="font-size: 18px; margin-bottom: 8px;">Klausur-Details</div>
|
||
<div style="font-size: 14px;">Wähle eine Klausur aus der Liste</div>
|
||
</div>
|
||
<div id="exam-detail-content" style="display: none;">
|
||
<h3 id="exam-detail-title">Klausur-Titel</h3>
|
||
<div style="display: flex; gap: 16px; margin: 16px 0; flex-wrap: wrap;">
|
||
<span class="small-pill" id="exam-detail-type">Typ</span>
|
||
<span class="small-pill" id="exam-detail-date">Datum</span>
|
||
<span class="small-pill" id="exam-detail-points">Punkte</span>
|
||
</div>
|
||
<div style="margin: 20px 0;">
|
||
<div style="font-weight: 600; margin-bottom: 8px;">Inhalt / Aufgaben:</div>
|
||
<div id="exam-detail-content-text" style="background: var(--bp-bg); padding: 16px; border-radius: 8px; white-space: pre-wrap;"></div>
|
||
</div>
|
||
<div style="display: flex; gap: 12px; margin-top: 20px;">
|
||
<button class="btn btn-sm btn-primary" onclick="showExamResultsModal()">Ergebnisse eintragen</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="generateNachschreiber()">Nachschreiber generieren (KI)</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="editExam()">Bearbeiten</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Panel: Notenspiegel -->
|
||
<section class="panel" id="panel-grades" style="display:none;">
|
||
<div class="panel-header">
|
||
<div>
|
||
<div class="panel-title">Notenspiegel</div>
|
||
<div class="panel-subtitle">Übersicht aller Noten einer Klasse</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<select class="unit-input" id="grades-class-select" style="width: 180px;" onchange="loadGrades()">
|
||
<option value="">Klasse wählen...</option>
|
||
</select>
|
||
<select class="unit-input" id="grades-semester-select" style="width: 150px;" onchange="loadGrades()">
|
||
<option value="1">1. Halbjahr</option>
|
||
<option value="2">2. Halbjahr</option>
|
||
</select>
|
||
<button class="btn btn-sm btn-primary" onclick="calculateFinalGrades()">Endnoten berechnen</button>
|
||
</div>
|
||
</div>
|
||
<div class="panel-body" style="overflow: auto;">
|
||
<div class="card" style="padding: 20px; overflow-x: auto;">
|
||
<table style="width: 100%; border-collapse: collapse; min-width: 800px;" id="grades-table">
|
||
<thead>
|
||
<tr style="background: var(--bp-bg);">
|
||
<th style="padding: 12px; text-align: left; border-bottom: 2px solid var(--bp-border);">Schüler/in</th>
|
||
<th style="padding: 12px; text-align: center; border-bottom: 2px solid var(--bp-border);">Schriftlich</th>
|
||
<th style="padding: 12px; text-align: center; border-bottom: 2px solid var(--bp-border);">Mündlich</th>
|
||
<th style="padding: 12px; text-align: center; border-bottom: 2px solid var(--bp-border);">Endnote</th>
|
||
<th style="padding: 12px; text-align: center; border-bottom: 2px solid var(--bp-border);">Status</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="grades-table-body">
|
||
<tr>
|
||
<td colspan="5" style="padding: 40px; text-align: center; color: var(--bp-text-muted);">
|
||
<div style="font-size: 24px; margin-bottom: 8px;">📊</div>
|
||
<div>Wähle eine Klasse aus</div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Panel: Klassenbuch -->
|
||
<section class="panel" id="panel-gradebook" style="display:none;">
|
||
<div class="panel-header">
|
||
<div>
|
||
<div class="panel-title">Digitales Klassenbuch</div>
|
||
<div class="panel-subtitle">Fehlzeiten und Eintragungen verwalten</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<select class="unit-input" id="gradebook-class-select" style="width: 180px;" onchange="loadGradebook()">
|
||
<option value="">Klasse wählen...</option>
|
||
</select>
|
||
<input type="date" class="unit-input" id="gradebook-date" style="width: 150px;" onchange="loadGradebook()">
|
||
<button class="btn btn-sm btn-primary" onclick="showAttendanceModal()">Fehlzeiten eintragen</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="showGradebookEntryModal()">+ Eintrag</button>
|
||
</div>
|
||
</div>
|
||
<div class="panel-body" style="display: flex; gap: 20px; height: calc(100vh - 220px);">
|
||
<div style="width: 50%; display: flex; flex-direction: column; gap: 12px;">
|
||
<div class="card" style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border); font-weight: 600;">
|
||
Anwesenheit
|
||
</div>
|
||
<div id="attendance-list" style="flex: 1; overflow-y: auto; padding: 12px;">
|
||
<div style="text-align: center; color: var(--bp-text-muted); padding: 20px;">
|
||
<div style="font-size: 24px; margin-bottom: 8px;">📅</div>
|
||
<div>Wähle Klasse und Datum</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div style="width: 50%; display: flex; flex-direction: column; gap: 12px;">
|
||
<div class="card" style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border); font-weight: 600; display: flex; justify-content: space-between;">
|
||
<span>Eintragungen</span>
|
||
<select class="unit-input" id="gradebook-entry-type" style="width: 120px;" onchange="loadGradebookEntries()">
|
||
<option value="">Alle Typen</option>
|
||
<option value="note">Notiz</option>
|
||
<option value="warning">Ermahnung</option>
|
||
<option value="praise">Lob</option>
|
||
<option value="incident">Vorfall</option>
|
||
<option value="homework">Hausaufgaben</option>
|
||
</select>
|
||
</div>
|
||
<div id="gradebook-entries-list" style="flex: 1; overflow-y: auto; padding: 12px;">
|
||
<div style="text-align: center; color: var(--bp-text-muted); padding: 20px;">
|
||
<div style="font-size: 24px; margin-bottom: 8px;">📝</div>
|
||
<div>Keine Eintragungen</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Panel: Zeugnisse -->
|
||
<section class="panel" id="panel-certificates" style="display:none;">
|
||
<div class="panel-header">
|
||
<div>
|
||
<div class="panel-title">Zeugnisgenerator</div>
|
||
<div class="panel-subtitle">Zeugnisse erstellen und exportieren</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<select class="unit-input" id="cert-class-select" style="width: 180px;" onchange="loadCertificates()">
|
||
<option value="">Klasse wählen...</option>
|
||
</select>
|
||
<select class="unit-input" id="cert-semester-select" style="width: 150px;">
|
||
<option value="1">1. Halbjahr</option>
|
||
<option value="2">2. Halbjahr</option>
|
||
</select>
|
||
<select class="unit-input" id="cert-template-select" style="width: 180px;">
|
||
<option value="">Vorlage wählen...</option>
|
||
</select>
|
||
<button class="btn btn-sm btn-primary" onclick="generateAllCertificates()">Alle generieren</button>
|
||
</div>
|
||
</div>
|
||
<div class="panel-body" style="overflow: auto;">
|
||
<div class="card" style="padding: 20px;">
|
||
<table style="width: 100%; border-collapse: collapse;" id="certificates-table">
|
||
<thead>
|
||
<tr style="background: var(--bp-bg);">
|
||
<th style="padding: 12px; text-align: left; border-bottom: 2px solid var(--bp-border);">Schüler/in</th>
|
||
<th style="padding: 12px; text-align: center; border-bottom: 2px solid var(--bp-border);">Zeugnis-Typ</th>
|
||
<th style="padding: 12px; text-align: center; border-bottom: 2px solid var(--bp-border);">Fehlzeiten</th>
|
||
<th style="padding: 12px; text-align: center; border-bottom: 2px solid var(--bp-border);">Status</th>
|
||
<th style="padding: 12px; text-align: center; border-bottom: 2px solid var(--bp-border);">Aktionen</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="certificates-table-body">
|
||
<tr>
|
||
<td colspan="5" style="padding: 40px; text-align: center; color: var(--bp-text-muted);">
|
||
<div style="font-size: 24px; margin-bottom: 8px;">📜</div>
|
||
<div>Wähle eine Klasse aus</div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Panel: Klassen & Schüler -->
|
||
<section class="panel" id="panel-classes" style="display:none;">
|
||
<div class="panel-header">
|
||
<div>
|
||
<div class="panel-title">Klassen & Schüler</div>
|
||
<div class="panel-subtitle">Klassenverwaltung und Schülerlisten</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<select class="unit-input" id="classes-year-select" style="width: 150px;" onchange="loadClasses()">
|
||
<option value="">Schuljahr...</option>
|
||
</select>
|
||
<button class="btn btn-sm btn-primary" onclick="showCreateClassModal()">+ Klasse anlegen</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="showCreateSchoolYearModal()">+ Schuljahr</button>
|
||
</div>
|
||
</div>
|
||
<div class="panel-body" style="display: flex; gap: 20px; height: calc(100vh - 220px);">
|
||
<div style="width: 300px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px;">
|
||
<div class="card" style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border); font-weight: 600; display: flex; justify-content: space-between;">
|
||
<span>Meine Klassen</span>
|
||
<span class="small-pill" id="classes-count">0</span>
|
||
</div>
|
||
<div id="classes-list" style="flex: 1; overflow-y: auto; padding: 8px;">
|
||
<div style="text-align: center; color: var(--bp-text-muted); padding: 20px;">
|
||
<div style="font-size: 24px; margin-bottom: 8px;">🏫</div>
|
||
<div>Noch keine Klassen</div>
|
||
<div style="font-size: 12px;">Lege deine erste Klasse an</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div style="flex: 1; display: flex; flex-direction: column; gap: 12px;">
|
||
<div class="card" style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
|
||
<div style="padding: 12px; border-bottom: 1px solid var(--bp-border); font-weight: 600; display: flex; justify-content: space-between;">
|
||
<span>Schüler</span>
|
||
<div style="display: flex; gap: 8px;">
|
||
<span class="small-pill" id="students-count">0</span>
|
||
<button class="btn btn-sm btn-ghost" onclick="showAddStudentModal()">+ Schüler</button>
|
||
<button class="btn btn-sm btn-ghost" onclick="showImportStudentsModal()">CSV Import</button>
|
||
</div>
|
||
</div>
|
||
<div id="students-list" style="flex: 1; overflow-y: auto; padding: 8px;">
|
||
<div style="text-align: center; color: var(--bp-text-muted); padding: 20px;">
|
||
<div style="font-size: 24px; margin-bottom: 8px;">👥</div>
|
||
<div>Wähle eine Klasse aus</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Panel: Fächer -->
|
||
<section class="panel" id="panel-subjects" style="display:none;">
|
||
<div class="panel-header">
|
||
<div>
|
||
<div class="panel-title">Fächer verwalten</div>
|
||
<div class="panel-subtitle">Unterrichtsfächer anlegen und bearbeiten</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<button class="btn btn-sm btn-primary" onclick="showCreateSubjectModal()">+ Fach anlegen</button>
|
||
</div>
|
||
</div>
|
||
<div class="panel-body">
|
||
<div class="card" style="padding: 20px;">
|
||
<div id="subjects-list" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 16px;">
|
||
<div style="text-align: center; color: var(--bp-text-muted); padding: 40px; grid-column: 1 / -1;">
|
||
<div style="font-size: 24px; margin-bottom: 8px;">📚</div>
|
||
<div>Noch keine Fächer angelegt</div>
|
||
<div style="font-size: 12px;">Lege dein erstes Fach an</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<div class="pager">
|
||
<button id="pager-prev"><</button>
|
||
<span id="pager-label">1 von 2</span>
|
||
<button id="pager-next">></button>
|
||
</div>
|
||
|
||
<div class="status-bar" id="status-bar">
|
||
<div class="status-dot" id="status-dot"></div>
|
||
<div>
|
||
<div class="status-text-main" id="status-main"></div>
|
||
<div class="status-text-sub" id="status-sub"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Vollbild-Overlay -->
|
||
<div class="lightbox hidden" id="lightbox">
|
||
<div class="lightbox-inner">
|
||
<button type="button" class="lightbox-close" id="lightbox-close">Schließen ✕</button>
|
||
<img id="lightbox-img" class="lightbox-img" src="" alt="">
|
||
<div id="lightbox-caption" class="lightbox-caption"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MC Quiz Modal -->
|
||
<div class="mc-modal hidden" id="mc-modal">
|
||
<div class="mc-modal-content">
|
||
<div class="mc-modal-header">
|
||
<div class="mc-modal-title">Multiple Choice Quiz</div>
|
||
<button type="button" class="mc-modal-close" id="mc-modal-close">Schließen ✕</button>
|
||
</div>
|
||
<div id="mc-modal-body"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Cloze / Lückentext Modal -->
|
||
<div class="mc-modal hidden" id="cloze-modal">
|
||
<div class="mc-modal-content" style="max-width:700px;">
|
||
<div class="mc-modal-header">
|
||
<div class="mc-modal-title">Lückentext-Übung</div>
|
||
<button type="button" class="mc-modal-close" id="cloze-modal-close">Schließen ✕</button>
|
||
</div>
|
||
<div id="cloze-modal-body"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Q&A / Frage-Antwort Modal mit Leitner-System -->
|
||
<div class="mc-modal hidden" id="qa-modal">
|
||
<div class="mc-modal-content" style="max-width:700px;">
|
||
<div class="mc-modal-header">
|
||
<div class="mc-modal-title">Frage-Antwort Lernmodus</div>
|
||
<button type="button" class="mc-modal-close" id="qa-modal-close">Schließen ✕</button>
|
||
</div>
|
||
<div id="qa-modal-body"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="footer">
|
||
<span>© 2025 BreakPilot</span>
|
||
<span style="display: flex; gap: 12px; font-size: 11px;">
|
||
<a href="#" onclick="openImprintModal(); return false;" style="color: var(--bp-text-muted);">Impressum</a>
|
||
<a href="#" onclick="openLegalModal('terms'); return false;" style="color: var(--bp-text-muted);">AGB</a>
|
||
<a href="#" onclick="openLegalModal('privacy'); return false;" style="color: var(--bp-text-muted);">Datenschutz</a>
|
||
<a href="#" onclick="openLegalModal('cookies'); return false;" style="color: var(--bp-text-muted);">Cookies</a>
|
||
<a href="#" onclick="openLegalModal('gdpr'); return false;" style="color: var(--bp-text-muted);">Deine Rechte</a>
|
||
<a href="#" onclick="openSettingsModal(); return false;" style="color: var(--bp-text-muted);">Einstellungen</a>
|
||
</span>
|
||
</div>
|
||
|
||
|
||
|
||
<!-- Admin Panel Modal -->
|
||
<div id="admin-modal" class="admin-modal">
|
||
<div class="admin-modal-content">
|
||
<div class="admin-modal-header">
|
||
<h2><span>⚙️</span> Consent Admin Panel</h2>
|
||
<button id="admin-modal-close" class="legal-modal-close">×</button>
|
||
</div>
|
||
<div class="admin-tabs">
|
||
<button class="admin-tab active" data-tab="documents">Dokumente</button>
|
||
<button class="admin-tab" data-tab="versions">Versionen</button>
|
||
<button class="admin-tab" data-tab="cookies">Cookie-Kategorien</button>
|
||
<button class="admin-tab" data-tab="stats">Statistiken</button>
|
||
<button class="admin-tab" data-tab="emails">E-Mail Vorlagen</button>
|
||
<button class="admin-tab" data-tab="dsr">Betroffenenanfragen</button>
|
||
<button class="admin-tab" data-tab="dsms">DSMS</button>
|
||
</div>
|
||
<div class="admin-body">
|
||
<!-- Documents Tab -->
|
||
<div id="admin-documents" class="admin-content active">
|
||
<div class="admin-toolbar">
|
||
<div class="admin-toolbar-left">
|
||
<input type="text" class="admin-search" placeholder="Dokumente suchen..." id="admin-doc-search">
|
||
</div>
|
||
<button class="btn btn-primary btn-sm" onclick="showDocumentForm()">+ Neues Dokument</button>
|
||
</div>
|
||
|
||
<!-- Document Creation Form -->
|
||
<div id="admin-document-form" class="admin-form" style="display: none;">
|
||
<h3 class="admin-form-title" id="admin-document-form-title">Neues Dokument erstellen</h3>
|
||
<input type="hidden" id="admin-document-id">
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Dokumenttyp *</label>
|
||
<select class="admin-form-select" id="admin-document-type">
|
||
<option value="">-- Typ auswählen --</option>
|
||
<option value="terms">AGB (Allgemeine Geschäftsbedingungen)</option>
|
||
<option value="privacy">Datenschutzerklärung</option>
|
||
<option value="cookies">Cookie-Richtlinie</option>
|
||
<option value="community">Community Guidelines</option>
|
||
<option value="imprint">Impressum</option>
|
||
</select>
|
||
</div>
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Name *</label>
|
||
<input type="text" class="admin-form-input" id="admin-document-name" placeholder="z.B. Allgemeine Geschäftsbedingungen">
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group full-width">
|
||
<label class="admin-form-label">Beschreibung</label>
|
||
<input type="text" class="admin-form-input" id="admin-document-description" placeholder="Kurze Beschreibung des Dokuments">
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">
|
||
<input type="checkbox" id="admin-document-mandatory" style="margin-right: 8px;">
|
||
Pflichtdokument (Nutzer müssen zustimmen)
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-actions">
|
||
<button class="btn btn-ghost btn-sm" onclick="hideDocumentForm()">Abbrechen</button>
|
||
<button class="btn btn-primary btn-sm" onclick="saveDocument()">Dokument erstellen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="admin-doc-table-container">
|
||
<div class="admin-loading">Lade Dokumente...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Versions Tab -->
|
||
<div id="admin-versions" class="admin-content">
|
||
<div class="admin-toolbar">
|
||
<div class="admin-toolbar-left">
|
||
<select class="admin-form-select" id="admin-version-doc-select" onchange="loadVersionsForDocument()">
|
||
<option value="">-- Dokument auswählen --</option>
|
||
</select>
|
||
</div>
|
||
<button class="btn btn-primary btn-sm" onclick="showVersionForm()" id="btn-new-version" disabled>+ Neue Version</button>
|
||
</div>
|
||
|
||
<div id="admin-version-form" class="admin-form">
|
||
<h3 class="admin-form-title" id="admin-version-form-title">Neue Version erstellen</h3>
|
||
<input type="hidden" id="admin-version-id">
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Version *</label>
|
||
<input type="text" class="admin-form-input" id="admin-version-number" placeholder="z.B. 1.0.0">
|
||
</div>
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Sprache *</label>
|
||
<select class="admin-form-select" id="admin-version-lang">
|
||
<option value="de">Deutsch</option>
|
||
<option value="en">English</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group full-width">
|
||
<label class="admin-form-label">Titel *</label>
|
||
<input type="text" class="admin-form-input" id="admin-version-title" placeholder="Titel der Version">
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group full-width">
|
||
<label class="admin-form-label">Zusammenfassung</label>
|
||
<input type="text" class="admin-form-input" id="admin-version-summary" placeholder="Kurze Zusammenfassung der Änderungen">
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group full-width">
|
||
<label class="admin-form-label">Inhalt *</label>
|
||
<div class="editor-container">
|
||
<div class="editor-toolbar">
|
||
<div class="editor-toolbar-group">
|
||
<button type="button" class="editor-btn" onclick="formatDoc('bold')" title="Fett (Strg+B)"><b>B</b></button>
|
||
<button type="button" class="editor-btn" onclick="formatDoc('italic')" title="Kursiv (Strg+I)"><i>I</i></button>
|
||
<button type="button" class="editor-btn" onclick="formatDoc('underline')" title="Unterstrichen (Strg+U)"><u>U</u></button>
|
||
</div>
|
||
<div class="editor-toolbar-group">
|
||
<button type="button" class="editor-btn" onclick="formatBlock('h1')" title="Überschrift 1">H1</button>
|
||
<button type="button" class="editor-btn" onclick="formatBlock('h2')" title="Überschrift 2">H2</button>
|
||
<button type="button" class="editor-btn" onclick="formatBlock('h3')" title="Überschrift 3">H3</button>
|
||
<button type="button" class="editor-btn" onclick="formatBlock('p')" title="Absatz">P</button>
|
||
</div>
|
||
<div class="editor-toolbar-group">
|
||
<button type="button" class="editor-btn" onclick="formatDoc('insertUnorderedList')" title="Aufzählung">• Liste</button>
|
||
<button type="button" class="editor-btn" onclick="formatDoc('insertOrderedList')" title="Nummerierung">1. Liste</button>
|
||
</div>
|
||
<div class="editor-toolbar-group">
|
||
<button type="button" class="editor-btn" onclick="insertLink()" title="Link einfügen">🔗</button>
|
||
<button type="button" class="editor-btn" onclick="formatDoc('formatBlock', 'blockquote')" title="Zitat">❝</button>
|
||
<button type="button" class="editor-btn" onclick="formatDoc('insertHorizontalRule')" title="Trennlinie">—</button>
|
||
</div>
|
||
<div class="editor-toolbar-group">
|
||
<button type="button" class="editor-btn editor-btn-upload" onclick="document.getElementById('word-upload').click()" title="Word-Dokument importieren">📄 Word Import</button>
|
||
<input type="file" id="word-upload" class="word-upload-input" accept=".docx,.doc" onchange="handleWordUpload(event)">
|
||
</div>
|
||
</div>
|
||
<div id="admin-version-editor" class="editor-content" contenteditable="true" placeholder="Schreiben Sie hier den Inhalt..."></div>
|
||
<div class="editor-status">
|
||
<span id="editor-char-count">0 Zeichen</span> |
|
||
<span style="color: var(--bp-text-muted);">Tipp: Sie können direkt aus Word kopieren und einfügen!</span>
|
||
</div>
|
||
</div>
|
||
<input type="hidden" id="admin-version-content">
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-actions">
|
||
<button class="btn btn-ghost btn-sm" onclick="hideVersionForm()">Abbrechen</button>
|
||
<button class="btn btn-primary btn-sm" onclick="saveVersion()">Speichern</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="admin-version-table-container">
|
||
<div class="admin-empty">Wählen Sie ein Dokument aus, um dessen Versionen anzuzeigen.</div>
|
||
</div>
|
||
|
||
<!-- Approval Dialog -->
|
||
<div id="approval-dialog" class="admin-dialog">
|
||
<div class="admin-dialog-content">
|
||
<h3>Version genehmigen</h3>
|
||
<p class="admin-dialog-info">
|
||
Legen Sie einen Veröffentlichungszeitpunkt fest. Die Version wird automatisch zum gewählten Zeitpunkt veröffentlicht.
|
||
</p>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Veröffentlichungsdatum *</label>
|
||
<input type="date" class="admin-form-input" id="approval-date" required>
|
||
</div>
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Uhrzeit</label>
|
||
<input type="time" class="admin-form-input" id="approval-time" value="00:00">
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group full-width">
|
||
<label class="admin-form-label">Kommentar (optional)</label>
|
||
<input type="text" class="admin-form-input" id="approval-comment" placeholder="z.B. Genehmigt nach rechtlicher Prüfung">
|
||
</div>
|
||
</div>
|
||
<div class="admin-dialog-actions">
|
||
<button class="btn btn-ghost btn-sm" onclick="hideApprovalDialog()">Abbrechen</button>
|
||
<button class="btn btn-primary btn-sm" onclick="submitApproval()">Genehmigen & Planen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Version Compare View (Full Screen Overlay) -->
|
||
<div id="version-compare-view" class="version-compare-overlay">
|
||
<div class="version-compare-header">
|
||
<h2>Versionsvergleich</h2>
|
||
<div class="version-compare-info">
|
||
<span id="compare-published-info"></span>
|
||
<span class="compare-vs">vs</span>
|
||
<span id="compare-draft-info"></span>
|
||
</div>
|
||
<button class="btn btn-ghost" onclick="hideCompareView()">Schließen</button>
|
||
</div>
|
||
<div class="version-compare-container">
|
||
<div class="version-compare-panel">
|
||
<div class="version-compare-panel-header">
|
||
<span class="compare-label compare-label-published">Veröffentlichte Version</span>
|
||
<span id="compare-published-version"></span>
|
||
</div>
|
||
<div class="version-compare-content" id="compare-content-left"></div>
|
||
</div>
|
||
<div class="version-compare-panel">
|
||
<div class="version-compare-panel-header">
|
||
<span class="compare-label compare-label-draft">Neue Version</span>
|
||
<span id="compare-draft-version"></span>
|
||
</div>
|
||
<div class="version-compare-content" id="compare-content-right"></div>
|
||
</div>
|
||
</div>
|
||
<div class="version-compare-footer">
|
||
<div id="compare-history-container"></div>
|
||
<div id="compare-actions-container" style="display: flex; gap: 12px; justify-content: flex-end; margin-top: 12px;"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Cookie Categories Tab -->
|
||
<div id="admin-cookies" class="admin-content">
|
||
<div class="admin-toolbar">
|
||
<div class="admin-toolbar-left">
|
||
<span style="color: var(--bp-text-muted);">Cookie-Kategorien verwalten</span>
|
||
</div>
|
||
<button class="btn btn-primary btn-sm" onclick="showCookieForm()">+ Neue Kategorie</button>
|
||
</div>
|
||
|
||
<div id="admin-cookie-form" class="admin-form">
|
||
<h3 class="admin-form-title">Neue Cookie-Kategorie</h3>
|
||
<input type="hidden" id="admin-cookie-id">
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Technischer Name *</label>
|
||
<input type="text" class="admin-form-input" id="admin-cookie-name" placeholder="z.B. analytics">
|
||
</div>
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Anzeigename (DE) *</label>
|
||
<input type="text" class="admin-form-input" id="admin-cookie-display-de" placeholder="z.B. Analyse-Cookies">
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Anzeigename (EN)</label>
|
||
<input type="text" class="admin-form-input" id="admin-cookie-display-en" placeholder="z.B. Analytics Cookies">
|
||
</div>
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">
|
||
<input type="checkbox" id="admin-cookie-mandatory"> Notwendig (kann nicht deaktiviert werden)
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group full-width">
|
||
<label class="admin-form-label">Beschreibung (DE)</label>
|
||
<input type="text" class="admin-form-input" id="admin-cookie-desc-de" placeholder="Beschreibung auf Deutsch">
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-actions">
|
||
<button class="btn btn-ghost btn-sm" onclick="hideCookieForm()">Abbrechen</button>
|
||
<button class="btn btn-primary btn-sm" onclick="saveCookieCategory()">Speichern</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="admin-cookie-table-container">
|
||
<div class="admin-loading">Lade Cookie-Kategorien...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Statistics Tab -->
|
||
<div id="admin-stats" class="admin-content">
|
||
<div id="admin-stats-container">
|
||
<div class="admin-loading">Lade Statistiken...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- E-Mail Templates Tab -->
|
||
<div id="admin-emails" class="admin-content">
|
||
<div class="admin-toolbar">
|
||
<div class="admin-toolbar-left">
|
||
<select class="admin-form-select" id="email-template-select" onchange="loadEmailTemplateVersions()">
|
||
<option value="">-- E-Mail-Vorlage auswählen --</option>
|
||
</select>
|
||
</div>
|
||
<button class="btn btn-ghost btn-sm" onclick="initializeEmailTemplates()">Templates initialisieren</button>
|
||
<button class="btn btn-primary btn-sm" onclick="showEmailVersionForm()" id="btn-new-email-version" disabled>+ Neue Version</button>
|
||
</div>
|
||
|
||
<!-- E-Mail Template Info Card -->
|
||
<div id="email-template-info" style="display: none; margin-bottom: 16px;">
|
||
<div style="background: var(--bp-surface-elevated); border-radius: 8px; padding: 16px; border: 1px solid var(--bp-border);">
|
||
<div style="display: flex; justify-content: space-between; align-items: start;">
|
||
<div>
|
||
<h3 style="margin: 0 0 8px 0; font-size: 16px;" id="email-template-name">-</h3>
|
||
<p style="margin: 0; color: var(--bp-text-muted); font-size: 13px;" id="email-template-description">-</p>
|
||
</div>
|
||
<div style="text-align: right;">
|
||
<div class="admin-badge" id="email-template-type-badge">-</div>
|
||
</div>
|
||
</div>
|
||
<div style="margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--bp-border);">
|
||
<span style="font-size: 12px; color: var(--bp-text-muted);">Variablen: </span>
|
||
<span id="email-template-variables" style="font-size: 12px; font-family: monospace; color: var(--bp-primary);"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- E-Mail Version Form -->
|
||
<div id="email-version-form" class="admin-form" style="display: none;">
|
||
<h3 class="admin-form-title" id="email-version-form-title">Neue E-Mail-Version erstellen</h3>
|
||
<input type="hidden" id="email-version-id">
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Version *</label>
|
||
<input type="text" class="admin-form-input" id="email-version-number" placeholder="z.B. 1.0.0">
|
||
</div>
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Sprache *</label>
|
||
<select class="admin-form-select" id="email-version-lang">
|
||
<option value="de">Deutsch</option>
|
||
<option value="en">English</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group full-width">
|
||
<label class="admin-form-label">Betreff *</label>
|
||
<input type="text" class="admin-form-input" id="email-version-subject" placeholder="E-Mail Betreff (kann Variablen enthalten)">
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group full-width">
|
||
<label class="admin-form-label">HTML-Inhalt *</label>
|
||
<div class="editor-container">
|
||
<div class="editor-toolbar">
|
||
<div class="editor-toolbar-group">
|
||
<button type="button" class="editor-btn" onclick="formatEmailDoc('bold')" title="Fett"><b>B</b></button>
|
||
<button type="button" class="editor-btn" onclick="formatEmailDoc('italic')" title="Kursiv"><i>I</i></button>
|
||
<button type="button" class="editor-btn" onclick="formatEmailDoc('underline')" title="Unterstrichen"><u>U</u></button>
|
||
</div>
|
||
<div class="editor-toolbar-group">
|
||
<button type="button" class="editor-btn" onclick="formatEmailBlock('h1')" title="Überschrift 1">H1</button>
|
||
<button type="button" class="editor-btn" onclick="formatEmailBlock('h2')" title="Überschrift 2">H2</button>
|
||
<button type="button" class="editor-btn" onclick="formatEmailBlock('p')" title="Absatz">P</button>
|
||
</div>
|
||
<div class="editor-toolbar-group">
|
||
<button type="button" class="editor-btn" onclick="insertEmailVariable()" title="Variable einfügen">{{var}}</button>
|
||
<button type="button" class="editor-btn" onclick="insertEmailLink()" title="Link einfügen">🔗</button>
|
||
<button type="button" class="editor-btn" onclick="insertEmailButton()" title="Button einfügen">🔘</button>
|
||
</div>
|
||
</div>
|
||
<div id="email-version-editor" class="editor-content" contenteditable="true" placeholder="HTML-Inhalt der E-Mail..." style="min-height: 200px;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group full-width">
|
||
<label class="admin-form-label">Text-Version (Plain Text)</label>
|
||
<textarea class="admin-form-input" id="email-version-text" rows="5" placeholder="Plain-Text-Version der E-Mail (optional, wird aus HTML generiert falls leer)"></textarea>
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-actions">
|
||
<button class="btn btn-ghost btn-sm" onclick="hideEmailVersionForm()">Abbrechen</button>
|
||
<button class="btn btn-ghost btn-sm" onclick="previewEmailVersion()">Vorschau</button>
|
||
<button class="btn btn-primary btn-sm" onclick="saveEmailVersion()">Speichern</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- E-Mail Versions Table -->
|
||
<div id="email-version-table-container">
|
||
<div class="admin-empty">Wählen Sie eine E-Mail-Vorlage aus, um deren Versionen anzuzeigen.</div>
|
||
</div>
|
||
|
||
<!-- E-Mail Preview Dialog -->
|
||
<div id="email-preview-dialog" class="admin-dialog" style="display: none;">
|
||
<div class="admin-dialog-content" style="max-width: 700px; max-height: 80vh; overflow-y: auto;">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
||
<h3 style="margin: 0;">E-Mail Vorschau</h3>
|
||
<button class="btn btn-ghost btn-sm" onclick="hideEmailPreview()">Schließen</button>
|
||
</div>
|
||
<div style="margin-bottom: 12px;">
|
||
<strong>Betreff:</strong> <span id="email-preview-subject"></span>
|
||
</div>
|
||
<div style="border: 1px solid var(--bp-border); border-radius: 8px; padding: 16px; background: white; color: #333;">
|
||
<div id="email-preview-content"></div>
|
||
</div>
|
||
<div style="margin-top: 16px; display: flex; gap: 8px;">
|
||
<input type="email" class="admin-form-input" id="email-test-address" placeholder="Test-E-Mail-Adresse" style="flex: 1;">
|
||
<button class="btn btn-primary btn-sm" onclick="sendTestEmail()">Test-E-Mail senden</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- E-Mail Approval Dialog -->
|
||
<div id="email-approval-dialog" class="admin-dialog" style="display: none;">
|
||
<div class="admin-dialog-content">
|
||
<h3>E-Mail-Version genehmigen</h3>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group full-width">
|
||
<label class="admin-form-label">Kommentar (optional)</label>
|
||
<input type="text" class="admin-form-input" id="email-approval-comment" placeholder="z.B. Genehmigt nach Marketing-Prüfung">
|
||
</div>
|
||
</div>
|
||
<div class="admin-dialog-actions">
|
||
<button class="btn btn-ghost btn-sm" onclick="hideEmailApprovalDialog()">Abbrechen</button>
|
||
<button class="btn btn-primary btn-sm" onclick="submitEmailApproval()">Genehmigen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- DSR (Betroffenenanfragen) Tab -->
|
||
<div id="admin-dsr" class="admin-content">
|
||
<div class="admin-toolbar">
|
||
<div class="admin-toolbar-left">
|
||
<select class="admin-form-select" id="dsr-filter-status" onchange="loadDSRList()" style="min-width: 150px;">
|
||
<option value="">Alle Status</option>
|
||
<option value="intake">Eingang</option>
|
||
<option value="identity_verification">Identitätsprüfung</option>
|
||
<option value="processing">In Bearbeitung</option>
|
||
<option value="completed">Abgeschlossen</option>
|
||
<option value="rejected">Abgelehnt</option>
|
||
<option value="cancelled">Storniert</option>
|
||
</select>
|
||
<select class="admin-form-select" id="dsr-filter-type" onchange="loadDSRList()" style="min-width: 150px;">
|
||
<option value="">Alle Typen</option>
|
||
<option value="access">Art. 15 - Auskunft</option>
|
||
<option value="rectification">Art. 16 - Berichtigung</option>
|
||
<option value="erasure">Art. 17 - Löschung</option>
|
||
<option value="restriction">Art. 18 - Einschränkung</option>
|
||
<option value="portability">Art. 20 - Datenübertragbarkeit</option>
|
||
</select>
|
||
<label style="display: flex; align-items: center; gap: 4px; font-size: 13px; color: var(--bp-text-muted);">
|
||
<input type="checkbox" id="dsr-filter-overdue" onchange="loadDSRList()">
|
||
Nur überfällige
|
||
</label>
|
||
</div>
|
||
<button class="btn btn-primary btn-sm" onclick="showDSRCreateForm()">+ Neue Anfrage</button>
|
||
</div>
|
||
|
||
<!-- DSR Stats Dashboard -->
|
||
<div id="dsr-stats-cards" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; margin: 16px 0;">
|
||
<div class="admin-loading">Lade Statistiken...</div>
|
||
</div>
|
||
|
||
<!-- DSR Create Form -->
|
||
<div id="dsr-create-form" class="admin-form" style="display: none;">
|
||
<h3 class="admin-form-title">Neue Betroffenenanfrage erstellen</h3>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Anfragetyp *</label>
|
||
<select class="admin-form-select" id="dsr-create-type" required>
|
||
<option value="">-- Typ wählen --</option>
|
||
<option value="access">Art. 15 - Auskunftsrecht</option>
|
||
<option value="rectification">Art. 16 - Recht auf Berichtigung</option>
|
||
<option value="erasure">Art. 17 - Recht auf Löschung</option>
|
||
<option value="restriction">Art. 18 - Recht auf Einschränkung</option>
|
||
<option value="portability">Art. 20 - Recht auf Datenübertragbarkeit</option>
|
||
</select>
|
||
</div>
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Priorität</label>
|
||
<select class="admin-form-select" id="dsr-create-priority">
|
||
<option value="normal">Normal</option>
|
||
<option value="high">Hoch</option>
|
||
<option value="expedited">Beschleunigt</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">E-Mail des Antragstellers *</label>
|
||
<input type="email" class="admin-form-input" id="dsr-create-email" required placeholder="email@example.com">
|
||
</div>
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Name des Antragstellers</label>
|
||
<input type="text" class="admin-form-input" id="dsr-create-name" placeholder="Max Mustermann">
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group full-width">
|
||
<label class="admin-form-label">Telefon</label>
|
||
<input type="text" class="admin-form-input" id="dsr-create-phone" placeholder="+49 123 456789">
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-actions">
|
||
<button class="btn btn-ghost btn-sm" onclick="hideDSRCreateForm()">Abbrechen</button>
|
||
<button class="btn btn-primary btn-sm" onclick="createDSR()">Anfrage erstellen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- DSR Table -->
|
||
<div id="dsr-table-container">
|
||
<div class="admin-loading">Lade Betroffenenanfragen...</div>
|
||
</div>
|
||
|
||
<!-- DSR Detail View -->
|
||
<div id="dsr-detail-view" style="display: none;">
|
||
<div class="admin-toolbar" style="margin-bottom: 16px;">
|
||
<button class="btn btn-ghost btn-sm" onclick="hideDSRDetail()">← Zurück zur Liste</button>
|
||
<div style="display: flex; gap: 8px;">
|
||
<button class="btn btn-ghost btn-sm" id="dsr-btn-verify" onclick="verifyDSRIdentity()">Identität verifizieren</button>
|
||
<button class="btn btn-ghost btn-sm" id="dsr-btn-assign" onclick="showDSRAssignDialog()">Zuweisen</button>
|
||
<button class="btn btn-ghost btn-sm" id="dsr-btn-extend" onclick="showDSRExtendDialog()">Frist verlängern</button>
|
||
<button class="btn btn-primary btn-sm" id="dsr-btn-complete" onclick="showDSRCompleteDialog()">Abschließen</button>
|
||
<button class="btn btn-danger btn-sm" id="dsr-btn-reject" onclick="showDSRRejectDialog()">Ablehnen</button>
|
||
</div>
|
||
</div>
|
||
<div id="dsr-detail-content"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- DSMS Tab -->
|
||
<div id="admin-dsms" class="admin-content">
|
||
<div class="admin-toolbar">
|
||
<div class="admin-toolbar-left">
|
||
<span style="font-weight: 600; color: var(--bp-primary);">Dezentrales Speichersystem (IPFS)</span>
|
||
</div>
|
||
<div style="display: flex; gap: 8px;">
|
||
<button class="btn btn-ghost btn-sm" onclick="openDsmsWebUI()">DSMS WebUI</button>
|
||
<button class="btn btn-primary btn-sm" onclick="loadDsmsData()">Aktualisieren</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- DSMS Status Cards -->
|
||
<div id="dsms-status-cards" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px;">
|
||
<div class="admin-loading">Lade DSMS Status...</div>
|
||
</div>
|
||
|
||
<!-- DSMS Tabs -->
|
||
<div style="display: flex; gap: 8px; margin-bottom: 16px; border-bottom: 1px solid var(--bp-border); padding-bottom: 8px;">
|
||
<button class="dsms-subtab active" data-dsms-tab="archives" onclick="switchDsmsTab('archives')">Archivierte Dokumente</button>
|
||
<button class="dsms-subtab" data-dsms-tab="verify" onclick="switchDsmsTab('verify')">Verifizierung</button>
|
||
<button class="dsms-subtab" data-dsms-tab="settings" onclick="switchDsmsTab('settings')">Einstellungen</button>
|
||
</div>
|
||
|
||
<!-- Archives Sub-Tab -->
|
||
<div id="dsms-archives" class="dsms-content active">
|
||
<div class="admin-toolbar" style="margin-bottom: 16px;">
|
||
<div class="admin-toolbar-left">
|
||
<input type="text" class="admin-search" placeholder="CID suchen..." id="dsms-cid-search" style="width: 300px;">
|
||
</div>
|
||
<button class="btn btn-primary btn-sm" onclick="showArchiveForm()">+ Dokument archivieren</button>
|
||
</div>
|
||
|
||
<!-- Archive Form -->
|
||
<div id="dsms-archive-form" class="admin-form" style="display: none; margin-bottom: 16px;">
|
||
<h3 class="admin-form-title">Dokument im DSMS archivieren</h3>
|
||
<div class="admin-form-row">
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Dokument auswählen *</label>
|
||
<select class="admin-form-select" id="dsms-archive-doc-select">
|
||
<option value="">-- Dokument wählen --</option>
|
||
</select>
|
||
</div>
|
||
<div class="admin-form-group">
|
||
<label class="admin-form-label">Version *</label>
|
||
<select class="admin-form-select" id="dsms-archive-version-select" disabled>
|
||
<option value="">-- Erst Dokument wählen --</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-actions">
|
||
<button class="btn btn-ghost btn-sm" onclick="hideArchiveForm()">Abbrechen</button>
|
||
<button class="btn btn-primary btn-sm" onclick="archiveDocumentToDsms()">Archivieren</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="dsms-archives-table">
|
||
<div class="admin-loading">Lade archivierte Dokumente...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Verify Sub-Tab -->
|
||
<div id="dsms-verify" class="dsms-content" style="display: none;">
|
||
<div style="background: var(--bp-surface-elevated); border-radius: 8px; padding: 24px; border: 1px solid var(--bp-border);">
|
||
<h3 style="margin: 0 0 16px 0; font-size: 16px;">Dokumentenintegrität prüfen</h3>
|
||
<p style="color: var(--bp-text-muted); margin-bottom: 16px; font-size: 14px;">
|
||
Geben Sie einen CID (Content Identifier) ein, um die Integrität eines archivierten Dokuments zu verifizieren.
|
||
</p>
|
||
<div style="display: flex; gap: 12px; margin-bottom: 16px;">
|
||
<input type="text" class="admin-form-input" id="dsms-verify-cid" placeholder="Qm... oder bafy..." style="flex: 1;">
|
||
<button class="btn btn-primary btn-sm" onclick="verifyDsmsDocument()">Verifizieren</button>
|
||
</div>
|
||
<div id="dsms-verify-result" style="display: none;"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Settings Sub-Tab -->
|
||
<div id="dsms-settings" class="dsms-content" style="display: none;">
|
||
<div style="display: grid; gap: 16px;">
|
||
<!-- Node Info -->
|
||
<div style="background: var(--bp-surface-elevated); border-radius: 8px; padding: 24px; border: 1px solid var(--bp-border);">
|
||
<h3 style="margin: 0 0 16px 0; font-size: 16px;">Node-Informationen</h3>
|
||
<div id="dsms-node-info">
|
||
<div class="admin-loading">Lade Node-Info...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Quick Links -->
|
||
<div style="background: var(--bp-surface-elevated); border-radius: 8px; padding: 24px; border: 1px solid var(--bp-border);">
|
||
<h3 style="margin: 0 0 16px 0; font-size: 16px;">Schnellzugriff</h3>
|
||
<div style="display: flex; flex-wrap: wrap; gap: 12px;">
|
||
<button class="btn btn-primary btn-sm" onclick="openDsmsWebUI()">DSMS WebUI</button>
|
||
<a href="http://localhost:8082/docs" target="_blank" class="btn btn-ghost btn-sm">DSMS API Docs</a>
|
||
<a href="http://localhost:8085" target="_blank" class="btn btn-ghost btn-sm">IPFS Gateway</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Lizenzhinweise -->
|
||
<div style="background: var(--bp-surface-elevated); border-radius: 8px; padding: 24px; border: 1px solid var(--bp-border);">
|
||
<h3 style="margin: 0 0 16px 0; font-size: 16px;">Open Source Lizenzen</h3>
|
||
<p style="color: var(--bp-text-muted); font-size: 13px; margin-bottom: 12px;">
|
||
DSMS verwendet folgende Open-Source-Komponenten:
|
||
</p>
|
||
<ul style="color: var(--bp-text-muted); font-size: 13px; margin: 0; padding-left: 20px;">
|
||
<li><strong>IPFS Kubo</strong> - MIT + Apache 2.0 (Dual License) - Protocol Labs, Inc.</li>
|
||
<li><strong>IPFS WebUI</strong> - MIT License - Protocol Labs, Inc.</li>
|
||
<li><strong>FastAPI</strong> - MIT License</li>
|
||
</ul>
|
||
<p style="color: var(--bp-text-muted); font-size: 12px; margin-top: 12px; font-style: italic;">
|
||
Alle Komponenten erlauben kommerzielle Nutzung.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- DSMS WebUI Modal -->
|
||
<div id="dsms-webui-modal" class="legal-modal" style="display: none;">
|
||
<div class="legal-modal-content" style="max-width: 1200px; width: 95%; height: 90vh;">
|
||
<div class="legal-modal-header" style="border-bottom: 1px solid var(--bp-border);">
|
||
<h2 style="display: flex; align-items: center; gap: 10px;">
|
||
<span style="font-size: 24px;">🌐</span> DSMS WebUI
|
||
</h2>
|
||
<button id="dsms-webui-modal-close" class="legal-modal-close" onclick="closeDsmsWebUI()">×</button>
|
||
</div>
|
||
<div style="display: flex; height: calc(100% - 60px);">
|
||
<!-- Sidebar -->
|
||
<div style="width: 200px; background: var(--bp-surface); border-right: 1px solid var(--bp-border); padding: 16px;">
|
||
<nav style="display: flex; flex-direction: column; gap: 4px;">
|
||
<button class="dsms-webui-nav active" data-section="overview" onclick="switchDsmsWebUISection('overview')">
|
||
<span>📈</span> Übersicht
|
||
</button>
|
||
<button class="dsms-webui-nav" data-section="files" onclick="switchDsmsWebUISection('files')">
|
||
<span>📁</span> Dateien
|
||
</button>
|
||
<button class="dsms-webui-nav" data-section="explore" onclick="switchDsmsWebUISection('explore')">
|
||
<span>🔍</span> Erkunden
|
||
</button>
|
||
<button class="dsms-webui-nav" data-section="peers" onclick="switchDsmsWebUISection('peers')">
|
||
<span>🌐</span> Peers
|
||
</button>
|
||
<button class="dsms-webui-nav" data-section="config" onclick="switchDsmsWebUISection('config')">
|
||
<span>⚙</span> Konfiguration
|
||
</button>
|
||
</nav>
|
||
</div>
|
||
<!-- Main Content -->
|
||
<div style="flex: 1; overflow-y: auto; padding: 24px;" id="dsms-webui-content">
|
||
<!-- Overview Section (default) -->
|
||
<div id="dsms-webui-overview" class="dsms-webui-section active">
|
||
<h3 style="margin: 0 0 24px 0;">Node Übersicht</h3>
|
||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px;">
|
||
<div class="dsms-webui-stat-card">
|
||
<div class="dsms-webui-stat-label">Status</div>
|
||
<div class="dsms-webui-stat-value" id="webui-status">--</div>
|
||
</div>
|
||
<div class="dsms-webui-stat-card">
|
||
<div class="dsms-webui-stat-label">Node ID</div>
|
||
<div class="dsms-webui-stat-value" id="webui-node-id" style="font-size: 11px; word-break: break-all;">--</div>
|
||
</div>
|
||
<div class="dsms-webui-stat-card">
|
||
<div class="dsms-webui-stat-label">Protokoll</div>
|
||
<div class="dsms-webui-stat-value" id="webui-protocol">--</div>
|
||
</div>
|
||
<div class="dsms-webui-stat-card">
|
||
<div class="dsms-webui-stat-label">Agent</div>
|
||
<div class="dsms-webui-stat-value" id="webui-agent">--</div>
|
||
</div>
|
||
</div>
|
||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px;">
|
||
<div class="dsms-webui-stat-card">
|
||
<div class="dsms-webui-stat-label">Repo Größe</div>
|
||
<div class="dsms-webui-stat-value" id="webui-repo-size">--</div>
|
||
<div class="dsms-webui-stat-sub" id="webui-storage-info">--</div>
|
||
</div>
|
||
<div class="dsms-webui-stat-card">
|
||
<div class="dsms-webui-stat-label">Objekte</div>
|
||
<div class="dsms-webui-stat-value" id="webui-num-objects">--</div>
|
||
</div>
|
||
<div class="dsms-webui-stat-card">
|
||
<div class="dsms-webui-stat-label">Gepinnte Dokumente</div>
|
||
<div class="dsms-webui-stat-value" id="webui-pinned-count">--</div>
|
||
</div>
|
||
</div>
|
||
<div style="margin-top: 24px;">
|
||
<h4 style="margin: 0 0 12px 0;">Adressen</h4>
|
||
<div id="webui-addresses" style="background: var(--bp-input-bg); border-radius: 8px; padding: 12px; font-family: monospace; font-size: 12px; max-height: 150px; overflow-y: auto;">
|
||
Lade...
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Files Section -->
|
||
<div id="dsms-webui-files" class="dsms-webui-section" style="display: none;">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px;">
|
||
<h3 style="margin: 0;">Dateien hochladen</h3>
|
||
</div>
|
||
<div class="dsms-webui-upload-zone" id="dsms-upload-zone" ondrop="handleDsmsFileDrop(event)" ondragover="handleDsmsDragOver(event)" ondragleave="handleDsmsDragLeave(event)">
|
||
<div style="text-align: center;">
|
||
<div style="font-size: 48px; margin-bottom: 16px;">📥</div>
|
||
<p style="color: var(--bp-text); margin-bottom: 8px;">Dateien hierher ziehen</p>
|
||
<p style="color: var(--bp-text-muted); font-size: 13px;">oder</p>
|
||
<input type="file" id="dsms-file-input" style="display: none;" onchange="handleDsmsFileSelect(event)" multiple>
|
||
<button class="btn btn-primary btn-sm" onclick="document.getElementById('dsms-file-input').click()">Dateien auswählen</button>
|
||
</div>
|
||
</div>
|
||
<div id="dsms-upload-progress" style="display: none; margin-top: 16px;">
|
||
<div style="background: var(--bp-surface-elevated); border-radius: 8px; padding: 16px;">
|
||
<div id="dsms-upload-status">Hochladen...</div>
|
||
<div style="background: var(--bp-border); border-radius: 4px; height: 8px; margin-top: 8px; overflow: hidden;">
|
||
<div id="dsms-upload-bar" style="background: var(--bp-primary); height: 100%; width: 0%; transition: width 0.3s;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="dsms-upload-results" style="margin-top: 24px;"></div>
|
||
</div>
|
||
|
||
<!-- Explore Section -->
|
||
<div id="dsms-webui-explore" class="dsms-webui-section" style="display: none;">
|
||
<h3 style="margin: 0 0 24px 0;">IPFS Explorer</h3>
|
||
<div style="display: flex; gap: 12px; margin-bottom: 24px;">
|
||
<input type="text" class="admin-search" placeholder="CID eingeben (z.B. QmXyz...)" id="webui-explore-cid" style="flex: 1;">
|
||
<button class="btn btn-primary btn-sm" onclick="exploreDsmsCid()">Erkunden</button>
|
||
</div>
|
||
<div id="dsms-explore-result" style="display: none;">
|
||
<div style="background: var(--bp-surface-elevated); border-radius: 8px; padding: 16px;">
|
||
<div id="dsms-explore-content"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Peers Section -->
|
||
<div id="dsms-webui-peers" class="dsms-webui-section" style="display: none;">
|
||
<h3 style="margin: 0 0 24px 0;">Verbundene Peers</h3>
|
||
<p style="color: var(--bp-text-muted); margin-bottom: 16px;">
|
||
Hinweis: In einem privaten DSMS-Netzwerk sind normalerweise keine externen Peers verbunden.
|
||
</p>
|
||
<div id="webui-peers-list">
|
||
<div class="admin-loading">Lade Peers...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Config Section -->
|
||
<div id="dsms-webui-config" class="dsms-webui-section" style="display: none;">
|
||
<h3 style="margin: 0 0 24px 0;">Konfiguration</h3>
|
||
<div style="display: grid; gap: 16px;">
|
||
<div style="background: var(--bp-surface-elevated); border-radius: 8px; padding: 16px;">
|
||
<h4 style="margin: 0 0 12px 0;">API Endpoints</h4>
|
||
<table style="width: 100%; font-size: 13px;">
|
||
<tr>
|
||
<td style="padding: 8px 0; color: var(--bp-text-muted);">IPFS API</td>
|
||
<td style="padding: 8px 0; font-family: monospace;">http://localhost:5001</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="padding: 8px 0; color: var(--bp-text-muted);">DSMS Gateway</td>
|
||
<td style="padding: 8px 0; font-family: monospace;">http://localhost:8082</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="padding: 8px 0; color: var(--bp-text-muted);">IPFS Gateway</td>
|
||
<td style="padding: 8px 0; font-family: monospace;">http://localhost:8085</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="padding: 8px 0; color: var(--bp-text-muted);">Swarm P2P</td>
|
||
<td style="padding: 8px 0; font-family: monospace;">:4001</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
<div style="background: var(--bp-surface-elevated); border-radius: 8px; padding: 16px;">
|
||
<h4 style="margin: 0 0 12px 0;">Aktionen</h4>
|
||
<div style="display: flex; flex-wrap: wrap; gap: 12px;">
|
||
<button class="btn btn-ghost btn-sm" onclick="runDsmsGarbageCollection()">🗑 Garbage Collection</button>
|
||
<button class="btn btn-ghost btn-sm" onclick="loadDsmsWebUIData()">↻ Daten aktualisieren</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Legal Modal -->
|
||
<div id="legal-modal" class="legal-modal">
|
||
<div class="legal-modal-content">
|
||
<div class="legal-modal-header">
|
||
<h2>Rechtliches</h2>
|
||
<button id="legal-modal-close" class="legal-modal-close">×</button>
|
||
</div>
|
||
<div class="legal-tabs">
|
||
<button class="legal-tab active" data-tab="terms">AGB</button>
|
||
<button class="legal-tab" data-tab="privacy">Datenschutz</button>
|
||
<button class="legal-tab" data-tab="community">Community Guidelines</button>
|
||
<button class="legal-tab" data-tab="cookies">Cookie-Einstellungen</button>
|
||
<button class="legal-tab" data-tab="gdpr">DSGVO-Rechte</button>
|
||
</div>
|
||
<div class="legal-body">
|
||
<div id="legal-terms" class="legal-content active">
|
||
<div id="legal-terms-content">
|
||
<div class="legal-loading">Lade AGB...</div>
|
||
</div>
|
||
</div>
|
||
<div id="legal-privacy" class="legal-content">
|
||
<div id="legal-privacy-content">
|
||
<div class="legal-loading">Lade Datenschutzerklärung...</div>
|
||
</div>
|
||
</div>
|
||
<div id="legal-community" class="legal-content">
|
||
<div id="legal-community-content">
|
||
<div class="legal-loading">Lade Community Guidelines...</div>
|
||
</div>
|
||
</div>
|
||
<div id="legal-cookies" class="legal-content">
|
||
<h3>Cookie-Einstellungen</h3>
|
||
<p>Wir verwenden Cookies, um Ihnen die bestmögliche Erfahrung zu bieten. Hier können Sie Ihre Präferenzen jederzeit anpassen.</p>
|
||
<div id="cookie-categories-container" class="cookie-categories">
|
||
<div class="legal-loading">Lade Cookie-Kategorien...</div>
|
||
</div>
|
||
<button class="btn btn-primary" style="margin-top:16px" onclick="saveCookiePreferences()">Einstellungen speichern</button>
|
||
</div>
|
||
<div id="legal-gdpr" class="legal-content">
|
||
<h3>Ihre DSGVO-Rechte (Art. 15-21)</h3>
|
||
<p>Nach der Datenschutz-Grundverordnung haben Sie folgende Rechte:</p>
|
||
<div class="gdpr-actions">
|
||
<div class="gdpr-action">
|
||
<h4>📋 Auskunftsrecht (Art. 15)</h4>
|
||
<p>Erfahren Sie, welche personenbezogenen Daten wir über Sie verarbeiten.</p>
|
||
<button class="btn btn-sm" onclick="requestDataExport()">Auskunft anfordern</button>
|
||
</div>
|
||
<div class="gdpr-action">
|
||
<h4>✏️ Recht auf Berichtigung (Art. 16)</h4>
|
||
<p>Lassen Sie unrichtige Daten korrigieren oder unvollständige Daten ergänzen.</p>
|
||
<button class="btn btn-sm" onclick="requestDataCorrection()">Berichtigung beantragen</button>
|
||
</div>
|
||
<div class="gdpr-action">
|
||
<h4>🗑️ Recht auf Löschung (Art. 17)</h4>
|
||
<p>Beantragen Sie die vollständige Löschung Ihrer personenbezogenen Daten.</p>
|
||
<button class="btn btn-sm btn-danger" onclick="requestDataDeletion()">Löschung beantragen</button>
|
||
</div>
|
||
<div class="gdpr-action">
|
||
<h4>⏸️ Einschränkung der Verarbeitung (Art. 18)</h4>
|
||
<p>Verlangen Sie die Einschränkung der Verarbeitung Ihrer Daten.</p>
|
||
<button class="btn btn-sm" onclick="requestProcessingRestriction()">Einschränkung beantragen</button>
|
||
</div>
|
||
<div class="gdpr-action">
|
||
<h4>📢 Mitteilungspflicht (Art. 19)</h4>
|
||
<p>Wir informieren alle Empfänger über Berichtigungen, Löschungen oder Einschränkungen.</p>
|
||
<span style="color: var(--bp-text-muted); font-size: 12px;">Automatisch bei Berichtigung/Löschung</span>
|
||
</div>
|
||
<div class="gdpr-action">
|
||
<h4>📤 Datenübertragbarkeit (Art. 20)</h4>
|
||
<p>Exportieren Sie Ihre Daten in einem maschinenlesbaren Format (JSON).</p>
|
||
<button class="btn btn-sm" onclick="requestDataDownload()">Daten exportieren</button>
|
||
</div>
|
||
<div class="gdpr-action">
|
||
<h4>🚫 Widerspruchsrecht (Art. 21)</h4>
|
||
<p>Widersprechen Sie der Verarbeitung Ihrer Daten für bestimmte Zwecke.</p>
|
||
<button class="btn btn-sm" onclick="requestProcessingObjection()">Widerspruch einlegen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="margin-top: 24px; padding: 16px; background: var(--bp-surface-elevated); border-radius: 8px; border: 1px solid var(--bp-border);">
|
||
<h4 style="margin-top: 0;">Ihre Einwilligungen verwalten</h4>
|
||
<p style="margin-bottom: 12px;">Sehen und widerrufen Sie Ihre erteilten Einwilligungen.</p>
|
||
<button class="btn btn-sm" onclick="showConsentManager()">Einwilligungen verwalten</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Imprint Modal (Impressum - muss direkt erreichbar sein) -->
|
||
<div id="imprint-modal" class="legal-modal">
|
||
<div class="legal-modal-content">
|
||
<div class="legal-modal-header">
|
||
<h2>Impressum</h2>
|
||
<button id="imprint-modal-close" class="legal-modal-close">×</button>
|
||
</div>
|
||
<div class="legal-body" style="padding: 24px;">
|
||
<div id="imprint-content">
|
||
<div class="legal-loading">Lade Impressum...</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Auth Modal -->
|
||
<div id="auth-modal" class="auth-modal">
|
||
<div class="auth-modal-content">
|
||
<div class="auth-modal-header">
|
||
<h2><span>🔐</span> Anmeldung</h2>
|
||
<button id="auth-modal-close" class="legal-modal-close">×</button>
|
||
</div>
|
||
<div class="auth-tabs">
|
||
<button class="auth-tab active" data-tab="login">Anmelden</button>
|
||
<button class="auth-tab" data-tab="register">Registrieren</button>
|
||
</div>
|
||
<div class="auth-body">
|
||
<!-- Login Tab -->
|
||
<div id="auth-login" class="auth-content active">
|
||
<div id="auth-login-error" class="auth-error"></div>
|
||
<div id="auth-login-success" class="auth-success"></div>
|
||
<form id="auth-login-form">
|
||
<div class="auth-form-group">
|
||
<label class="auth-form-label">E-Mail</label>
|
||
<input type="email" class="auth-form-input" id="login-email" placeholder="ihre@email.de" required>
|
||
</div>
|
||
<div class="auth-form-group">
|
||
<label class="auth-form-label">Passwort</label>
|
||
<input type="password" class="auth-form-input" id="login-password" placeholder="Ihr Passwort" required>
|
||
</div>
|
||
<button type="submit" class="auth-btn auth-btn-primary" id="login-btn">Anmelden</button>
|
||
</form>
|
||
<div class="auth-link">
|
||
<a href="#" id="auth-forgot-password">Passwort vergessen?</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Register Tab -->
|
||
<div id="auth-register" class="auth-content">
|
||
<div id="auth-register-error" class="auth-error"></div>
|
||
<div id="auth-register-success" class="auth-success"></div>
|
||
<form id="auth-register-form">
|
||
<div class="auth-form-group">
|
||
<label class="auth-form-label">Name (optional)</label>
|
||
<input type="text" class="auth-form-input" id="register-name" placeholder="Ihr Name">
|
||
</div>
|
||
<div class="auth-form-group">
|
||
<label class="auth-form-label">E-Mail</label>
|
||
<input type="email" class="auth-form-input" id="register-email" placeholder="ihre@email.de" required>
|
||
</div>
|
||
<div class="auth-form-group">
|
||
<label class="auth-form-label">Passwort</label>
|
||
<input type="password" class="auth-form-input" id="register-password" placeholder="Mind. 8 Zeichen" required minlength="8">
|
||
</div>
|
||
<div class="auth-form-group">
|
||
<label class="auth-form-label">Passwort bestätigen</label>
|
||
<input type="password" class="auth-form-input" id="register-password-confirm" placeholder="Passwort wiederholen" required>
|
||
</div>
|
||
<button type="submit" class="auth-btn auth-btn-primary" id="register-btn">Registrieren</button>
|
||
</form>
|
||
<div class="auth-link">
|
||
Bereits registriert? <a href="#" id="auth-goto-login">Hier anmelden</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Forgot Password Tab (hidden by default) -->
|
||
<div id="auth-forgot" class="auth-content">
|
||
<div id="auth-forgot-error" class="auth-error"></div>
|
||
<div id="auth-forgot-success" class="auth-success"></div>
|
||
<p style="color: var(--bp-text-muted); font-size: 13px; margin-bottom: 16px;">
|
||
Geben Sie Ihre E-Mail-Adresse ein und wir senden Ihnen einen Link zum Zurücksetzen Ihres Passworts.
|
||
</p>
|
||
<form id="auth-forgot-form">
|
||
<div class="auth-form-group">
|
||
<label class="auth-form-label">E-Mail</label>
|
||
<input type="email" class="auth-form-input" id="forgot-email" placeholder="ihre@email.de" required>
|
||
</div>
|
||
<button type="submit" class="auth-btn auth-btn-primary" id="forgot-btn">Link senden</button>
|
||
</form>
|
||
<div class="auth-link">
|
||
<a href="#" id="auth-back-to-login">Zurück zur Anmeldung</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Reset Password Tab (hidden by default, shown via URL token) -->
|
||
<div id="auth-reset" class="auth-content">
|
||
<div id="auth-reset-error" class="auth-error"></div>
|
||
<div id="auth-reset-success" class="auth-success"></div>
|
||
<form id="auth-reset-form">
|
||
<div class="auth-form-group">
|
||
<label class="auth-form-label">Neues Passwort</label>
|
||
<input type="password" class="auth-form-input" id="reset-password" placeholder="Mind. 8 Zeichen" required minlength="8">
|
||
</div>
|
||
<div class="auth-form-group">
|
||
<label class="auth-form-label">Passwort bestätigen</label>
|
||
<input type="password" class="auth-form-input" id="reset-password-confirm" placeholder="Passwort wiederholen" required>
|
||
</div>
|
||
<input type="hidden" id="reset-token">
|
||
<button type="submit" class="auth-btn auth-btn-primary" id="reset-btn">Passwort ändern</button>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- Email Verification Tab (hidden by default, shown via URL token) -->
|
||
<div id="auth-verify" class="auth-content">
|
||
<div id="auth-verify-error" class="auth-error"></div>
|
||
<div id="auth-verify-success" class="auth-success"></div>
|
||
<div style="text-align: center; padding: 20px 0;">
|
||
<div id="auth-verify-loading" style="color: var(--bp-text-muted);">
|
||
E-Mail wird verifiziert...
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Notification Preferences Modal -->
|
||
<div id="notification-prefs-modal" class="notification-prefs-modal">
|
||
<div class="notification-prefs-content">
|
||
<div class="auth-modal-header">
|
||
<h2>Benachrichtigungseinstellungen</h2>
|
||
<button class="legal-modal-close" onclick="closeNotificationPreferences()">×</button>
|
||
</div>
|
||
<div class="auth-body">
|
||
<div class="notification-pref-item">
|
||
<div>
|
||
<div class="notification-pref-label">E-Mail-Benachrichtigungen</div>
|
||
<div class="notification-pref-desc">Wichtige Updates per E-Mail erhalten</div>
|
||
</div>
|
||
<div class="toggle-switch active" id="pref-email-toggle" onclick="toggleNotificationPref('email')">
|
||
<div class="toggle-switch-handle"></div>
|
||
</div>
|
||
</div>
|
||
<div class="notification-pref-item">
|
||
<div>
|
||
<div class="notification-pref-label">In-App-Benachrichtigungen</div>
|
||
<div class="notification-pref-desc">Benachrichtigungen in der App anzeigen</div>
|
||
</div>
|
||
<div class="toggle-switch active" id="pref-inapp-toggle" onclick="toggleNotificationPref('inapp')">
|
||
<div class="toggle-switch-handle"></div>
|
||
</div>
|
||
</div>
|
||
<div class="notification-pref-item">
|
||
<div>
|
||
<div class="notification-pref-label">Push-Benachrichtigungen</div>
|
||
<div class="notification-pref-desc">Browser-Push-Benachrichtigungen aktivieren</div>
|
||
</div>
|
||
<div class="toggle-switch" id="pref-push-toggle" onclick="toggleNotificationPref('push')">
|
||
<div class="toggle-switch-handle"></div>
|
||
</div>
|
||
</div>
|
||
<div style="margin-top: 20px;">
|
||
<button class="auth-btn auth-btn-primary" onclick="saveNotificationPreferences()">Speichern</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Suspension Overlay -->
|
||
<div id="suspension-overlay" class="suspension-overlay">
|
||
<div class="suspension-content">
|
||
<div class="suspension-icon">🚫</div>
|
||
<div class="suspension-title">Account vorübergehend gesperrt</div>
|
||
<div class="suspension-message">
|
||
Ihr Account wurde gesperrt, da ausstehende Zustimmungen nicht innerhalb der Frist erteilt wurden.
|
||
Bitte bestätigen Sie die folgenden Dokumente, um Ihren Account wiederherzustellen.
|
||
</div>
|
||
<div class="suspension-docs">
|
||
<div class="suspension-docs-title">Ausstehende Dokumente:</div>
|
||
<div id="suspension-doc-list">
|
||
<!-- Will be populated dynamically -->
|
||
</div>
|
||
</div>
|
||
<button class="suspension-btn" onclick="showConsentModal()">
|
||
Jetzt bestätigen
|
||
</button>
|
||
<div class="suspension-countdown" id="suspension-countdown"></div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
<script src="/static/js/studio.js"></script>
|
||
</body>
|
||
</html> |