Files
quiz/app/templates/admin.html
T

314 lines
17 KiB
HTML
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}⚡ Zaubereiministerium – Cockpit{% endblock %}
{% block content %}
<div class="admin-wrapper">
<div class="admin-header">
<div>
<h1 class="glow-title">⚡ Großinquisitor-Cockpit</h1>
<p class="subtitle">Eingeloggt als: <strong>{{ admin_user }}</strong></p>
</div>
<div class="admin-top-actions">
<a href="/" target="_blank" class="btn btn-secondary">🌐 Zum Live-Quiz</a>
<a href="/admin/logout" class="btn btn-danger">🚪 Abmelden</a>
</div>
</div>
<!-- Navigation Tabs -->
<div class="tabs-nav">
<button class="tab-btn active" onclick="showTab('tab-pending')">
📥 Eingereichte Vorschläge
{% if pending_questions|length > 0 %}
<span class="badge badge-warning">{{ pending_questions|length }}</span>
{% endif %}
</button>
<button class="tab-btn" onclick="showTab('tab-active')">
📜 Aktive Quiz-Fragen
<span class="badge badge-info">{{ active_questions|length }}</span>
</button>
<button class="tab-btn" onclick="showTab('tab-new')">
➕ Neue Frage anlegen
</button>
{% if rejected_questions|length > 0 %}
<button class="tab-btn" onclick="showTab('tab-rejected')">
❌ Archiviert / Abgelehnt
<span class="badge badge-muted">{{ rejected_questions|length }}</span>
</button>
{% endif %}
</div>
<!-- TAB 1: Eingereichte Vorschläge (User Questions Need Test) -->
<section id="tab-pending" class="tab-content active">
<h2>📥 Eingegangene Vorschläge (Prüfung & Validierung erforderlich)</h2>
<p class="description">Diese Fragen wurden von Besuchern eingereicht. Bitte teste die Antwort und schalte die Frage frei oder lehne sie ab.</p>
{% if pending_questions|length == 0 %}
<div class="empty-state">
<p>🎉 Keine offenen Vorschläge zur Prüfung vorhanden!</p>
</div>
{% else %}
<div class="questions-list">
{% for q in pending_questions %}
<div class="card question-admin-card" id="q-card-{{ q.id }}">
<div class="q-header">
<div style="display: flex; gap: 8px; align-items: center;">
<span class="badge badge-warning">⚠️ Prüfung ausstehend</span>
<span class="badge badge-diff badge-diff-{{ q.difficulty or 'medium' }}">{{ (q.difficulty or 'medium')|capitalize }}</span>
{% if q.question_type == 'multiple_choice' %}
<span class="badge" style="background: rgba(155, 89, 182, 0.2); border-color: #9b59b6; color: #d2b4de;">🔘 Multiple-Choice</span>
{% else %}
<span class="badge badge-muted">🔤 Freitext</span>
{% endif %}
</div>
<span class="q-submitter">Von: <strong>{{ q.submitted_by or 'Gast' }}</strong> am {{ q.created_at.strftime('%d.%m.%Y %H:%M') }}</span>
</div>
<div class="q-body">
<h3>{{ q.question }}</h3>
<p><strong>Erwartete Antwort:</strong> <span class="highlight-answer">{{ q.canonical_answer }}</span></p>
{% if q.options %}
<p style="margin-top: 5px;"><strong>Auswahl-Optionen:</strong> <code>{{ q.options }}</code></p>
{% endif %}
{% if q.hint %}
<p style="margin-top: 5px;"><strong>Tipp:</strong> <em>{{ q.hint }}</em></p>
{% endif %}
<!-- Interaktives Testfeld für den Admin -->
<div class="test-matcher-box">
<label>🧪 Antwort-Validierung testen:</label>
<div class="test-input-group">
<input type="text" id="test-input-{{ q.id }}" class="input-text-sm" placeholder="Test-Eingabe (z.B. mit Tippfehler)">
<button type="button" class="btn btn-sm btn-secondary" onclick="testMatcher({{ q.id }}, '{{ q.canonical_answer|escape }}')">Testen</button>
</div>
<div id="test-result-{{ q.id }}" class="test-result-feedback"></div>
</div>
</div>
<div class="q-actions">
<button class="btn btn-success" onclick="approveQuestion({{ q.id }})">
✅ Freischalten & Aktivieren
</button>
<button class="btn btn-secondary" onclick="toggleEdit({{ q.id }})">
✏️ Bearbeiten
</button>
<button class="btn btn-danger" onclick="rejectQuestion({{ q.id }})">
❌ Ablehnen
</button>
</div>
<!-- Inline Edit Form (Hidden by default) -->
<div id="edit-form-{{ q.id }}" class="inline-edit-form hidden">
<form action="/admin/questions/{{ q.id }}/edit" method="post">
<div class="form-group">
<label>Frage:</label>
<input type="text" name="question" class="input-text" value="{{ q.question }}" required>
</div>
<div class="form-group">
<label>Fragentyp:</label>
<select name="question_type" class="input-text">
<option value="text" {% if q.question_type != 'multiple_choice' %}selected{% endif %}>🔤 Freitext</option>
<option value="multiple_choice" {% if q.question_type == 'multiple_choice' %}selected{% endif %}>🔘 Multiple Choice</option>
</select>
</div>
<div class="form-group">
<label>Richtige Antwort:</label>
<input type="text" name="canonical_answer" class="input-text" value="{{ q.canonical_answer }}" required>
</div>
<div class="form-group">
<label>Optionen (JSON-Liste oder Komma-getrennt für Multiple Choice):</label>
<input type="text" name="options_raw" class="input-text" value="{{ q.options or '' }}">
</div>
<div class="form-group">
<label>Tipp:</label>
<input type="text" name="hint" class="input-text" value="{{ q.hint or '' }}">
</div>
<input type="hidden" name="status_val" value="active">
<button type="submit" class="btn btn-primary">Speichern & Aktivieren</button>
</form>
</div>
</div>
{% endfor %}
</div>
{% endif %}
</section>
<!-- TAB 2: Aktive Fragen -->
<section id="tab-active" class="tab-content">
<h2>📜 Aktive Fragen im Live-Quiz ({{ active_questions|length }})</h2>
<p class="description">Diese Fragen werden den Spielern in der angegebenen Reihenfolge gestellt.</p>
<div class="questions-list">
{% for q in active_questions %}
<div class="card question-admin-card" id="q-card-{{ q.id }}">
<div class="q-header">
<div style="display: flex; gap: 8px; align-items: center;">
<span class="badge badge-success">Reihenfolge #{{ q.sort_order }}</span>
<span class="badge badge-diff badge-diff-{{ q.difficulty or 'medium' }}">{{ (q.difficulty or 'medium')|capitalize }}</span>
{% if q.question_type == 'multiple_choice' %}
<span class="badge" style="background: rgba(155, 89, 182, 0.2); border-color: #9b59b6; color: #d2b4de;">🔘 Multiple-Choice</span>
{% else %}
<span class="badge badge-muted">🔤 Freitext</span>
{% endif %}
</div>
<span class="q-category">Kategorie: {{ q.category }}</span>
</div>
<div class="q-body">
<h3>{{ loop.index }}. {{ q.question }}</h3>
<p><strong>Antwort:</strong> <span class="highlight-answer">{{ q.canonical_answer }}</span></p>
{% if q.options %}
<p style="margin-top: 5px;"><strong>Optionen:</strong> <code>{{ q.options }}</code></p>
{% endif %}
{% if q.hint %}
<p style="margin-top: 5px;"><strong>Tipp:</strong> <em>{{ q.hint }}</em></p>
{% endif %}
</div>
<div class="q-actions">
<button class="btn btn-secondary btn-sm" onclick="toggleEdit({{ q.id }})">✏️ Bearbeiten</button>
<button class="btn btn-danger btn-sm" onclick="deleteQuestion({{ q.id }})">🗑️ Löschen</button>
</div>
<!-- Inline Edit Form -->
<div id="edit-form-{{ q.id }}" class="inline-edit-form hidden">
<form action="/admin/questions/{{ q.id }}/edit" method="post">
<div class="form-group">
<label>Frage:</label>
<input type="text" name="question" class="input-text" value="{{ q.question }}" required>
</div>
<div class="form-group">
<label>Fragentyp:</label>
<select name="question_type" class="input-text">
<option value="text" {% if q.question_type != 'multiple_choice' %}selected{% endif %}>🔤 Freitext</option>
<option value="multiple_choice" {% if q.question_type == 'multiple_choice' %}selected{% endif %}>🔘 Multiple Choice</option>
</select>
</div>
<div class="form-group">
<label>Schwierigkeitsgrad:</label>
<select name="difficulty" class="input-text">
<option value="easy" {% if q.difficulty == 'easy' %}selected{% endif %}>🟢 Leicht</option>
<option value="medium" {% if q.difficulty == 'medium' or not q.difficulty %}selected{% endif %}>🟡 Mittel</option>
<option value="hard" {% if q.difficulty == 'hard' %}selected{% endif %}>🔴 Schwer</option>
</select>
</div>
<div class="form-group">
<label>Richtige Antwort:</label>
<input type="text" name="canonical_answer" class="input-text" value="{{ q.canonical_answer }}" required>
</div>
<div class="form-group">
<label>Optionen (JSON-Liste oder Komma-getrennt für Multiple Choice):</label>
<input type="text" name="options_raw" class="input-text" value="{{ q.options or '' }}">
</div>
<div class="form-group">
<label>Tipp:</label>
<input type="text" name="hint" class="input-text" value="{{ q.hint or '' }}">
</div>
<div class="form-group">
<label>Reihenfolge (Sort Order):</label>
<input type="number" name="sort_order" class="input-text-sm" value="{{ q.sort_order }}">
</div>
<input type="hidden" name="status_val" value="active">
<button type="submit" class="btn btn-primary">Änderungen speichern</button>
</form>
</div>
</div>
{% endfor %}
</div>
</section>
<!-- TAB 3: Neue Frage anlegen -->
<section id="tab-new" class="tab-content">
<h2>➕ Neue Frage direkt zum Live-Quiz hinzufügen</h2>
<div class="card">
<form action="/admin/questions/new" method="post" class="magic-form">
<div class="form-group">
<label for="category">Kategorie:</label>
<select name="category" id="category" class="input-text">
<option value="harry_potter" selected>Harry Potter / Escape</option>
<option value="insider">Persönlich / Insider</option>
<option value="general">Allgemeines Rätsel</option>
</select>
</div>
<div class="form-group">
<label for="new_diff">Schwierigkeitsgrad:</label>
<select name="difficulty" id="new_diff" class="input-text">
<option value="easy">🟢 Leicht</option>
<option value="medium" selected>🟡 Mittel</option>
<option value="hard">🔴 Schwer</option>
</select>
</div>
<div class="form-group">
<label for="new_type">Fragentyp:</label>
<select name="question_type" id="new_type" class="input-text" onchange="toggleAdminNewType(this.value)">
<option value="text" selected>🔤 Freitext-Eingabe (Tippen)</option>
<option value="multiple_choice">🔘 Multiple Choice (Auswahl)</option>
</select>
</div>
<div class="form-group">
<label for="new_question">Frage:</label>
<textarea name="question" id="new_question" class="textarea" rows="2" required placeholder="z. B. Welcher Zauber entwaffnet Gegner?"></textarea>
</div>
<div class="form-group">
<label for="new_answer">Richtige Antwort:</label>
<input type="text" name="canonical_answer" id="new_answer" class="input-text" required placeholder="z. B. Expelliarmus">
</div>
<!-- Multiple Choice Optionen für Admin -->
<div id="adminMcOptions" class="form-group hidden" style="background: rgba(255,255,255,0.03); padding: 15px; border-radius: 8px; border: 1px dashed var(--border-gold);">
<label style="color: var(--gold);">Falsche Optionen für Multiple Choice (Optionen 2 bis 4):</label>
<input type="text" name="wrong_option_1" class="input-text" placeholder="Falsche Option 1 (z.B. Stupor)" style="margin-bottom: 8px;">
<input type="text" name="wrong_option_2" class="input-text" placeholder="Falsche Option 2 (z.B. Lumos)" style="margin-bottom: 8px;">
<input type="text" name="wrong_option_3" class="input-text" placeholder="Falsche Option 3 (z.B. Alohomora)">
</div>
<div class="form-group">
<label for="new_hint">Tipp (optional):</label>
<input type="text" name="hint" id="new_hint" class="input-text" placeholder="z. B. Harrys Lieblingszauber">
</div>
<div class="form-group">
<label for="new_sort">Reihenfolge (Nummerierung):</label>
<input type="number" name="sort_order" id="new_sort" class="input-text-sm" value="{{ active_questions|length + 1 }}">
</div>
<button type="submit" class="btn btn-primary btn-large">Frage speichern & aktivieren</button>
</form>
</div>
</section>
<!-- TAB 4: Archiviert / Abgelehnt -->
{% if rejected_questions|length > 0 %}
<section id="tab-rejected" class="tab-content">
<h2>❌ Abgelehnte / Archivierte Vorschläge</h2>
<div class="questions-list">
{% for q in rejected_questions %}
<div class="card question-admin-card muted-card" id="q-card-{{ q.id }}">
<div class="q-header">
<span class="badge badge-danger">Abgelehnt</span>
<span class="q-submitter">Eingereicht von: {{ q.submitted_by or 'Gast' }}</span>
</div>
<div class="q-body">
<h3>{{ q.question }}</h3>
<p><strong>Antwort:</strong> {{ q.canonical_answer }}</p>
</div>
<div class="q-actions">
<button class="btn btn-sm btn-success" onclick="approveQuestion({{ q.id }})">Wieder aktivieren</button>
<button class="btn btn-sm btn-danger" onclick="deleteQuestion({{ q.id }})">Endgültig löschen</button>
</div>
</div>
{% endfor %}
</div>
</section>
{% endif %}
</div>
{% endblock %}
{% block scripts %}
<script src="/static/js/admin.js"></script>
{% endblock %}