c60d1219b2
Features: - 6-stelliger Passcode pro Session (z.B. 5E92C5) - /join Seite: Passcode-Eingabe für andere Geräte - /api/session/join: Verifiziert Passcode, setzt Cookie - /api/session/info: Gibt Session-ID + Passcode zurück - Index-Seite zeigt Passcode mit Hinweis - Chat-Header zeigt Passcode (lila hervorgehoben) - Passcode in sessions Tabelle gespeichert - Falscher Code = Fehlermeldung, kein Raten möglich Workflow: 1. Desktop: Öffne NeonChat → siehst Passcode im Header 2. Handy: Öffne http://[IP]:5252/join → Code eingeben 3. Handy bekommt gleiches Cookie → gleicher Chat-Verlauf
73 lines
3.8 KiB
HTML
73 lines
3.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>NeonChat — Session beitreten</title>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: 'Segoe UI', system-ui, sans-serif; background: #0a0a0f; color: #e0e0e8; min-height: 100vh; display: flex; align-items: center; justify-content: center; }
|
|
.join-box { background: #15151f; border: 1px solid #252535; border-radius: 20px; padding: 40px; max-width: 400px; width: 90%; text-align: center; }
|
|
h1 { font-size: 1.8rem; margin-bottom: 8px; background: linear-gradient(135deg, #ff006e, #8338ec); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
|
|
.subtitle { color: #6b6b80; margin-bottom: 30px; font-size: 0.9rem; }
|
|
.passcode-input { width: 100%; background: #1e1e2e; border: 2px solid #252535; border-radius: 12px; padding: 16px; color: #e0e0e8; font-size: 1.5rem; text-align: center; letter-spacing: 8px; text-transform: uppercase; outline: none; transition: border 0.2s; font-family: monospace; }
|
|
.passcode-input:focus { border-color: #8338ec; }
|
|
.passcode-input::placeholder { color: #4b4b60; letter-spacing: 4px; }
|
|
.btn { margin-top: 20px; width: 100%; padding: 14px; border-radius: 12px; border: none; background: linear-gradient(135deg, #8338ec, #ff006e); color: white; font-size: 1rem; cursor: pointer; font-weight: 600; transition: opacity 0.15s; }
|
|
.btn:hover { opacity: 0.9; }
|
|
.error { color: #ff006e; margin-top: 12px; font-size: 0.85rem; display: none; }
|
|
.info { margin-top: 20px; padding: 12px; background: #1e1e2e; border-radius: 10px; font-size: 0.8rem; color: #6b6b80; line-height: 1.5; }
|
|
.info b { color: #9b9bb0; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="join-box">
|
|
<h1>✦ NeonChat</h1>
|
|
<p class="subtitle">Gib den 6-stelligen Code ein um einer Session beizutreten</p>
|
|
<input type="text" class="passcode-input" id="passcode" maxlength="6" placeholder="A3F2B1" autofocus>
|
|
<button class="btn" onclick="joinSession()">Session beitreten</button>
|
|
<div class="error" id="error"></div>
|
|
<div class="info">
|
|
<b>Wie bekomme ich den Code?</b><br>
|
|
Öffne NeonChat auf deinem Desktop. Der Code steht oben rechts im Header neben der Session-ID.
|
|
</div>
|
|
</div>
|
|
<script>
|
|
document.getElementById('passcode').addEventListener('keydown', (e) => {
|
|
if (e.key === 'Enter') joinSession();
|
|
// Auto-uppercase
|
|
e.target.value = e.target.value.toUpperCase();
|
|
});
|
|
|
|
async function joinSession() {
|
|
const passcode = document.getElementById('passcode').value.trim().toUpperCase();
|
|
const errorDiv = document.getElementById('error');
|
|
errorDiv.style.display = 'none';
|
|
|
|
if (passcode.length !== 6) {
|
|
errorDiv.textContent = 'Code muss 6 Zeichen lang sein';
|
|
errorDiv.style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const resp = await fetch('/api/session/join', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({passcode: passcode})
|
|
});
|
|
const data = await resp.json();
|
|
if (resp.ok) {
|
|
window.location.href = '/';
|
|
} else {
|
|
errorDiv.textContent = data.error || 'Ungültiger Code';
|
|
errorDiv.style.display = 'block';
|
|
}
|
|
} catch(e) {
|
|
errorDiv.textContent = 'Verbindungsfehler';
|
|
errorDiv.style.display = 'block';
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |