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

232 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 Lobby</title>
<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; --card:#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(1000px 500px at 20% -10%, rgba(29,185,84,.14), transparent 60%),
radial-gradient(900px 450px at 110% -20%, rgba(29,185,84,.12), transparent 70%),
var(--bg);
padding:24px;
}
.container{max-width:1100px; margin:0 auto}
header{display:flex; align-items:center; gap:12px; padding-bottom:12px; border-bottom:1px solid var(--border)}
.logo{width:40px; height:40px; 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:24px}
.pill{margin-left:auto; display:inline-flex; gap:8px; align-items:center; padding:6px 10px; border-radius:999px;
border:1px solid var(--border); background:#101010; color:var(--muted); font-size:12px}
.grid{display:grid; grid-template-columns:1fr 1fr; gap:20px; margin-top:20px}
@media (max-width:900px){ .grid{grid-template-columns:1fr} }
.card{background:var(--card); border:1px solid var(--border); border-radius:var(--radius); box-shadow:var(--shadow)}
.card .hd{padding:18px 18px 8px}
.card .bd{padding:0 18px 18px}
.muted{color:var(--muted)}
.btn{width:100%; border:0; border-radius:14px; padding:14px 16px; cursor:pointer; font-weight:700; display:flex; align-items:center; justify-content:center; gap:10px; transition:transform .06s ease, filter .15s ease, background .2s ease}
.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)}
.tile{display:flex; gap:14px; align-items:center; padding:14px; border:1px solid var(--border); border-radius:14px; background:#101010}
.tile .icon{width:44px; height:44px; border-radius:10px; display:grid; place-content:center; background:#0e0e0e; border:1px solid var(--border)}
.tile .txt{display:flex; flex-direction:column}
.tile .txt b{font-size:16px}
.tile .txt span{font-size:13px; color:var(--muted)}
/* Join form Spotify-like Input */
.row{display:flex; gap:12px; align-items:flex-end; flex-wrap:wrap}
.field{display:flex; flex-direction:column; gap:6px}
label{color:var(--muted); font-size:13px}
.inputWrap{position:relative; min-width:220px}
.inputWrap .leading-icon{
position:absolute; left:12px; top:50%; transform:translateY(-50%); opacity:.9;
}
.inputWrap .chip{
position:absolute; right:10px; top:50%; transform:translateY(-50%);
font-size:11px; color:var(--muted);
border:1px solid var(--border); background:#0d0d0d;
padding:4px 8px; border-radius:999px;
}
input#gameId{
width:100%;
background:#0b0b0b; color:var(--text);
border:1px solid var(--border);
border-radius:999px;
padding:14px 78px 14px 42px; /* Platz für Icon + Chip */
outline:none;
letter-spacing:.12em; font-weight:600;
box-shadow: inset 0 1px 0 rgba(255,255,255,.02);
transition:border-color .2s, box-shadow .2s, background .2s, transform .06s;
}
input#gameId::placeholder{color:#777}
input#gameId:focus{
border-color:var(--accent);
box-shadow:0 0 0 4px var(--glow), inset 0 1px 0 rgba(255,255,255,.02);
background:#0e0e0e;
}
input#gameId:active{transform:translateY(1px)}
/* Icon-only clipboard button */
.icon-btn{width:auto; padding:10px; border-radius:999px; display:inline-flex; align-items:center; justify-content:center}
.icon-btn svg{display:block}
.icon-btn--accent{
background:var(--accent); color:#0a0a0a;
box-shadow:0 0 0 0 var(--glow);
transition: box-shadow .2s, filter .15s, transform .06s, background .2s;
}
.icon-btn--accent:hover{ filter:brightness(1.05); box-shadow:0 0 0 6px var(--glow) }
.icon-btn--accent:active{ background:var(--accent-press); transform:translateY(1px) }
</style>
</head>
<body>
<div class="container">
<header>
<div class="logo" aria-hidden="true">
<svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2 2 7l10 5 10-5-10-5Zm10 7-10 5v9l10-5V9ZM2 9v9l10 5v-9L2 9Z"/></svg>
</div>
<h1>Lobby</h1>
<span class="pill">Angemeldet als <b id="uname" style="color:#fff"></b></span>
</header>
<section class="grid" aria-label="Aktionen">
<div class="card">
<div class="hd"><h2 style="margin:0">Neues Spiel</h2></div>
<div class="bd">
<div class="tile" style="margin-bottom:12px">
<div class="icon" aria-hidden="true">
<svg width="22" height="22" viewBox="0 0 24 24" fill="#1db954"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2Z"/></svg>
</div>
<div class="txt"><b>Spiel erstellen</b><span>Starte eine neue Runde und teile den Code.</span></div>
</div>
<button id="createGame" class="btn btn-primary">Spiel erstellen</button>
</div>
</div>
<div class="card">
<div class="hd"><h2 style="margin:0">Spiel beitreten</h2></div>
<div class="bd">
<div class="tile" style="margin-bottom:12px">
<div class="icon" aria-hidden="true">
<svg width="22" height="22" viewBox="0 0 24 24" fill="#1db954"><path d="M12 2a6 6 0 0 1 6 6v2h2v12H4V10h2V8a6 6 0 0 1 6-6Zm0 2a4 4 0 0 0-4 4v2h8V8a4 4 0 0 0-4-4Z"/></svg>
</div>
<div class="txt"><b>Bestehendem Spiel beitreten</b><span>Du hast schon einen Code? Gib ihn unten ein.</span></div>
</div>
<!-- Direktes Join-Formular in der Lobby -->
<form id="joinForm" class="row">
<div class="field">
<label for="gameId">Spiel-Code</label>
<div class="inputWrap">
<span class="leading-icon" aria-hidden="true">
<svg width="18" height="18" viewBox="0 0 24 24" fill="#1db954">
<path d="M3 11h18v10H3V11Zm9-8a5 5 0 0 1 5 5v3h-2V8a3 3 0 1 0-6 0v3H7V8a5 5 0 0 1 5-5Z"/>
</svg>
</span>
<input id="gameId" name="gameId"
placeholder="••••"
inputmode="numeric"
pattern="\d{4}"
maxlength="4"
autocomplete="one-time-code"
required />
<span class="chip">4-stellig</span>
</div>
</div>
<!-- Icon-Button: Zwischenablage (grün) -->
<button type="button" id="pasteCode"
class="btn icon-btn icon-btn--accent"
aria-label="Code aus Zwischenablage einfügen"
title="Aus Zwischenablage">
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M9 2h6a2 2 0 0 1 2 2h1a2 2 0 0 1 2 2v13a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V6a2 2 0 0 1 2-2h1a2 2 0 0 1 2-2Zm0 2a1 1 0 0 0-1 1h8a1 1 0 0 0-1-1H9Z"/>
</svg>
</button>
<button type="submit" class="btn btn-primary" style="width:auto">Beitreten</button>
<!-- (legacy) -->
<button id="joinGame" type="button" style="display:none">Join (legacy)</button>
</form>
<p class="muted" style="margin-top:8px">Tipp: Code ist vierstellig (z. B. 6767).</p>
</div>
</div>
</section>
</div>
<!-- Username-Anzeige + Clipboard-Button -->
<script type="module">
// Username-Badge
const p = new URLSearchParams(location.search);
const u = p.get('username');
if (u) document.querySelector('#uname').textContent = u;
// Clipboard-Paste für Spiel-Code
const input = document.getElementById('gameId');
const pasteBtn = document.getElementById('pasteCode');
pasteBtn?.addEventListener('click', async () => {
try {
// Clipboard ist nur über HTTPS/localhost verfügbar
const text = await navigator.clipboard.readText();
const digits = (text.match(/\d/g) || []).join('').slice(0, 4);
if (!digits) {
alert('Keinen 4-stelligen Code in der Zwischenablage gefunden.');
return;
}
input.value = digits;
input.focus();
input.select();
// Optional auto-submit, wenn 4 Ziffern vorhanden
if (digits.length === 4) {
if (input.form?.requestSubmit) input.form.requestSubmit();
else input.form?.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
}
} catch (err) {
alert('Zwischenablage nicht verfügbar. Öffne die Seite über HTTPS oder erlaube Zugriff.');
console.error(err);
}
});
</script>
<script type="module" src="/js/lobby.js"></script>
<!-- Join-Handling wiederverwenden -->
<script type="module" src="/js/join-game.js"></script>
<!-- Optional: alter Join-Button (legacy) fokussiert nur das Feld -->
<script>
const btn = document.getElementById('joinGame');
if (btn) {
btn.addEventListener('click', (ev) => {
ev.preventDefault(); ev.stopImmediatePropagation();
const input = document.getElementById('gameId');
if (input) { input.focus(); input.select(); }
}, true);
}
</script>
</body>
</html>