publicquiz/templates/host.html
2025-07-06 14:50:13 +00:00

159 lines
5.1 KiB
HTML

<!-- host.html -->
{% extends 'base.html' %}
{% block content %}
<h1 class="mb-4">Public Quiz</h1>
<div class="container" id="host-app">
<!-- QR & Join Roster -->
<div id="qrContainer" class="mb-4 text-center">
<img id="qrImg"
src="data:image/png;base64,{{ qr_data }}"
class="img-fluid"
style="max-width:300px;"/>
<p class="mt-2">Scanne den QR-Code, um dem Spiel beizutreten!</p>
</div>
<!-- new-game form -->
<form action="{{ url_for('new_game') }}" method="post" class="d-inline">
<button type="submit" class="btn btn-secondary mb-3" id="newGameButton">
Spiel neu starten
</button>
</form>
<button id="startBtn" class="btn btn-primary mb-3" disabled>Spiel beginnen</button>
<h3 id="rosterHeader">Spieler Beigetreten:</h3>
<ul id="roster" class="list-group mb-4"></ul>
<!-- Question & Current Leaderboard -->
<div id="host-question" style="display:none;">
<h2 id="qText" style="font-size:5rem;"></h2>
<div id="host-results" style="display:none; margin:20px;">
<ul id="perQ" class="list-group mb-3 text-center"></ul>
</div>
<div class="mt-3">
<button id="showAnswerBtn" class="btn btn-info">Antwort zeigen</button>
<button id="nextBtn" class="btn btn-warning" disabled>Nächste Frage</button>
</div>
</div>
<!-- Final Top-10 Leaderboard -->
<div id="final-results" style="display:none;" class="mt-4">
<h4>Rangliste</h4>
<table class="table table-striped">
<thead>
<tr><th>Rang</th><th>Name</th><th>Punkte</th></tr>
</thead>
<tbody id="finalResultsBody"></tbody>
</table>
</div>
<!-- Persistent Overall Leaderboard Footer -->
<footer id="overallFooter" class="mt-4 bg-light border-top" style="position:fixed; bottom:0; left:0; width:100%; z-index:1000; display:none;">
<div class="container py-2">
<h4 class="mb-2">Rangliste</h4>
<table class="table table-striped mb-0">
<thead><tr><th>Name</th><th>Punkte</th></tr></thead>
<tbody id="overallFooterBody"></tbody>
</table>
</div>
</footer>
</div>
<script>
const socket = io();
// Connect and fetch roster
socket.on('connect', () => {
console.log('Connected as host');
socket.emit('get_roster');
});
// Update roster when players join
socket.on('update_roster', data => {
console.log('Roster update:', data.players);
$('#roster').empty();
data.players.forEach(name => {
$('#roster').append(`<li class="list-group-item">${name}</li>`);
});
$('#startBtn').prop('disabled', data.players.length === 0);
});
// Start game
$('#startBtn').on('click', () => {
console.log('Start game clicked');
$('#newGameButton').hide();
$('#overallFooter').show();
socket.emit('start_game');
});
// Handle new question
socket.on('new_question', data => {
console.log('New question:', data.question);
$('#qrContainer, #startBtn, #rosterHeader, #roster').hide();
$('#host-question').show();
$('#qText').text(data.question);
$('#host-results').hide();
$('#showAnswerBtn').prop({ disabled: false }).show();
$('#nextBtn').prop('disabled', true);
});
// Overall leaderboard updates (max 5 rows)
socket.on('overall_leader', data => {
console.log('Overall leader:', data.board);
window.lastOverall = data;
$('#overallFooterBody').empty();
const top5 = data.board.slice(0, 5);
top5.forEach(p => {
$('#overallFooterBody').append(`<tr><td>${p.name}</td><td>${p.score}</td></tr>`);
});
});
// Next question
$('#nextBtn').off('click').on('click', () => {
console.log('Next question clicked');
socket.emit('next_question');
});
// when host clicks “Show Answer”
$('#showAnswerBtn').off('click').on('click', () => {
socket.emit('show_answer');
});
// once server confirms the answer is revealed
socket.on('answer_revealed', data => {
// display the correct answer on host screen
$('#perQ').empty();
$('#perQ').append(
`<li class="list-group-item list-group-item-success" style="font-size:5rem;">${data.correct}</li>`
);
$('#host-results').show();
// disable Show Answer button, enable Next
$('#showAnswerBtn').prop('disabled', true);
$('#nextBtn').prop('disabled', false);
});
// Show final top-10 when game_over arrives
socket.on('game_over', data => {
if (data.board) {
// hide all the old UI
$('#qrContainer, #startBtn, #rosterHeader, #roster, #host-question, #host-results, #overallFooter').hide();
$('#newGameButton').show();
// fill & show your existing <div id="final-results">…
const top10 = data.board.slice(0, 10);
$('#finalResultsBody').empty();
top10.forEach((p, i) => {
$('#finalResultsBody').append(
`<tr><td>${i+1}</td><td>${p.name}</td><td>${p.score}</td></tr>`
);
});
$('#final-results').show();
// make absolutely sure the “Start Game” button stays disabled
$('#startBtn').prop('disabled', true);
}
});
</script>
{% endblock %}