SpotifyRoulette/src/main/resources/public/game.html

230 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Spotify Roulette Spiel</title>
<!-- Font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<style>
:root{
--bg:#121212; --elev:#181818; --border:#282828; --text:#fff; --muted:#b3b3b3;
--accent:#1db954; --accent-press:#169e47; --glow:rgba(29,185,84,.25);
--radius:16px; --shadow:0 10px 30px rgba(0,0,0,.35);
}
*{box-sizing:border-box}
html,body{height:100%}
body{
margin:0; font-family:Inter,system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial;
color:var(--text);
background:
radial-gradient(1200px 600px at 20% -10%, rgba(29,185,84,.15), transparent 60%),
radial-gradient(1000px 500px at 100% -20%, rgba(29,185,84,.12), transparent 70%),
var(--bg);
}
.container{max-width:1100px; margin:0 auto; padding:24px}
/* Header */
header{
display:flex; align-items:center; justify-content:space-between; gap:16px;
padding-bottom:12px; border-bottom:1px solid var(--border);
}
.brand{display:flex; align-items:center; gap:12px}
.logo{width:36px; height:36px; border-radius:50%; background:var(--accent); color:#121212;
display:grid; place-content:center; box-shadow:0 0 0 6px var(--glow)}
h1{margin:0; font-size:20px; letter-spacing:.2px}
.pill{display:inline-flex; align-items:center; gap:8px; padding:6px 10px; border-radius:999px;
border:1px solid var(--border); background:#101010; color:var(--muted); font-weight:600}
.pill b{color:#fff; letter-spacing:.08em}
.row{display:flex; gap:10px; align-items:center; flex-wrap:wrap}
.btn{border:0; padding:10px 14px; border-radius:999px; font-weight:700; cursor:pointer;
transition:transform .06s, filter .15s, background .2s}
.btn:active{transform:translateY(1px)}
.btn-primary{background:var(--accent); color:#0a0a0a}
.btn-primary:hover{filter:brightness(1.05)}
.btn-primary:active{background:var(--accent-press)}
.btn-ghost{background:transparent; color:var(--text); border:1px solid var(--border)}
.btn-ghost:hover{border-color:var(--muted)}
.muted{color:var(--muted)}
/* Grid */
.grid{display:grid; grid-template-columns:1.1fr .9fr; gap:24px; margin-top:20px}
@media (max-width:980px){.grid{grid-template-columns:1fr}}
/* Cards */
.card{background:var(--elev); border:1px solid var(--border); border-radius:var(--radius); box-shadow:var(--shadow)}
.card-hd{padding:18px 18px 8px; display:flex; align-items:center; justify-content:space-between}
.card-bd{padding:16px 18px 20px}
/* Now Playing */
.now{display:grid; grid-template-columns:96px 1fr; gap:16px; align-items:center}
.cover{width:96px; height:96px; border-radius:10px; background:#0d0d0d; border:1px solid var(--border);
overflow:hidden; display:grid; place-content:center}
.cover img{width:100%; height:100%; object-fit:cover}
.track-title{font-size:18px; font-weight:700; margin:0 0 2px}
.artists{color:var(--muted); margin:0 0 6px}
#songEmbed iframe{border-radius:10px; width:100%; height:80px; border:0}
/* Round area (Kreis) */
#roundArea[hidden]{display:none}
#options{
position:relative; width:100%; max-width:520px; aspect-ratio:1; margin:14px 0 6px;
border-radius:50%; border:1px dashed var(--border);
background: radial-gradient(240px 240px at 50% 50%, rgba(29,185,84,.08), transparent 60%);
}
.player-option{
position:absolute;
left:50%; /* neu */
top:50%; /* neu */
transform-origin:center;
background:#0f0f0f; color:var(--text);
border:1px solid var(--border);
border-radius:999px; padding:8px 12px;
font-weight:700;
white-space:nowrap;
transition:filter .15s, transform .06s, background .2s, box-shadow .2s;
box-shadow:0 0 0 0 var(--glow);
}
.player-option:hover{filter:brightness(1.1)}
.player-option:active{transform:scale(.98)}
.player-option:disabled{opacity:.7}
.player-option.correct{background:var(--accent); color:#0a0a0a; box-shadow:0 0 0 6px var(--glow)}
/* Players + Scoreboard */
#playersList{list-style:none; padding:0; margin:0; display:grid;
grid-template-columns:repeat(auto-fill, minmax(200px,1fr)); gap:12px}
#playersList > *{display:flex; align-items:center; gap:10px; padding:10px;
border:1px solid var(--border); border-radius:12px; background:#101010}
#scoreboard{list-style:none; padding:0; margin:0}
#scoreboard li{display:flex; justify-content:space-between; padding:10px 4px; border-bottom:1px solid var(--border)}
/* Aside / Device select */
aside{background:transparent}
.section-title{font-weight:700; margin:0 0 10px}
#songList{list-style:none; padding:0; margin:0 0 14px; display:flex; flex-direction:column; gap:8px}
#songList li{padding:10px 12px; border:1px solid var(--border); border-radius:10px; background:#101010}
#deviceSelectArea label{color:var(--muted); font-size:13px}
#deviceSelect{
width:100%; margin-top:8px;
background:#0f0f0f; color:#fff; border:1px solid var(--border); border-radius:12px; padding:10px 12px; outline:none;
}
#deviceSelect:focus{border-color:var(--accent); box-shadow:0 0 0 3px var(--glow)}
/* Toast (Clipboard-Notice) */
.toast{position:fixed; left:50%; bottom:22px; transform:translateX(-50%);
background:#101010; color:#fff; border:1px solid var(--border);
padding:10px 14px; border-radius:999px; box-shadow:var(--shadow); z-index:50; display:none}
.toast.show{display:block}
/* Slide-out Drawer für Songliste (wie im Beispiel) */
.drawer{position:fixed; top:0; right:0; height:100%; width:340px; background:#0f0f0f;
border-left:1px solid var(--border); transform:translateX(100%); transition:transform .25s ease;
z-index:60; display:flex; flex-direction:column}
.drawer.open{transform:translateX(0)}
.drawer header{padding:16px; border-bottom:1px solid var(--border); display:flex; justify-content:space-between; align-items:center}
.drawer .list{padding:12px 16px; overflow:auto}
.drawer .track{display:flex; align-items:center; gap:10px; padding:8px 6px; border-radius:10px}
.drawer .track:hover{background:#141414}
.drawer .tcover{width:40px; height:40px; border-radius:6px; background:#1a1a1a; border:1px solid var(--border)}
.drawer .meta{display:flex; flex-direction:column}
.drawer .meta b{font-size:13px}
.drawer .meta span{font-size:12px; color:var(--muted)}
</style>
</head>
<body>
<div class="container">
<header>
<div class="brand">
<div class="logo" aria-hidden="true">
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M12 2 2 7l10 5 10-5-10-5Zm10 7-10 5v9l10-5V9ZM2 9v9l10 5v-9L2 9Z"/>
</svg>
</div>
<h1>Spotify Roulette</h1>
</div>
<div class="row">
<span class="pill">Spiel-Code: <b id="gameId"></b></span>
<button id="toggleSongList" class="btn btn-ghost" title="Zuletzt gehörte Songs">Songliste</button>
</div>
</header>
<div class="grid">
<!-- LEFT: Now Playing + Runde -->
<section class="card">
<div class="card-hd">
<h2 style="margin:0">Now Playing</h2>
<div class="row">
<button id="startRound" class="btn btn-ghost">Runde starten</button>
</div>
</div>
<div class="card-bd">
<!-- <div class="now" style="margin-bottom:10px">-->
<!-- <div class="cover" aria-hidden="true">-->
<!-- <svg width="48" height="48" viewBox="0 0 24 24" fill="#333"><path d="M12 3a9 9 0 1 0 .001 18.001A9 9 0 0 0 12 3Zm0 2a7 7 0 1 1-.001 14.001A7 7 0 0 1 12 5Zm0 3a4 4 0 1 0 .001 8.001A4 4 0 0 0 12 8Z"/></svg>-->
<!-- </div>-->
<!-- <div>-->
<!-- <p id="trackTitle" class="track-title">—</p>-->
<!-- <p id="trackArtists" class="artists">—</p>-->
<!-- </div>-->
<!-- </div>-->
<!-- IDs exakt wie dein game.js -->
<section id="roundArea" hidden>
<div id="songEmbed" style="margin-bottom:12px"></div>
<div id="options"></div>
<div id="result" class="muted" style="margin-top:10px"></div>
<button id="nextRound" class="btn btn-primary" hidden>Nächster Song</button>
</section>
</div>
</section>
<!-- RIGHT: Teilnehmer + Scoreboard -->
<section class="card">
<div class="card-hd">
<h2 style="margin:0">Teilnehmer</h2>
<button id="refreshPlayers" class="btn btn-ghost">Aktualisieren</button>
</div>
<div class="card-bd">
<ul id="playersList"></ul>
</div>
<div class="card-hd"><h2 style="margin:0">Scoreboard</h2></div>
<div class="card-bd">
<ul id="scoreboard"></ul>
</div>
</section>
</div>
<!-- ASIDE: Geladene Songs + Wiedergabegerät -->
<div id="deviceSelectArea"></div>
</aside>
</div>
<!-- Slide-out Drawer für Songliste -->
<aside class="drawer" id="songDrawer" aria-label="Zuletzt gehörte Songs">
<header>
<h3 style="margin:0">Zuletzt gehört</h3>
<button class="btn btn-ghost" id="closeDrawer">Schließen</button>
</header>
<div class="list" id="songListArea"></div>
</aside>
<!-- Toast für Clipboard-Notice -->
<div id="toast" class="toast" role="status" aria-live="polite"></div>
<!-- Deine existierenden Module -->
<script type="module" src="/js/utils.js"></script>
<script type="module" src="/js/start-round.js"></script>
<script type="module" src="/js/device-select.js"></script> <!-- füllt #deviceSelectArea -->
<script type="module" src="/js/game.js"></script>
</body>
</html>