feat: Implement initial client-side UI rendering for game rooms, player dashboards, and track timelines, alongside core WebSocket server functionality.
All checks were successful
Build and Push Docker Image / docker (push) Successful in 13s
All checks were successful
Build and Push Docker Image / docker (push) Successful in 13s
This commit is contained in:
@@ -9,7 +9,9 @@ import {
|
||||
import { state } from "./state.js";
|
||||
import { cacheLastRoomId, cacheSessionId, clearSessionId, sendMsg } from "./ws.js";
|
||||
import { renderRoom } from "./render.js";
|
||||
import { applySync, loadTrack, getSound } from "./audio.js";
|
||||
import { applySync, loadTrack, getSound, stopAudioPlayback } from "./audio.js";
|
||||
import { playCorrect, playWrong, playWinner, playTurnStart, playCoinEarned } from "./sfx.js";
|
||||
import { showReaction, celebrateCorrect } from "./reactions.js";
|
||||
|
||||
function updatePlayerIdFromRoom(r) {
|
||||
try {
|
||||
@@ -101,6 +103,11 @@ export function handlePlayTrack(msg) {
|
||||
}
|
||||
}, delay);
|
||||
|
||||
// Play turn start sound if it's the current player's turn
|
||||
if (state.room?.state?.currentGuesser === state.playerId) {
|
||||
playTurnStart();
|
||||
}
|
||||
|
||||
if (state.room) renderRoom(state.room);
|
||||
}
|
||||
|
||||
@@ -143,10 +150,13 @@ export function handleReveal(msg) {
|
||||
$rb.textContent = "Richtig!";
|
||||
$rb.className =
|
||||
"inline-block rounded-md bg-emerald-600 text-white px-3 py-1 text-sm font-medium";
|
||||
playCorrect();
|
||||
celebrateCorrect(); // Auto 🎉 animation
|
||||
} else {
|
||||
$rb.textContent = "Falsch!";
|
||||
$rb.className =
|
||||
"inline-block rounded-md bg-rose-600 text-white px-3 py-1 text-sm font-medium";
|
||||
playWrong();
|
||||
}
|
||||
}
|
||||
// Note: placeArea visibility is now controlled by renderRoom() based on game phase
|
||||
@@ -167,6 +177,8 @@ export function handleReveal(msg) {
|
||||
}
|
||||
|
||||
export function handleGameEnded(msg) {
|
||||
// Play winner fanfare
|
||||
playWinner();
|
||||
// Create and show the winner popup with confetti
|
||||
showWinnerPopup(msg);
|
||||
}
|
||||
@@ -208,9 +220,14 @@ function showWinnerPopup(msg) {
|
||||
${timelineHtml}
|
||||
</div>
|
||||
</div>
|
||||
<button id="closeWinnerBtn" class="mt-6 px-6 py-3 bg-white text-indigo-600 font-bold rounded-xl hover:bg-indigo-100 transition-colors shadow-lg">
|
||||
Schließen
|
||||
</button>
|
||||
<div class="mt-6 flex flex-col sm:flex-row gap-3 justify-center">
|
||||
<button id="rematchBtn" class="px-6 py-3 bg-emerald-500 text-white font-bold rounded-xl hover:bg-emerald-600 transition-colors shadow-lg flex items-center justify-center gap-2">
|
||||
🔄 Rematch
|
||||
</button>
|
||||
<button id="closeWinnerBtn" class="px-6 py-3 bg-white text-indigo-600 font-bold rounded-xl hover:bg-indigo-100 transition-colors shadow-lg">
|
||||
Schließen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -219,6 +236,13 @@ function showWinnerPopup(msg) {
|
||||
// Start confetti animation
|
||||
createConfetti();
|
||||
|
||||
// Rematch button handler
|
||||
document.getElementById('rematchBtn').addEventListener('click', () => {
|
||||
stopAudioPlayback(); // Stop the music
|
||||
sendMsg({ type: 'rematch' });
|
||||
overlay.remove();
|
||||
});
|
||||
|
||||
// Close button handler
|
||||
document.getElementById('closeWinnerBtn').addEventListener('click', () => {
|
||||
overlay.remove();
|
||||
@@ -333,8 +357,12 @@ export function onMessage(ev) {
|
||||
parts.push(msg.correctTitle ? "Titel ✓" : "Titel ✗");
|
||||
parts.push(msg.correctArtist ? "Künstler ✓" : "Künstler ✗");
|
||||
let coin = "";
|
||||
if (msg.awarded) coin = " +1 Token";
|
||||
else if (msg.alreadyAwarded) coin = " (bereits erhalten)";
|
||||
if (msg.awarded) {
|
||||
coin = " +1 Token";
|
||||
playCoinEarned();
|
||||
} else if (msg.alreadyAwarded) {
|
||||
coin = " (bereits erhalten)";
|
||||
}
|
||||
$answerResult.textContent = `${parts.join(" · ")}${coin}`;
|
||||
$answerResult.className = okBoth
|
||||
? "mt-1 text-sm text-emerald-600"
|
||||
@@ -345,5 +373,10 @@ export function onMessage(ev) {
|
||||
}
|
||||
default:
|
||||
return;
|
||||
case "reaction": {
|
||||
// Show reaction from another player
|
||||
showReaction(msg.emoji, msg.playerName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user