feat: add tokens column to dashboard and update rendering logic
All checks were successful
Build and Push Docker Image / docker (push) Successful in 8s
All checks were successful
Build and Push Docker Image / docker (push) Successful in 8s
This commit is contained in:
@@ -113,6 +113,7 @@
|
||||
<th class="py-2 pr-3">Verbindung</th>
|
||||
<th class="py-2 pr-3">Ready</th>
|
||||
<th class="py-2 pr-3">Score</th>
|
||||
<th class="py-2 pr-3">Tokens</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="dashboardList" class="divide-y divide-slate-200 dark:divide-slate-800"></tbody>
|
||||
@@ -144,99 +145,117 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="nowPlaying"
|
||||
class="hidden rounded-lg border border-slate-200 dark:border-slate-800 p-4 bg-slate-50/60 dark:bg-slate-800/60">
|
||||
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-3">
|
||||
<div class="text-lg font-semibold">
|
||||
<strong id="npTitle"> </strong><span id="npArtist"></span><span id="npYear"
|
||||
class="text-slate-500"></span>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<!-- Player Card -->
|
||||
<div id="nowPlaying"
|
||||
class="hidden md:row-span-2 h-full rounded-lg border border-slate-200 dark:border-slate-800 p-4 bg-slate-50/60 dark:bg-slate-800/60">
|
||||
<h3 class="text-lg font-semibold mb-2">Musik-Player</h3>
|
||||
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-3">
|
||||
<div class="text-lg font-semibold">
|
||||
<strong id="npTitle"> </strong><span id="npArtist"></span><span id="npYear"
|
||||
class="text-slate-500"></span>
|
||||
</div>
|
||||
<div id="revealBanner" class="hidden"></div>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<audio id="audio" preload="none" class="hidden"></audio>
|
||||
<div class="flex flex-col items-center">
|
||||
<!-- Record Disc -->
|
||||
<div class="relative" style="width: 200px; height: 200px">
|
||||
<img id="recordDisc" src="/hitstar.png" alt="Record"
|
||||
class="w-full h-full rounded-full object-cover shadow-lg ring-2 ring-slate-300 dark:ring-slate-700" />
|
||||
<!-- center hole overlay -->
|
||||
<div class="pointer-events-none absolute inset-0 rounded-full" style="
|
||||
background: radial-gradient(
|
||||
circle at center,
|
||||
transparent 0 14px,
|
||||
rgba(0, 0, 0, 0.22) 14px,
|
||||
transparent 16px
|
||||
);
|
||||
"></div>
|
||||
<!-- buffering badge -->
|
||||
<div id="bufferBadge"
|
||||
class="absolute bottom-2 left-1/2 -translate-x-1/2 rounded bg-slate-900/80 text-white text-xs px-2 py-1 hidden">
|
||||
Buffering…
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Progress bar -->
|
||||
<div class="mt-4 w-full">
|
||||
<div class="relative h-2 rounded-full bg-slate-200 dark:bg-slate-700 overflow-hidden">
|
||||
<div id="progressFill" class="absolute left-0 top-0 h-full bg-indigo-600" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Controls (Play/Pause restricted to guesser) -->
|
||||
<div id="mediaControls" class="hidden mt-4 flex items-center gap-3">
|
||||
<button id="playBtn"
|
||||
class="h-10 px-4 rounded-lg bg-emerald-600 hover:bg-emerald-700 text-white font-medium">
|
||||
Play
|
||||
</button>
|
||||
<button id="pauseBtn" class="h-10 px-4 rounded-lg bg-rose-600 hover:bg-rose-700 text-white font-medium">
|
||||
Pause
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Volume (available to all players) -->
|
||||
<div class="mt-3">
|
||||
<label class="inline-flex items-center gap-2 text-sm text-slate-700 dark:text-slate-300">
|
||||
Lautstärke
|
||||
<input id="volumeSlider" type="range" min="0" max="1" step="0.01" class="w-40 accent-indigo-600" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="revealBanner" class="hidden"></div>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<audio id="audio" preload="none" class="hidden"></audio>
|
||||
<div class="flex flex-col items-center">
|
||||
<!-- Record Disc -->
|
||||
<div class="relative" style="width: 200px; height: 200px">
|
||||
<img id="recordDisc" src="/hitstar.png" alt="Record"
|
||||
class="w-full h-full rounded-full object-cover shadow-lg ring-2 ring-slate-300 dark:ring-slate-700" />
|
||||
<!-- center hole overlay -->
|
||||
<div class="pointer-events-none absolute inset-0 rounded-full" style="
|
||||
background: radial-gradient(
|
||||
circle at center,
|
||||
transparent 0 14px,
|
||||
rgba(0, 0, 0, 0.22) 14px,
|
||||
transparent 16px
|
||||
);
|
||||
"></div>
|
||||
<!-- buffering badge -->
|
||||
<div id="bufferBadge"
|
||||
class="absolute bottom-2 left-1/2 -translate-x-1/2 rounded bg-slate-900/80 text-white text-xs px-2 py-1 hidden">
|
||||
Buffering…
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Progress bar -->
|
||||
<div class="mt-4 w-full">
|
||||
<div class="relative h-2 rounded-full bg-slate-200 dark:bg-slate-700 overflow-hidden">
|
||||
<div id="progressFill" class="absolute left-0 top-0 h-full bg-indigo-600" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Controls (Play/Pause restricted to guesser) -->
|
||||
<div id="mediaControls" class="hidden mt-4 flex items-center gap-3">
|
||||
<button id="playBtn"
|
||||
class="h-10 px-4 rounded-lg bg-emerald-600 hover:bg-emerald-700 text-white font-medium">
|
||||
Play
|
||||
</button>
|
||||
<button id="pauseBtn" class="h-10 px-4 rounded-lg bg-rose-600 hover:bg-rose-700 text-white font-medium">
|
||||
Pause
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Volume (available to all players) -->
|
||||
<div class="mt-3">
|
||||
<label class="inline-flex items-center gap-2 text-sm text-slate-700 dark:text-slate-300">
|
||||
Lautstärke
|
||||
<input id="volumeSlider" type="range" min="0" max="1" step="0.01" class="w-40 accent-indigo-600" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Answer form: everyone can try to guess title & artist for a coin -->
|
||||
<form id="answerForm" class="mt-4 w-full flex flex-col md:flex-row gap-2 md:items-end">
|
||||
<label class="flex-1 text-sm">
|
||||
<span class="text-slate-700 dark:text-slate-300">Titel</span>
|
||||
<input id="guessTitle" name="title" placeholder="Songtitel" autocomplete="off"
|
||||
class="mt-1 w-full h-10 rounded-lg border border-slate-300 dark:border-slate-700 bg-white/80 dark:bg-slate-800 px-3" />
|
||||
</label>
|
||||
<label class="flex-1 text-sm">
|
||||
<span class="text-slate-700 dark:text-slate-300">Künstler</span>
|
||||
<input id="guessArtist" name="artist" placeholder="Künstler" autocomplete="off"
|
||||
class="mt-1 w-full h-10 rounded-lg border border-slate-300 dark:border-slate-700 bg-white/80 dark:bg-slate-800 px-3" />
|
||||
</label>
|
||||
<!-- Guess Card -->
|
||||
<div id="guessBox"
|
||||
class="rounded-lg border border-slate-200 dark:border-slate-800 p-4 bg-white/70 dark:bg-slate-900/60">
|
||||
<h3 class="text-lg font-semibold">Raten</h3>
|
||||
<p class="text-sm text-slate-500 dark:text-slate-400 mb-2">Gib Titel und Künstler ein und drücke Abschicken.
|
||||
</p>
|
||||
<form id="answerForm" class="mt-2 w-full flex flex-col gap-2">
|
||||
<label class="text-sm">
|
||||
<span class="text-slate-700 dark:text-slate-300">Titel</span>
|
||||
<input id="guessTitle" name="title" placeholder="Songtitel" autocomplete="off"
|
||||
class="mt-1 w-full h-11 rounded-lg border border-slate-300 dark:border-slate-700 bg-white/80 dark:bg-slate-800 px-3" />
|
||||
</label>
|
||||
<label class="text-sm">
|
||||
<span class="text-slate-700 dark:text-slate-300">Künstler</span>
|
||||
<input id="guessArtist" name="artist" placeholder="Künstler" autocomplete="off"
|
||||
class="mt-1 w-full h-11 rounded-lg border border-slate-300 dark:border-slate-700 bg-white/80 dark:bg-slate-800 px-3" />
|
||||
</label>
|
||||
<div class="flex items-center gap-2">
|
||||
<button id="submitAnswer" type="submit"
|
||||
class="h-10 px-4 rounded-lg bg-emerald-600 hover:bg-emerald-700 text-white font-medium">
|
||||
class="h-11 px-4 rounded-lg bg-emerald-600 hover:bg-emerald-700 text-white font-medium">
|
||||
Abschicken
|
||||
</button>
|
||||
</form>
|
||||
<div id="answerResult" class="mt-1 text-sm"></div>
|
||||
</div>
|
||||
<div id="answerResult" class="text-sm"></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="mt-3 flex flex-wrap items-center gap-3">
|
||||
<div id="placeArea" class="hidden flex items-center gap-2">
|
||||
<label class="text-sm text-slate-600 dark:text-slate-300">Position:
|
||||
|
||||
<!-- Position Card (under Guess, beside Player) -->
|
||||
<div id="positionBox"
|
||||
class="rounded-lg border border-slate-200 dark:border-slate-800 p-4 bg-white/70 dark:bg-slate-900/60 md:col-start-2">
|
||||
<h3 class="text-lg font-semibold">Position</h3>
|
||||
<p class="text-sm text-slate-500 dark:text-slate-400 mb-2">Wähle die Position und klicke Platzieren.</p>
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<div id="placeArea" class="hidden flex items-center gap-2">
|
||||
<select id="slotSelect"
|
||||
class="ml-2 h-10 rounded-lg border border-slate-300 dark:border-slate-700 bg-white/80 dark:bg-slate-800 px-3"></select>
|
||||
</label>
|
||||
<button id="placeBtn"
|
||||
class="h-10 px-4 rounded-lg bg-slate-900 hover:bg-slate-700 text-white font-medium dark:bg-slate-700 dark:hover:bg-slate-600">
|
||||
Platzieren
|
||||
</button>
|
||||
</div>
|
||||
<div id="nextArea" class="hidden">
|
||||
<button id="nextBtn" class="h-10 px-4 rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white font-medium">
|
||||
Next
|
||||
</button>
|
||||
class="h-10 rounded-lg border border-slate-300 dark:border-slate-700 bg-white/80 dark:bg-slate-800 px-3"></select>
|
||||
<button id="placeBtn"
|
||||
class="h-10 px-4 rounded-lg bg-slate-900 hover:bg-slate-700 text-white font-medium dark:bg-slate-700 dark:hover:bg-slate-600">
|
||||
Platzieren
|
||||
</button>
|
||||
</div>
|
||||
<div id="nextArea" class="hidden">
|
||||
<button id="nextBtn"
|
||||
class="h-10 px-4 rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white font-medium">
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -248,9 +267,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-3 text-slate-700 dark:text-slate-300">
|
||||
Tokens: <span id="tokens" class="font-semibold">0</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ export const $nameDisplay = el('nameDisplay');
|
||||
export const $status = el('status');
|
||||
export const $guesser = el('guesser');
|
||||
export const $timeline = el('timeline');
|
||||
export const $tokens = el('tokens');
|
||||
export const $audio = el('audio');
|
||||
export const $np = el('nowPlaying');
|
||||
export const $npTitle = el('npTitle');
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
$startGame,
|
||||
$status,
|
||||
$timeline,
|
||||
$tokens,
|
||||
} from './dom.js';
|
||||
|
||||
export function renderRoom(room) {
|
||||
@@ -58,6 +57,7 @@ export function renderRoom(room) {
|
||||
? '<span class="text-emerald-600">bereit</span>'
|
||||
: '<span class="text-slate-400">-</span>';
|
||||
const score = room.state.timeline?.[p.id]?.length ?? 0;
|
||||
const tokens = room.state.tokens?.[p.id] ?? 0;
|
||||
const isMe = p.id === state.playerId;
|
||||
return `
|
||||
<tr class="align-top">
|
||||
@@ -71,6 +71,7 @@ export function renderRoom(room) {
|
||||
<td class="py-2 pr-3">${connected}</td>
|
||||
<td class="py-2 pr-3">${ready}</td>
|
||||
<td class="py-2 pr-3 font-semibold tabular-nums">${score}</td>
|
||||
<td class="py-2 pr-3 font-semibold tabular-nums">${tokens}</td>
|
||||
</tr>`;
|
||||
})
|
||||
.join('');
|
||||
@@ -93,7 +94,6 @@ export function renderRoom(room) {
|
||||
`;
|
||||
})
|
||||
.join('');
|
||||
$tokens.textContent = room.state.tokens?.[state.playerId] ?? 0;
|
||||
if ($readyChk) {
|
||||
const serverReady = !!me?.ready;
|
||||
if (state.pendingReady === null || state.pendingReady === undefined) {
|
||||
|
||||
Reference in New Issue
Block a user