More smoothness and persistence

This commit is contained in:
MeBeBruno committed 2026-10-04 22:47:53 +02:00
1 parent f924016478
commit aeb9173825
10 files changed
+2113 -1776

No files matched your search

+343 -343
View File
@@ -1,348 +1,348 @@
{% extends "layout.html" %}
{% block content %}
<section class="administrator-section">
{% if setup_required %}
<div class="content-card">
<h2 class="section-title"><i data-lucide="settings"></i> Administrator Einrichtung</h2>
<form action="{{ url_for('handle_administrator') }}" method="POST" class="input-form">
<div class="form-group">
<label for="password_string" class="input-label">Neues Administrator-Passwort</label>
<input type="password" id="password_string" name="password_string" class="text-input" required>
</div>
<div class="form-group">
<label for="password_string_confirmation" class="input-label">Passwort wiederholen</label>
<input type="password" id="password_string_confirmation" name="password_string_confirmation" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="check"></i> Einrichtung abschließen</button>
</form>
</div>
{% elif login_required %}
<div class="content-card">
<h2 class="section-title"><i data-lucide="shield"></i> Administrator Anmeldung</h2>
<form action="{{ url_for('handle_administrator') }}" method="POST" class="input-form">
<div class="form-group">
<label for="password_string" class="input-label">Passwort</label>
<input type="password" id="password_string" name="password_string" class="text-input" required>
</div>
{% if two_factor_enabled %}
<div class="form-group">
<label for="two_factor_code" class="input-label">Zwei-Faktor Code</label>
<input type="text" id="two_factor_code" name="two_factor_code" class="text-input" required>
</div>
{% endif %}
<button type="submit" class="action-button primary-button"><i data-lucide="log-in"></i> Anmelden</button>
</form>
</div>
{% elif dashboard_active %}
<div class="tab-container">
<button class="tab-button active-tab" data-target="control-panel"><i data-lucide="sliders"></i> Steuerung</button>
<button class="tab-button" data-target="player-panel"><i data-lucide="users"></i> Spieler</button>
<button class="tab-button" data-target="kill-panel"><i data-lucide="message-square"></i> Meldungen</button>
</div>
<div id="control-panel" class="tab-content active-content">
<div class="content-card status-card">
<h3 class="card-title" style="display: flex; align-items: center; gap: var(--spacing-small);">
<i data-lucide="activity"></i> Spielstatus:
{% if game_status == 'pending' %}
<span class="status-pill warning-pill"><i data-lucide="clock"></i> Ausstehend</span>
{% elif game_status == 'running' %}
<span class="status-pill success-pill"><i data-lucide="play"></i> Läuft</span>
{% elif game_status == 'paused' %}
<span class="status-pill warning-pill"><i data-lucide="pause"></i> Pausiert</span>
{% elif game_status == 'finished' %}
<span class="status-pill danger-pill"><i data-lucide="square"></i> Beendet</span>
{% endif %}
</h3>
{% if game_status == 'pending' %}
{% if can_start %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="start_game">
<button type="submit" class="action-button success-button large-button"><i data-lucide="play"></i> Spiel starten</button>
</form>
{% else %}
<div class="content-card notice-card warning-card">
<p class="notice-text">Es werden mindestens zwei freigegebene Spieler benötigt, um das Spiel zu starten.</p>
</div>
{% endif %}
{% elif game_status == 'running' %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form" style="margin-bottom: var(--spacing-medium);">
<input type="hidden" name="action_type" value="pause_game">
<button type="submit" class="action-button warning-button large-button"><i data-lucide="pause"></i> Spiel pausieren</button>
</form>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="stop_game">
<button type="submit" class="action-button danger-button large-button"><i data-lucide="square"></i> Spiel beenden</button>
</form>
{% elif game_status == 'paused' %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form" style="margin-bottom: var(--spacing-medium);">
<input type="hidden" name="action_type" value="resume_game">
<button type="submit" class="action-button success-button large-button"><i data-lucide="play"></i> Spiel fortsetzen</button>
</form>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="stop_game">
<button type="submit" class="action-button danger-button large-button"><i data-lucide="square"></i> Spiel beenden</button>
</form>
{% elif game_status == 'finished' %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="reset_game">
<button type="submit" class="action-button danger-button large-button"><i data-lucide="rotate-ccw"></i> Spiel zurücksetzen</button>
</form>
{% endif %}
</div>
<div class="content-card settings-card">
<h3 class="card-title"><i data-lucide="shield-check"></i> Sicherheit</h3>
{% if two_factor_enabled %}
<div class="content-card notice-card success-card">
<p class="notice-text">Zwei-Faktor-Authentifizierung ist aktiv.</p>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="inline-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="disable_two_factor">
<button type="submit" class="action-button danger-button"><i data-lucide="shield-off"></i> Deaktivieren</button>
</form>
</div>
{% else %}
<div class="content-card notice-card warning-card">
<p class="notice-text">Zwei-Faktor-Authentifizierung ist inaktiv. Bitte scanne den QR-Code und bestätige zur Aktivierung.</p>
<p>Manuelle Eingabe: <strong>{{ two_factor_secret }}</strong></p>
<div class="qr-code-container">
{{ qr_code_svg | safe }}
</div>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="enable_two_factor">
<div class="form-group">
<label for="enable_two_factor_code" class="input-label">Bestätigungscode</label>
<input type="text" id="enable_two_factor_code" name="two_factor_code" class="text-input" required>
</div>
<button type="submit" class="action-button success-button"><i data-lucide="shield-alert"></i> Aktivieren</button>
</form>
</div>
{% endif %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form" style="margin-top: var(--spacing-large);">
<input type="hidden" name="action_type" value="update_credentials">
<div class="form-group">
<label for="new_password_string" class="input-label">Passwort ändern</label>
<input type="password" id="new_password_string" name="password_string" class="text-input" required>
</div>
<div class="form-group">
<label for="update_password_confirmation" class="input-label">Passwort wiederholen</label>
<input type="password" id="update_password_confirmation" name="password_string_confirmation" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="save"></i> Aktualisieren</button>
</form>
</div>
</div>
<div id="player-panel" class="tab-content">
<div class="content-card">
<h3 class="card-title"><i data-lucide="user-plus"></i> Spieler manuell erstellen</h3>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="create_player">
<div class="form-group">
<label for="display_name" class="input-label">Anzeigename</label>
<input type="text" id="display_name" name="display_name" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="plus"></i> Spieler erstellen</button>
</form>
</div>
<div class="content-card" style="overflow-x: auto;">
<table class="data-table">
<thead>
<tr>
<th>Kennung</th>
<th>Name & Änderung</th>
<th>Status</th>
<th>Ziel</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
{% for current_player in all_players %}
<tr class="{% if not current_player.is_approved %}unregistered-row{% endif %}">
<td class="monospace-identifier">
{{ current_player.player_identifier }}
{% if not current_player.is_approved %}
<br><span class="status-pill warning-pill" style="margin-left: 0; margin-top: var(--spacing-small);">Wartet</span>
{% elif current_player.late_joiner %}
<br><span class="status-pill warning-pill" style="margin-left: 0; margin-top: var(--spacing-small);">Späteinstieg</span>
{% endif %}
</td>
<td>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="edit_name">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<input type="text" name="new_display_name" value="{{ current_player.display_name }}" class="text-input small-input" required>
<button type="submit" class="action-button primary-button small-button"><i data-lucide="save"></i></button>
</form>
{% if current_player.pending_display_name %}
<div class="content-card notice-card warning-card" style="margin-top: var(--spacing-small); padding: var(--spacing-small); margin-bottom: 0;">
<p style="margin: 0 0 var(--spacing-small) 0; font-size: calc(0.875rem * var(--dimension-multiplier));">
Wünscht: <strong>{{ current_player.pending_display_name }}</strong>
</p>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-bottom: var(--spacing-small);">
<input type="hidden" name="action_type" value="approve_name_change">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button success-button small-button"><i data-lucide="check"></i></button>
</form>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="reject_name_change">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button danger-button small-button"><i data-lucide="x"></i></button>
</form>
</div>
{% endif %}
</td>
<td>
{% if not current_player.is_approved %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="approve_player">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button success-button small-button"><i data-lucide="user-check"></i> Freigeben</button>
</form>
{% else %}
{% if current_player.is_alive %}
<span class="status-pill success-pill" style="margin-left: 0;"><i data-lucide="heart"></i> Lebend</span>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-top: var(--spacing-small);">
<input type="hidden" name="action_type" value="eliminate_player">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button danger-button small-button"><i data-lucide="skull"></i> Töten</button>
</form>
{% else %}
<span class="status-pill danger-pill" style="margin-left: 0;"><i data-lucide="skull"></i> Tot</span>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-top: var(--spacing-small);">
<input type="hidden" name="action_type" value="revive_player">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button success-button small-button"><i data-lucide="heart-pulse"></i> Beleben</button>
</form>
{% endif %}
{% endif %}
</td>
<td>
{% if current_player.target_identifier %}
{{ current_player.target_identifier }}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-top: var(--spacing-small);">
<input type="hidden" name="action_type" value="change_target">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<select name="new_target_identifier" class="text-input small-input">
{% for possible_target in all_players %}
{% if possible_target.is_alive and possible_target.player_identifier != current_player.player_identifier %}
<option value="{{ possible_target.player_identifier }}" {% if current_player.target_identifier == possible_target.player_identifier %}selected{% endif %}>{{ possible_target.display_name }}</option>
{% endif %}
{% endfor %}
</select>
<button type="submit" class="action-button secondary-button small-button"><i data-lucide="refresh-cw"></i></button>
</form>
{% else %}
-
{% endif %}
</td>
<td>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="generate_reset">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button secondary-button small-button"><i data-lucide="link"></i> Reset Link</button>
</form>
{% if current_player.reset_token %}
<input type="text" readonly value="{{ url_for('handle_password_reset', token=current_player.reset_token, _external=True) }}" class="text-input small-input" style="margin: var(--spacing-small) 0;">
{% endif %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-top: var(--spacing-small);">
<input type="hidden" name="action_type" value="delete_player">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button danger-button small-button"><i data-lucide="trash-2"></i></button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div id="kill-panel" class="tab-content">
<div class="content-card" style="overflow-x: auto;">
<table class="data-table">
<thead>
<tr>
<th>Zeitpunkt</th>
<th>Killer</th>
<th>Opfer</th>
<th>Status</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
{% for report in kill_logs %}
<tr>
<td>{{ report.kill_timestamp[:16].replace('T', ' ') if report.kill_timestamp else '-' }}</td>
<td>{{ report.killer_name or 'Unbekannt' }} ({{ report.killer_identifier }})</td>
<td>{{ report.victim_name or 'Unbekannt' }} ({{ report.victim_identifier }})</td>
<td>
{% if report.report_status == 'confirmed' %}
<span class="status-pill success-pill" style="margin-left: 0;">Bestätigt</span>
{% elif report.report_status == 'pending' %}
<span class="status-pill warning-pill" style="margin-left: 0;">Ausstehend</span>
{% elif report.report_status == 'rejected' %}
<span class="status-pill danger-pill" style="margin-left: 0;">Abgelehnt</span>
{% elif report.report_status == 'revoked' %}
<span class="status-pill danger-pill" style="margin-left: 0;">Widerrufen</span>
{% else %}
{{ report.report_status }}
{% endif %}
</td>
<td>
{% if report.report_status == 'confirmed' %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="revoke_kill">
<input type="hidden" name="kill_identifier" value="{{ report.kill_identifier }}">
<button type="submit" class="action-button danger-button small-button"><i data-lucide="rotate-ccw"></i> Rückgängig</button>
</form>
{% endif %}
{% if report.report_status == 'pending' %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="force_confirm_report">
<input type="hidden" name="kill_identifier" value="{{ report.kill_identifier }}">
<button type="submit" class="action-button success-button small-button"><i data-lucide="check"></i> Bestätigen</button>
</form>
{% endif %}
{% if report.report_status in ['pending', 'rejected', 'revoked'] %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-top: var(--spacing-small);">
<input type="hidden" name="action_type" value="delete_report">
<input type="hidden" name="kill_identifier" value="{{ report.kill_identifier }}">
<button type="submit" class="action-button secondary-button small-button"><i data-lucide="trash-2"></i> Löschen</button>
</form>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td colspan="5" style="text-align: center; opacity: 0.6;">Bisher keine Meldungen im System.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div id="admin-confirmation-modal" class="modal-overlay">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="calendar-clock"></i> Aktion planen</h2>
<p class="modal-description">Führe die Aktion sofort aus oder plane sie für die Zukunft.</p>
<div class="form-group" style="margin-bottom: var(--spacing-large); text-align: left;">
<label for="modal_execution_time" class="input-label">Zeitpunkt (Optional)</label>
<input type="datetime-local" id="modal_execution_time" class="text-input time-input" style="width: 100%; box-sizing: border-box;">
</div>
<div class="modal-actions">
<button type="button" id="confirm-admin-action" class="action-button success-button"><i data-lucide="check"></i> Bestätigen</button>
<button type="button" id="cancel-admin-action" class="action-button secondary-button"><i data-lucide="x"></i> Abbrechen</button>
</div>
</div>
</div>
{% endif %}
{% if setup_required %}
<div class="content-card">
<h2 class="section-title"><i data-lucide="settings"></i> Einrichtung</h2>
<form action="{{ url_for('handle_administrator') }}" method="POST" class="input-form">
<div class="form-group">
<label for="password_string" class="input-label">Neues Passwort</label>
<input type="password" id="password_string" name="password_string" class="text-input" required>
</div>
<div class="form-group">
<label for="password_string_confirmation" class="input-label">Passwort bestätigen</label>
<input type="password" id="password_string_confirmation" name="password_string_confirmation" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="check"></i> Abschließen</button>
</form>
</div>
{% elif login_required %}
<div class="content-card">
<h2 class="section-title"><i data-lucide="shield"></i> Admin-Login</h2>
<form action="{{ url_for('handle_administrator') }}" method="POST" class="input-form">
<div class="form-group">
<label for="password_string" class="input-label">Passwort</label>
<input type="password" id="password_string" name="password_string" class="text-input" required>
</div>
{% if two_factor_enabled %}
<div class="form-group">
<label for="two_factor_code" class="input-label">2FA-Code</label>
<input type="text" id="two_factor_code" name="two_factor_code" class="text-input" required>
</div>
{% endif %}
<button type="submit" class="action-button primary-button"><i data-lucide="log-in"></i> Anmelden</button>
</form>
</div>
{% elif dashboard_active %}
<div class="tab-container">
<button class="tab-button active-tab" data-target="control-panel"><i data-lucide="sliders"></i> Steuerung</button>
<button class="tab-button" data-target="player-panel"><i data-lucide="users"></i> Spieler</button>
<button class="tab-button" data-target="kill-panel"><i data-lucide="message-square"></i> Meldungen</button>
</div>
<div id="control-panel" class="tab-content active-content">
<div class="content-card status-card">
<h3 class="card-title" style="display: flex; align-items: center; gap: var(--spacing-small);">
<i data-lucide="activity"></i> Spielstatus:
{% if game_status == 'pending' %}
<span class="status-pill warning-pill"><i data-lucide="clock"></i> Ausstehend</span>
{% elif game_status == 'running' %}
<span class="status-pill success-pill"><i data-lucide="play"></i> Läuft</span>
{% elif game_status == 'paused' %}
<span class="status-pill warning-pill"><i data-lucide="pause"></i> Pausiert</span>
{% elif game_status == 'finished' %}
<span class="status-pill danger-pill"><i data-lucide="square"></i> Beendet</span>
{% endif %}
</h3>
{% if game_status == 'pending' %}
{% if can_start %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="start_game">
<button type="submit" class="action-button success-button large-button"><i data-lucide="play"></i> Spiel starten</button>
</form>
{% else %}
<div class="content-card notice-card warning-card">
<p class="notice-text">Zu wenige Spieler zum Starten.</p>
</div>
{% endif %}
{% elif game_status == 'running' %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form" style="margin-bottom: var(--spacing-medium);">
<input type="hidden" name="action_type" value="pause_game">
<button type="submit" class="action-button warning-button large-button"><i data-lucide="pause"></i> Spiel pausieren</button>
</form>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="stop_game">
<button type="submit" class="action-button danger-button large-button"><i data-lucide="square"></i> Spiel beenden</button>
</form>
{% elif game_status == 'paused' %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form" style="margin-bottom: var(--spacing-medium);">
<input type="hidden" name="action_type" value="resume_game">
<button type="submit" class="action-button success-button large-button"><i data-lucide="play"></i> Spiel fortsetzen</button>
</form>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="stop_game">
<button type="submit" class="action-button danger-button large-button"><i data-lucide="square"></i> Spiel beenden</button>
</form>
{% elif game_status == 'finished' %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="reset_game">
<button type="submit" class="action-button danger-button large-button"><i data-lucide="rotate-ccw"></i> Spiel zurücksetzen</button>
</form>
{% endif %}
</div>
<div class="content-card settings-card">
<h3 class="card-title"><i data-lucide="shield-check"></i> Sicherheit</h3>
{% if two_factor_enabled %}
<div class="content-card notice-card success-card">
<p class="notice-text">2FA ist aktiv.</p>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="inline-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="disable_two_factor">
<button type="submit" class="action-button danger-button"><i data-lucide="shield-off"></i> Deaktivieren</button>
</form>
</div>
{% else %}
<div class="content-card notice-card warning-card">
<p class="notice-text">2FA inaktiv. QR-Code scannen.</p>
<p>Code: <strong>{{ two_factor_secret }}</strong></p>
<div class="qr-code-container">
{{ qr_code_svg | safe }}
</div>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="enable_two_factor">
<div class="form-group">
<label for="enable_two_factor_code" class="input-label">Bestätigungscode</label>
<input type="text" id="enable_two_factor_code" name="two_factor_code" class="text-input" required>
</div>
<button type="submit" class="action-button success-button"><i data-lucide="shield-alert"></i> Aktivieren</button>
</form>
</div>
{% endif %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form" style="margin-top: var(--spacing-large);">
<input type="hidden" name="action_type" value="update_credentials">
<div class="form-group">
<label for="new_password_string" class="input-label">Neues Passwort</label>
<input type="password" id="new_password_string" name="password_string" class="text-input" required>
</div>
<div class="form-group">
<label for="update_password_confirmation" class="input-label">Passwort bestätigen</label>
<input type="password" id="update_password_confirmation" name="password_string_confirmation" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="save"></i> Speichern</button>
</form>
</div>
</div>
<div id="player-panel" class="tab-content">
<div class="content-card">
<h3 class="card-title"><i data-lucide="user-plus"></i> Spieler erstellen</h3>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="input-form admin-asynchronous-form">
<input type="hidden" name="action_type" value="create_player">
<div class="form-group">
<label for="display_name" class="input-label">Name</label>
<input type="text" id="display_name" name="display_name" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="plus"></i> Erstellen</button>
</form>
</div>
<div class="content-card" style="overflow-x: auto;">
<table class="data-table">
<thead>
<tr>
<th>Kennung</th>
<th>Name</th>
<th>Status</th>
<th>Ziel</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
{% for current_player in all_players %}
<tr class="{% if not current_player.is_approved %}unregistered-row{% endif %}">
<td class="monospace-identifier">
{{ current_player.player_identifier }}
{% if not current_player.is_approved %}
<br><span class="status-pill warning-pill" style="margin-left: 0; margin-top: var(--spacing-small);">Wartet</span>
{% elif current_player.late_joiner %}
<br><span class="status-pill warning-pill" style="margin-left: 0; margin-top: var(--spacing-small);">Späteinstieg</span>
{% endif %}
</td>
<td>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="edit_name">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<input type="text" name="new_display_name" value="{{ current_player.display_name }}" class="text-input small-input" required>
<button type="submit" class="action-button primary-button small-button"><i data-lucide="save"></i></button>
</form>
{% if current_player.pending_display_name %}
<div class="content-card notice-card warning-card" style="margin-top: var(--spacing-small); padding: var(--spacing-small); margin-bottom: 0;">
<p style="margin: 0 0 var(--spacing-small) 0; font-size: calc(0.875rem * var(--dimension-multiplier));">
-> <strong>{{ current_player.pending_display_name }}</strong>
</p>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-bottom: var(--spacing-small);">
<input type="hidden" name="action_type" value="approve_name_change">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button success-button small-button"><i data-lucide="check"></i></button>
</form>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="reject_name_change">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button danger-button small-button"><i data-lucide="x"></i></button>
</form>
</div>
{% endif %}
</td>
<td>
{% if not current_player.is_approved %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="approve_player">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button success-button small-button"><i data-lucide="user-check"></i> Freigeben</button>
</form>
{% else %}
{% if current_player.is_alive %}
<span class="status-pill success-pill" style="margin-left: 0;"><i data-lucide="heart"></i> Lebend</span>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-top: var(--spacing-small);">
<input type="hidden" name="action_type" value="eliminate_player">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button danger-button small-button"><i data-lucide="skull"></i> Killen</button>
</form>
{% else %}
<span class="status-pill danger-pill" style="margin-left: 0;"><i data-lucide="skull"></i> Gekillt</span>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-top: var(--spacing-small);">
<input type="hidden" name="action_type" value="revive_player">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button success-button small-button"><i data-lucide="heart-pulse"></i> Beleben</button>
</form>
{% endif %}
{% endif %}
</td>
<td>
{% if current_player.target_identifier %}
{{ current_player.target_identifier }}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-top: var(--spacing-small);">
<input type="hidden" name="action_type" value="change_target">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<select name="new_target_identifier" class="text-input small-input">
{% for possible_target in all_players %}
{% if possible_target.is_alive and possible_target.player_identifier != current_player.player_identifier %}
<option value="{{ possible_target.player_identifier }}" {% if current_player.target_identifier == possible_target.player_identifier %}selected{% endif %}>{{ possible_target.display_name }}</option>
{% endif %}
{% endfor %}
</select>
<button type="submit" class="action-button secondary-button small-button"><i data-lucide="refresh-cw"></i></button>
</form>
{% else %}
-
{% endif %}
</td>
<td>
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="generate_reset">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button secondary-button small-button"><i data-lucide="link"></i> Reset Link</button>
</form>
{% if current_player.reset_token %}
<input type="text" readonly value="{{ url_for('handle_password_reset', token=current_player.reset_token, _external=True) }}" class="text-input small-input" style="margin: var(--spacing-small) 0;">
{% endif %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-top: var(--spacing-small);">
<input type="hidden" name="action_type" value="delete_player">
<input type="hidden" name="player_identifier" value="{{ current_player.player_identifier }}">
<button type="submit" class="action-button danger-button small-button"><i data-lucide="trash-2"></i></button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div id="kill-panel" class="tab-content">
<div class="content-card" style="overflow-x: auto;">
<table class="data-table">
<thead>
<tr>
<th>Zeitpunkt</th>
<th>Killer</th>
<th>Opfer</th>
<th>Status</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
{% for report in kill_logs %}
<tr>
<td>{{ report.kill_timestamp[:16].replace('T', ' ') if report.kill_timestamp else '-' }}</td>
<td>{{ report.killer_name or 'Unbekannt' }} ({{ report.killer_identifier }})</td>
<td>{{ report.victim_name or 'Unbekannt' }} ({{ report.victim_identifier }})</td>
<td>
{% if report.report_status == 'confirmed' %}
<span class="status-pill success-pill" style="margin-left: 0;">Bestätigt</span>
{% elif report.report_status == 'pending' %}
<span class="status-pill warning-pill" style="margin-left: 0;">Ausstehend</span>
{% elif report.report_status == 'rejected' %}
<span class="status-pill danger-pill" style="margin-left: 0;">Abgelehnt</span>
{% elif report.report_status == 'revoked' %}
<span class="status-pill danger-pill" style="margin-left: 0;">Widerrufen</span>
{% else %}
{{ report.report_status }}
{% endif %}
</td>
<td>
{% if report.report_status == 'confirmed' %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="revoke_kill">
<input type="hidden" name="kill_identifier" value="{{ report.kill_identifier }}">
<button type="submit" class="action-button danger-button small-button"><i data-lucide="rotate-ccw"></i> Rückgängig</button>
</form>
{% endif %}
{% if report.report_status == 'pending' %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form">
<input type="hidden" name="action_type" value="force_confirm_report">
<input type="hidden" name="kill_identifier" value="{{ report.kill_identifier }}">
<button type="submit" class="action-button success-button small-button"><i data-lucide="check"></i> Bestätigen</button>
</form>
{% endif %}
{% if report.report_status in ['pending', 'rejected', 'revoked'] %}
<form action="{{ url_for('handle_administrator_action') }}" method="POST" class="flexible_form_container admin-asynchronous-form" style="margin-top: var(--spacing-small);">
<input type="hidden" name="action_type" value="delete_report">
<input type="hidden" name="kill_identifier" value="{{ report.kill_identifier }}">
<button type="submit" class="action-button secondary-button small-button"><i data-lucide="trash-2"></i> Löschen</button>
</form>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td colspan="5" style="text-align: center; opacity: 0.6;">Keine Meldungen.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div id="admin-confirmation-modal" class="modal-overlay">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="calendar-clock"></i> Aktion planen</h2>
<p class="modal-description">Sofort ausführen oder planen.</p>
<div class="form-group" style="margin-bottom: var(--spacing-large); text-align: left;">
<label for="modal_execution_time" class="input-label">Zeitpunkt (Optional)</label>
<input type="datetime-local" id="modal_execution_time" class="text-input time-input" style="width: 100%; box-sizing: border-box;">
</div>
<div class="modal-actions">
<button type="button" id="confirm-admin-action" class="action-button success-button"><i data-lucide="check"></i> Bestätigen</button>
<button type="button" id="cancel-admin-action" class="action-button secondary-button"><i data-lucide="x"></i> Abbrechen</button>
</div>
</div>
</div>
{% endif %}
</section>
{% endblock %}
+189 -182
View File
@@ -1,187 +1,194 @@
{% extends "layout.html" %}
{% block content %}
<section class="game-section">
<div class="content-card">
<h2 class="section-title" style="margin: 0;"><i data-lucide="user"></i> Willkommen, {{ player.display_name }} ({{ player.player_identifier }})!</h2>
</div>
{% if not player.is_approved %}
<div class="content-card notice-card warning-card">
<h2 class="modal-title"><i data-lucide="hourglass"></i> Konto wird geprüft&hellip;</h2>
</div>
{% elif game_status == 'pending' %}
<div class="content-card notice-card">
<h2 class="modal-title"><i data-lucide="clock"></i> Startet bald&hellip;</h2>
</div>
{% elif game_status == 'finished' %}
<div class="content-card leaderboard-card">
<h2 class="section-title"><i data-lucide="trophy"></i> Spiel beendet &ndash; Rangliste</h2>
<table class="data-table">
<thead>
<tr>
<th>Platz</th>
<th>Name</th>
<th>Punkte</th>
</tr>
</thead>
<tbody>
{% for current_player in all_players %}
<tr class="{% if current_player.player_identifier == session['player_identifier'] %}highlighted-row{% endif %}">
<td>{{ loop.index }}</td>
<td>{{ current_player.display_name }}</td>
<td>{{ current_player.score }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% elif game_status in ['running', 'paused'] %}
<div class="tab-container">
<button class="tab-button active-tab" data-target="mission-panel"><i data-lucide="crosshair"></i> Ziel</button>
<button class="tab-button" data-target="leaderboard-panel"><i data-lucide="bar-chart-2"></i> Punkte</button>
<button class="tab-button" data-target="rules-panel"><i data-lucide="book-open"></i> Regeln</button>
</div>
<div id="mission-panel" class="tab-content active-content">
{% if game_status == 'paused' %}
<div class="content-card notice-card warning-card">
<h2 class="modal-title"><i data-lucide="pause-circle"></i> Spiel pausiert</h2>
<p class="notice-text">Das Spiel wurde pausiert. Eliminierungen sind aktuell nicht möglich.</p>
</div>
{% endif %}
{% if player.is_alive %}
<div class="content-card target-card" style="text-align: center;">
<h3 class="card-subtitle"><i data-lucide="target"></i> Dein Ziel</h3>
<h2 class="target-name">{{ target_player.display_name if target_player else 'Niemand' }}</h2>
{% if game_status == 'running' %}
<button type="button" id="trigger-elimination" class="action-button danger-button large-button"><i data-lucide="crosshair"></i> Kill melden</button>
{% else %}
<button type="button" class="action-button secondary-button large-button" disabled><i data-lucide="lock"></i> Pausiert</button>
{% endif %}
</div>
{% elif player.late_joiner %}
<div class="content-card notice-card warning-card">
<h2 class="modal-title"><i data-lucide="users"></i> Warte auf Einstieg&hellip;</h2>
<p class="notice-text">Du bist dem Spiel während einer laufenden Runde beigetreten. Du wirst aktiv, sobald du eingewechselt wirst.</p>
</div>
{% else %}
<div class="content-card notice-card danger-card">
<h2 class="modal-title"><i data-lucide="skull"></i> Eliminiert</h2>
</div>
{% endif %}
<div class="content-card statistics-card">
<h3 class="section-title"><i data-lucide="pie-chart"></i> Spielübersicht</h3>
<p>Überlebende: <strong>{{ alive_count }}</strong></p>
<p>Deine Kills: <strong>{{ player.score }}</strong></p>
<p>Gesamte Kills: <strong>{{ total_eliminations }}</strong></p>
<p>Laufzeit: <strong id="game-stopwatch" data-start-time="{{ start_time }}">Wird berechnet...</strong></p>
</div>
<div class="content-card settings-card">
<h3 class="section-title"><i data-lucide="user-cog"></i> Profil</h3>
{% if player.pending_display_name %}
<div class="notice-card warning-card" style="padding: var(--spacing-medium);">
<p class="notice-text" style="margin: 0;">Der Name <strong>{{ player.pending_display_name }}</strong> wird geprüft&hellip;</p>
</div>
{% else %}
<button type="button" id="trigger-name-change-modal" class="action-button secondary-button"><i data-lucide="edit-3"></i> Name ändern</button>
{% endif %}
</div>
</div>
<div id="leaderboard-panel" class="tab-content">
<div class="content-card">
<table class="data-table">
<thead>
<tr>
<th>Platz</th>
<th>Name</th>
<th>Punkte</th>
</tr>
</thead>
<tbody>
{% for current_player in all_players %}
<tr class="{% if current_player.player_identifier == session['player_identifier'] %}highlighted-row{% endif %}">
<td>{{ loop.index }}</td>
<td>{{ current_player.display_name }}</td>
<td>{{ current_player.score }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div id="rules-panel" class="tab-content">
<div class="content-card markdown-container">
{{ rules_markup | safe }}
</div>
</div>
<div id="elimination-confirm-modal" class="modal-overlay">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="alert-triangle"></i> Kill</h2>
<p class="modal-description">Möchtest du melden, dass du dein Ziel gekillt hast?</p>
<div class="modal-actions">
<button type="button" id="proceed-elimination" class="action-button danger-button"><i data-lucide="crosshair"></i> Ja, melden</button>
<button type="button" id="cancel-elimination" class="action-button secondary-button"><i data-lucide="x"></i> Abbrechen</button>
</div>
</div>
</div>
<div id="waiting-modal" class="modal-overlay">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="loader"></i> Bitte warten</h2>
<p class="modal-description">Warte auf Bestätigung vom Ziel...</p>
</div>
</div>
<div id="rejection-modal" class="modal-overlay">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="x-octagon"></i> Abgelehnt</h2>
<p class="modal-description">Das Ziel hat deinen Kill abgelehnt.</p>
<div class="modal-actions">
<button type="button" id="acknowledge-rejection" class="action-button primary-button"><i data-lucide="check"></i> Verstanden</button>
</div>
</div>
</div>
<div id="verification-modal" class="modal-overlay {% if player.pending_attacker_identifier %}active-modal{% endif %}">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="shield-alert"></i> Wurdest du eliminiert?</h2>
<p class="modal-description">
{% if pending_attacker_name %}
<strong>{{ pending_attacker_name }}</strong> hat gemeldet, dass er/sie dich gekillt hat.
{% else %}
Dein Angreifer hat gemeldet, dass er dich gekillt hat.
{% endif %}
</p>
<div class="modal-actions">
<button type="button" id="confirm-elimination" class="action-button danger-button"><i data-lucide="check"></i> Bestätigen</button>
<button type="button" id="reject-elimination" class="action-button secondary-button"><i data-lucide="x"></i> Ablehnen</button>
</div>
</div>
</div>
<div id="name-change-modal" class="modal-overlay">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="edit-3"></i> Name ändern</h2>
<p class="modal-description">Dein neuer Name muss erst geprüft werden.</p>
<form action="{{ url_for('handle_player_action') }}" method="POST" class="input-form asynchronous-form">
<input type="hidden" name="action_type" value="request_name_change">
<div class="form-group" style="text-align: left;">
<label for="pending_display_name" class="input-label">Neuer Name</label>
<input type="text" id="pending_display_name" name="pending_display_name" class="text-input" required>
</div>
<div class="modal-actions">
<button type="submit" class="action-button primary-button"><i data-lucide="send"></i> Abschicken</button>
<button type="button" id="cancel-name-change" class="action-button secondary-button"><i data-lucide="x"></i> Abbrechen</button>
</div>
</form>
</div>
</div>
{% endif %}
<div class="content-card">
<h2 class="section-title" style="margin: 0;"><i data-lucide="user"></i> Hallo, {{ player.display_name }}!</h2>
</div>
{% if not player.is_approved %}
<div class="content-card notice-card warning-card">
<h2 class="modal-title"><i data-lucide="hourglass"></i> Warten auf Freigabe</h2>
<p class="notice-text">Die Spielleitung muss deinen Account noch aktivieren.</p>
</div>
{% elif game_status == 'pending' %}
<div class="content-card notice-card">
<h2 class="modal-title"><i data-lucide="clock"></i> Spiel startet in Kürze</h2>
</div>
{% elif game_status == 'finished' %}
<div class="content-card leaderboard-card">
<h2 class="section-title"><i data-lucide="trophy"></i> Rangliste</h2>
<table class="data-table">
<thead>
<tr>
<th>Platz</th>
<th>Name</th>
<th>Punkte</th>
</tr>
</thead>
<tbody>
{% for current_player in all_players %}
<tr class="{% if current_player.player_identifier == session['player_identifier'] %}highlighted-row{% endif %}">
<td>{{ loop.index }}</td>
<td>{{ current_player.display_name }}</td>
<td>{{ current_player.score }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% elif game_status in ['running', 'paused'] %}
<div class="tab-container">
<button class="tab-button active-tab" data-target="mission-panel"><i data-lucide="crosshair"></i> Ziel</button>
<button class="tab-button" data-target="leaderboard-panel"><i data-lucide="bar-chart-2"></i> Punkte</button>
<button class="tab-button" data-target="rules-panel"><i data-lucide="book-open"></i> Regeln</button>
</div>
<div id="mission-panel" class="tab-content active-content">
{% if game_status == 'paused' %}
<div class="content-card notice-card warning-card">
<h2 class="modal-title"><i data-lucide="pause-circle"></i> Pausiert</h2>
<p class="notice-text">Kills sind vorübergehend deaktiviert.</p>
</div>
{% endif %}
{% if player.is_alive %}
<div class="content-card target-card" style="text-align: center;">
<h3 class="card-subtitle"><i data-lucide="target"></i> Ziel</h3>
<h2 class="target-name">{{ target_player.display_name if target_player else 'Niemand' }}</h2>
{% if game_status == 'running' %}
{% if has_pending_kill_report %}
<div class="notice-card warning-card" style="padding: var(--spacing-medium); border-radius: var(--border-radius-small); margin-top: var(--spacing-large);">
<h3 style="margin-top: 0; display: flex; align-items: center; justify-content: center; gap: var(--spacing-small);"><i data-lucide="loader"></i> Kill gemeldet</h3>
<p>Warte auf Bestätigung…</p>
<button type="button" id="trigger-revoke-elimination" class="action-button secondary-button"><i data-lucide="rotate-ccw"></i> Zurückziehen</button>
</div>
{% else %}
<button type="button" id="trigger-elimination" class="action-button danger-button large-button"><i data-lucide="crosshair"></i> Kill melden</button>
{% endif %}
{% else %}
<button type="button" class="action-button secondary-button large-button" disabled><i data-lucide="lock"></i> Gesperrt</button>
{% endif %}
</div>
{% elif player.late_joiner %}
<div class="content-card notice-card warning-card">
<h2 class="modal-title"><i data-lucide="users"></i> Warten auf Einwechslung</h2>
<p class="notice-text">Die Spielleitung wechselt dich bald ein.</p>
</div>
{% else %}
<div class="content-card notice-card danger-card">
<h2 class="modal-title"><i data-lucide="skull"></i> Gekillt</h2>
</div>
{% endif %}
<div class="content-card statistics-card">
<h3 class="section-title"><i data-lucide="pie-chart"></i> Übersicht</h3>
<p>Lebend: <strong>{{ alive_count }}</strong></p>
<p>Kills: <strong>{{ player.score }}</strong></p>
<p>Gesamt: <strong>{{ total_eliminations }}</strong></p>
<p>Zeit: <strong id="game-stopwatch" data-start-time="{{ start_time }}">Lade...</strong></p>
</div>
<div class="content-card settings-card">
<h3 class="section-title"><i data-lucide="user-cog"></i> Profil</h3>
{% if player.pending_display_name %}
<div class="notice-card warning-card" style="padding: var(--spacing-medium); border-radius: var(--border-radius-small);">
<p class="notice-text" style="margin-top: 0;"><strong>{{ player.pending_display_name }}</strong> wird geprüft…</p>
<form action="{{ url_for('handle_player_action') }}" method="POST" class="asynchronous-form">
<input type="hidden" name="action_type" value="cancel_name_change">
<button type="submit" class="action-button secondary-button small-button"><i data-lucide="x"></i> Abbrechen</button>
</form>
</div>
{% else %}
<button type="button" id="trigger-name-change-modal" class="action-button secondary-button"><i data-lucide="edit-3"></i> Name ändern</button>
{% endif %}
</div>
</div>
<div id="leaderboard-panel" class="tab-content">
<div class="content-card">
<table class="data-table">
<thead>
<tr>
<th>Platz</th>
<th>Name</th>
<th>Punkte</th>
</tr>
</thead>
<tbody>
{% for current_player in all_players %}
<tr class="{% if current_player.player_identifier == session['player_identifier'] %}highlighted-row{% endif %}">
<td>{{ loop.index }}</td>
<td>{{ current_player.display_name }}</td>
<td>{{ current_player.score }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div id="rules-panel" class="tab-content">
<div class="content-card markdown-container">
{{ rules_markup | safe }}
</div>
</div>
<div id="elimination-confirm-modal" class="modal-overlay">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="alert-triangle"></i> Kill melden</h2>
<p class="modal-description">Sicher, dass du den Kill melden möchtest?</p>
<div class="modal-actions">
<button type="button" id="proceed-elimination" class="action-button danger-button"><i data-lucide="crosshair"></i> Melden</button>
<button type="button" id="cancel-elimination" class="action-button secondary-button"><i data-lucide="x"></i> Abbrechen</button>
</div>
</div>
</div>
<div id="rejection-modal" class="modal-overlay">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="x-octagon"></i> Abgelehnt</h2>
<p class="modal-description">Das Ziel hat die Meldung abgelehnt. Bitte klären.</p>
<div class="modal-actions">
<button type="button" id="acknowledge-rejection" class="action-button primary-button"><i data-lucide="check"></i> Okay</button>
</div>
</div>
</div>
<div id="verification-modal" class="modal-overlay {% if player.pending_attacker_identifier %}active-modal{% endif %}">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="shield-alert"></i> Gekillt?</h2>
<p class="modal-description">
{% if pending_attacker_name %}
Wurdest du von <strong>{{ pending_attacker_name }}</strong> gekillt?
{% else %}
Wurdest du gekillt?
{% endif %}
</p>
<div class="modal-actions">
<button type="button" id="confirm-elimination" class="action-button danger-button"><i data-lucide="check"></i> Ja</button>
<button type="button" id="reject-elimination" class="action-button secondary-button"><i data-lucide="x"></i> Nein</button>
</div>
</div>
</div>
<div id="name-change-modal" class="modal-overlay">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="edit-3"></i> Name ändern</h2>
<p class="modal-description">Der Name wird vorher von der Spielleitung geprüft.</p>
<form action="{{ url_for('handle_player_action') }}" method="POST" class="input-form asynchronous-form">
<input type="hidden" name="action_type" value="request_name_change">
<div class="form-group" style="text-align: left;">
<label for="pending_display_name" class="input-label">Neuer Name</label>
<input type="text" id="pending_display_name" name="pending_display_name" class="text-input" required>
</div>
<div class="modal-actions">
<button type="submit" class="action-button primary-button"><i data-lucide="send"></i> Speichern</button>
<button type="button" id="cancel-name-change-modal" class="action-button secondary-button"><i data-lucide="x"></i> Abbrechen</button>
</div>
</form>
</div>
</div>
{% endif %}
</section>
{% endblock %}
+28 -26
View File
@@ -1,33 +1,35 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>SCOicide Squad</title>
<link rel="shortcut icon" href="{{ url_for('static', filename='logo.svg') }}" type="image/svg">
<link rel="manifest" href="{{ url_for('static', filename='manifest.json') }}">
<meta name="theme-color" content="#1a1e29">
<link rel="stylesheet" href="{{ url_for('static', filename='stylesheet.css') }}">
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.2/socket.io.js" defer></script>
<script src="https://unpkg.com/lucide@latest" defer></script>
<script src="{{ url_for('static', filename='behavior.js') }}" defer></script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>SCOicide Squad</title>
<link rel="shortcut icon" href="{{ url_for('static', filename='logo.svg') }}" type="image/svg">
<link rel="manifest" href="{{ url_for('static', filename='manifest.json') }}">
<meta name="theme-color" content="#1a1e29">
<link rel="stylesheet" href="{{ url_for('static', filename='stylesheet.css') }}">
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.2/socket.io.js" defer></script>
<script src="https://unpkg.com/lucide@latest" defer></script>
<script src="{{ url_for('static', filename='behavior.js') }}" defer></script>
</head>
<body>
<header class="application-header">
<div class="brand-container">
<img src="{{ url_for('static', filename='logo.svg') }}" alt="Logo" class="brand-logo">
<h1 class="application-title"><i>SCO</i>icide Squad</h1>
</div>
<nav class="application-navigation">
{% if session.get('player_identifier') or session.get('administrator_authenticated') %}
<a href="{{ url_for('handle_logout') }}" class="action-button secondary-button icon-button">
<i data-lucide="log-out"></i>
</a>
{% endif %}
</nav>
</header>
<main class="application-content">
{% block content %}{% endblock %}
</main>
<header class="application-header">
<a href="/" class="brand-link">
<div class="brand-container">
<img src="{{ url_for('static', filename='logo.svg') }}" alt="Logo" class="brand-logo">
<h1 class="application-title"><i>SCO</i>icide Squad</h1>
</div>
</a>
<nav class="application-navigation">
{% if session.get('player_identifier') or session.get('administrator_authenticated') %}
<a href="{{ url_for('handle_logout') }}" class="action-button secondary-button icon-button">
<i data-lucide="log-out"></i>
</a>
{% endif %}
</nav>
</header>
<main class="application-content">
{% block content %}{% endblock %}
</main>
</body>
</html>
+80 -67
View File
@@ -1,72 +1,85 @@
{% extends "layout.html" %}
{% block content %}
<section class="authentication-section">
{% if reset_mode %}
<div class="content-card">
<h2 class="section-title"><i data-lucide="key-round"></i> Passwort zurücksetzen</h2>
<form action="{{ url_for('handle_password_reset') }}" method="POST" class="input-form">
<input type="hidden" name="token" value="{{ token }}">
<div class="form-group">
<label for="password_string" class="input-label">Neues Passwort</label>
<input type="password" id="password_string" name="password_string" class="text-input" required>
</div>
<div class="form-group">
<label for="password_string_confirmation" class="input-label">Passwort wiederholen</label>
<input type="password" id="password_string_confirmation" name="password_string_confirmation" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="save"></i> Passwort speichern</button>
</form>
</div>
{% elif register_mode %}
<div class="content-card">
<h2 class="section-title"><i data-lucide="user-plus"></i> Neues Konto erstellen</h2>
<form action="{{ url_for('handle_registration') }}" method="POST" class="input-form">
<div class="form-group">
<label for="display_name" class="input-label">Dein Name</label>
<input type="text" id="display_name" name="display_name" class="text-input" required>
</div>
<div class="form-group">
<label for="password_string" class="input-label">Passwort</label>
<input type="password" id="password_string" name="password_string" class="text-input" required>
</div>
<div class="form-group">
<label for="password_string_confirmation" class="input-label">Passwort wiederholen</label>
<input type="password" id="password_string_confirmation" name="password_string_confirmation" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="check-circle"></i> Registrieren</button>
</form>
</div>
<div class="content-card" style="text-align: center;">
<a href="{{ url_for('handle_login') }}" class="action-button secondary-button"><i data-lucide="arrow-left"></i> Zurück zur Anmeldung</a>
</div>
{% elif registration_success %}
<div class="content-card notice-card success-card" style="text-align: center;">
<h2 class="section-title" style="justify-content: center;"><i data-lucide="party-popper"></i> Registrierung erfolgreich</h2>
<p>Deine ID für die Anmeldung lautet:</p>
<h1 class="monospace-identifier" style="font-size: calc(3rem * var(--dimension-multiplier)); letter-spacing: calc(0.25rem * var(--dimension-multiplier)); color: oklch(var(--lightness-primary) var(--chroma-primary) var(--hue-primary)); margin: var(--spacing-medium) 0;">{{ new_identifier }}</h1>
<p>Bitte speichere oder merke sie dir!</p>
<div style="margin-top: var(--spacing-large);">
<a href="{{ url_for('handle_login') }}" class="action-button primary-button"><i data-lucide="log-in"></i> Jetzt anmelden</a>
</div>
</div>
{% else %}
<div class="content-card">
<h2 class="section-title"><i data-lucide="lock"></i> Anmeldung</h2>
<form action="{{ url_for('handle_login') }}" method="POST" class="input-form">
<div class="form-group">
<label for="player_identifier" class="input-label">ID</label>
<input type="text" id="player_identifier" name="player_identifier" class="text-input" style="text-transform: uppercase;" maxlength="{{ identifier_length }}" oninput="this.value = this.value.replace(/[^a-zA-Z]/g, '').toUpperCase().slice(0, {{ identifier_length }});" pattern="[A-Za-z]{{ '{' }}{{ identifier_length }}{{ '}' }}" required>
</div>
<div class="form-group">
<label for="password_string" class="input-label">Passwort</label>
<input type="password" id="password_string" name="password_string" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="log-in"></i> Anmelden</button>
</form>
</div>
<div class="content-card" style="text-align: center;">
<a href="{{ url_for('handle_registration') }}" class="action-button secondary-button"><i data-lucide="user-plus"></i> Noch kein Konto? Hier registrieren</a>
</div>
{% endif %}
{% if reset_mode %}
<div class="content-card">
<h2 class="section-title"><i data-lucide="key-round"></i> Passwort zurücksetzen</h2>
<form action="{{ url_for('handle_password_reset') }}" method="POST" class="input-form">
<input type="hidden" name="token" value="{{ token }}">
<div class="form-group">
<label for="password_string" class="input-label">Neues Passwort</label>
<input type="password" id="password_string" name="password_string" class="text-input" required>
</div>
<div class="form-group">
<label for="password_string_confirmation" class="input-label">Passwort bestätigen</label>
<input type="password" id="password_string_confirmation" name="password_string_confirmation" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="save"></i> Speichern</button>
</form>
</div>
{% elif register_mode %}
<div class="content-card">
<h2 class="section-title"><i data-lucide="user-plus"></i> Registrieren</h2>
<form action="{{ url_for('handle_registration') }}" method="POST" class="input-form">
<div class="form-group">
<label for="display_name" class="input-label">Name</label>
<input type="text" id="display_name" name="display_name" class="text-input" required>
</div>
<div class="form-group">
<label for="password_string" class="input-label">Passwort</label>
<input type="password" id="password_string" name="password_string" class="text-input" required>
</div>
<div class="form-group">
<label for="password_string_confirmation" class="input-label">Passwort bestätigen</label>
<input type="password" id="password_string_confirmation" name="password_string_confirmation" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="check-circle"></i> Konto erstellen</button>
</form>
</div>
<div class="content-card" style="text-align: center;">
<a href="{{ url_for('handle_login') }}" class="action-button secondary-button"><i data-lucide="arrow-left"></i> Zur Anmeldung</a>
</div>
{% elif registration_success %}
<div class="content-card notice-card success-card" style="text-align: center;">
<h2 class="section-title" style="justify-content: center;"><i data-lucide="party-popper"></i> Erfolgreich</h2>
<h2 style="color: var(--fallback-danger); color: oklch(var(--lightness-danger) var(--chroma-danger) var(--hue-danger));">Wichtig!</h2>
<p>Deine ID:</p>
<h1 class="monospace-identifier" style="font-size: calc(3rem * var(--dimension-multiplier)); letter-spacing: calc(0.25rem * var(--dimension-multiplier)); color: var(--fallback-primary); color: oklch(var(--lightness-primary) var(--chroma-primary) var(--hue-primary)); margin: var(--spacing-medium) 0;">{{ new_identifier }}</h1>
<button type="button" id="copy-identifier-button" class="action-button secondary-button" data-identifier="{{ new_identifier }}"><i data-lucide="copy"></i> ID kopieren</button>
<p style="margin-top: var(--spacing-medium);">Gut aufbewahren!</p>
<div style="margin-top: var(--spacing-large);">
<a href="{{ url_for('handle_login', prefill_identifier=new_identifier) }}" class="action-button primary-button"><i data-lucide="log-in"></i> Anmelden</a>
</div>
</div>
{% else %}
<div class="content-card">
<h2 class="section-title"><i data-lucide="lock"></i> Login</h2>
<form action="{{ url_for('handle_login') }}" method="POST" class="input-form">
<div class="form-group">
<label for="player_identifier" class="input-label">ID</label>
<input type="text" id="player_identifier" name="player_identifier" class="text-input" value="{{ request.args.get('prefill_identifier', '') }}" style="text-transform: uppercase;" maxlength="{{ identifier_length }}" oninput="this.value = this.value.replace(/[^a-zA-Z]/g, '').toUpperCase().slice(0, {{ identifier_length }});" pattern="[A-Za-z]{{ '{' }}{{ identifier_length }}{{ '}' }}" required>
</div>
<div class="form-group">
<label for="password_string" class="input-label">Passwort</label>
<input type="password" id="password_string" name="password_string" class="text-input" required>
</div>
<button type="submit" class="action-button primary-button"><i data-lucide="log-in"></i> Anmelden</button>
</form>
</div>
<div class="content-card" style="text-align: center; display: flex; flex-direction: column; gap: var(--spacing-medium);">
<a href="{{ url_for('handle_registration') }}" class="action-button secondary-button"><i data-lucide="user-plus"></i> Registrieren</a>
<button type="button" id="trigger-help-modal" class="action-button secondary-button"><i data-lucide="life-buoy"></i> Probleme beim Login?</button>
</div>
<div id="help-modal" class="modal-overlay">
<div class="modal-dialog">
<h2 class="modal-title"><i data-lucide="help-circle"></i> Hilfe</h2>
<p class="modal-description">Wende dich an die Spielleitung, falls du deine ID oder dein Passwort vergessen hast.</p>
<div class="modal-actions">
<button type="button" id="close-help-modal" class="action-button primary-button"><i data-lucide="check"></i> Okay</button>
</div>
</div>
</div>
{% endif %}
</section>
{% endblock %}