Merge branch '42-websockets-in-lobby-zur-aktualisierung-der-spielerliste' into 'master'

Resolve "Websockets in Lobby zur aktualisierung der Spielerliste"

Closes #42

See merge request enrichment-2024/qivip!25
This commit is contained in:
Juhn-Vitus Saß
2025-04-05 14:23:27 +00:00
14 changed files with 359 additions and 43 deletions

View File

@@ -85,7 +85,7 @@
<!-- Buttons bleiben am unteren Rand -->
<div class="flex justify-between items-center gap-2 ">
<a href="#" class="qp-a-button-small border-2 border-blue-600 text-white font-bold text-white drop-shadow-lg custom-outline">Spiel starten</a>
<a href="{% url 'play:create_game' quiz.id %}" class="qp-a-button-small border-2 border-blue-600 text-white font-bold text-white drop-shadow-lg custom-outline">Spiel starten</a>
<div class="flex gap-2">
<a href="{% url 'library:detail_quiz' quiz.id %}" class="qp-a-button-small border-2 border-blue-600 text-white font-bold drop-shadow-lg custom-outline">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-7">
@@ -145,7 +145,7 @@
<!-- Buttons bleiben am unteren Rand -->
<div class="flex justify-between items-center gap-2 ">
<a href="#" class="qp-a-button-small border-2 border-blue-600 text-white font-bold text-white drop-shadow-lg custom-outline">Spiel starten</a>
<a href="{% url 'play:create_game' quiz.id %}" class="qp-a-button-small border-2 border-blue-600 text-white font-bold text-white drop-shadow-lg custom-outline">Spiel starten</a>
<a href="{% url 'library:detail_quiz' quiz.id %}" class="qp-a-button-small border-2 border-blue-600 text-white text-white font-bold text-white drop-shadow-lg custom-outline">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-7">
<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
@@ -176,7 +176,7 @@
{% endif %}
{% if not filter_other_quizzes and not filter_my_quizzes %}
<div class="grid text-center font-bold items-center">Es wurde kein Quiz passendes gefunden!</div>
<div class="grid text-center font-bold items-center">Es wurde kein passendes Quiz gefunden!</div>
{% endif %}

View File

@@ -2,20 +2,73 @@
{% block content %}
<div class="container mx-auto px-4">
<h1>{{ quiz.name }}</h1>
<h3>{{ quiz.name }}</h3>
<h1 class="text-center text-4xl font-bold mb-4">{{ quiz_game.join_code }}</h1>
{% if participant %}
<div class="mt-4 mb-4 text-center">
<h3>Sichtbar als <b>{{ participant.display_name }}</b></h3>
</div>
<div id="player-list">
<ul>
<li>Noch keine Spieler gefunden.</li>
{% endif %}
<div class="mb-4">
<h3 class="font-bold mb-2">Teilnehmer:</h3>
<ul id="participants-list" class="space-y-2">
<li class="text-gray-500">Warte auf Teilnehmer...</li>
</ul>
{{debug}}
</div>
<button class="w-full p-3 rounded-full bg-blue-600 text-white font-black hover:scale-105 transition duration-200" type="submit">Starten</button>
{% if host_id %}
<button id="start-button" class="w-full p-3 rounded-full bg-blue-600 text-white font-black hover:scale-105 transition duration-200" type="button">Starten</button>
{% endif %}
</div>
{% endblock %}
{% block extra_js %}
<script>
// TODO: Websocket Verbindung aufbauen und Teilnehmerliste bei beitreten updaten
const joinCode = '{{ quiz_game.join_code }}';
const wsScheme = window.location.protocol === 'https:' ? 'wss' : 'ws';
const lobbySocket = new WebSocket(
wsScheme + '://' + window.location.host + '/ws/game/' + joinCode + '/'
);
lobbySocket.onmessage = function(e) {
const data = JSON.parse(e.data);
if (data.type === 'participant_list' || data.type === 'participant_list_update') {
updateParticipantsList(data.participants);
}
};
lobbySocket.onclose = function(e) {
console.error('Lobby socket closed unexpectedly');
};
{% if participant %}
// Send heartbeat every 10 seconds
setInterval(() => {
if (lobbySocket.readyState === WebSocket.OPEN) {
lobbySocket.send(JSON.stringify({
'type': 'heartbeat',
'participant_id': '{{ participant.participant_id }}'
}));
}
}, 10000);
{% endif %}
function updateParticipantsList(participants) {
const list = document.getElementById('participants-list');
if (participants.length === 0) {
list.innerHTML = '<li class="text-gray-500">Noch keine Teilnehmer...</li>';
return;
}
list.innerHTML = participants
.map(p => `<li class="p-2 bg-gray-100 rounded">${p.name}</li>`)
.join('');
}
// Request initial participants list
lobbySocket.onopen = function(e) {
lobbySocket.send(JSON.stringify({
'type': 'update_participants'
}));
};
</script>
{% endblock %}