219 lines
8.7 KiB
HTML
219 lines
8.7 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>ChessNut - Salle d'attente</title>
|
|
<link rel="stylesheet" href="/styles/style.css">
|
|
</head>
|
|
<body>
|
|
<div class="page">
|
|
<header class="hero card">
|
|
<div>
|
|
<div class="title">ChessNut — Salle d'attente</div>
|
|
<div class="subtitle">Préparez-vous, invitez un ami et lancez la partie quand tout le monde est prêt.</div>
|
|
</div>
|
|
<img class="decor" src="/assets/chess-pieces/boards/8x8_green.svg" alt="decor" />
|
|
</header>
|
|
|
|
<section class="card">
|
|
<div>Room: <strong id="roomId">-</strong></div>
|
|
<div>Status: <strong id="status">-</strong></div>
|
|
<div>Joueurs: <strong id="playerCount">0/2</strong></div>
|
|
<div id="youAreHost" style="display:none;color:green;font-weight:bold;">(Vous êtes l'hôte)</div>
|
|
|
|
<div style="margin-top:8px">
|
|
<label id="autoDrawLabel" style="display:none;align-items:center;gap:8px;">
|
|
<input type="checkbox" id="autoDrawToggle" />
|
|
Pioche automatique
|
|
</label>
|
|
</div>
|
|
|
|
<div style="margin-top:8px">
|
|
<button id="startBtn" style="display:none" class="btn-cta">Commencer la partie</button>
|
|
<button id="copyInviteBtn" style="margin-left:8px" class="btn-ghost">Copier le lien d'invitation</button>
|
|
</div>
|
|
</section>
|
|
|
|
<div style="margin-top:10px"><a href="/">Retour à la page principale</a></div>
|
|
</div>
|
|
|
|
<script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
|
|
<script>
|
|
function qs(name){ const url = new URL(window.location.href); return url.searchParams.get(name); }
|
|
const roomId = qs('roomId');
|
|
const playerId = qs('playerId') || undefined;
|
|
document.getElementById('roomId').textContent = roomId || '-';
|
|
|
|
const statusEl = document.getElementById('status');
|
|
const playerCountEl = document.getElementById('playerCount');
|
|
let socket = null;
|
|
let myPlayerId = null;
|
|
let myColor = null;
|
|
let roomHostId = null;
|
|
const hostLabelEl = document.getElementById('hostLabel');
|
|
const youAreHostEl = document.getElementById('youAreHost');
|
|
const autoDrawLabelEl = document.getElementById('autoDrawLabel');
|
|
const autoDrawToggleEl = document.getElementById('autoDrawToggle');
|
|
|
|
function log(...args){ console.log(...args); }
|
|
|
|
if(!roomId){ alert('roomId manquant dans l\'URL'); }
|
|
|
|
function connectAndJoin(){
|
|
socket = io();
|
|
socket.on('connect', ()=>{ log('socket connecté', socket.id); });
|
|
|
|
socket.on('room:update', (data)=>{
|
|
console.log('room:update', data);
|
|
statusEl.textContent = data.status || '-';
|
|
const count = (data.players||[]).length;
|
|
playerCountEl.textContent = `${count}/2`;
|
|
// remember hostId from server updates; if missing, fall back to first player
|
|
if(data.hostId !== undefined && data.hostId !== null) {
|
|
roomHostId = data.hostId;
|
|
} else if ((data.players || []).length > 0) {
|
|
// fallback: first player is host
|
|
roomHostId = data.players[0].id;
|
|
} else {
|
|
roomHostId = null;
|
|
}
|
|
|
|
// update host label UI
|
|
if(hostLabelEl){
|
|
hostLabelEl.textContent = roomHostId || '-';
|
|
if(myPlayerId && roomHostId && myPlayerId === roomHostId){
|
|
youAreHostEl.style.display = 'inline';
|
|
} else {
|
|
youAreHostEl.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
// enable start button only when there are 2 players and current user is host
|
|
const startBtn = document.getElementById('startBtn');
|
|
if(startBtn){
|
|
// host determined by explicit hostId sent by server (or fallback)
|
|
if(myPlayerId && roomHostId && myPlayerId === roomHostId){
|
|
startBtn.style.display = 'inline-block';
|
|
startBtn.disabled = count !== 2;
|
|
} else {
|
|
// hide for non-hosts
|
|
startBtn.style.display = 'none';
|
|
}
|
|
}
|
|
// update auto-draw UI if server provides it
|
|
try{
|
|
if(typeof data.autoDraw !== 'undefined' && autoDrawLabelEl && autoDrawToggleEl){
|
|
// show the control only to the host
|
|
if(myPlayerId && roomHostId && myPlayerId === roomHostId){
|
|
autoDrawLabelEl.style.display = 'inline-flex';
|
|
autoDrawToggleEl.checked = !!data.autoDraw;
|
|
autoDrawToggleEl.disabled = false;
|
|
} else {
|
|
// hide control for non-hosts
|
|
autoDrawLabelEl.style.display = 'none';
|
|
}
|
|
}
|
|
}catch(_){ }
|
|
});
|
|
|
|
// register game started handler early so we don't miss the broadcast
|
|
socket.on('game:started', (data)=>{
|
|
log('game:started', data);
|
|
if(myPlayerId){
|
|
window.location.href = `/game.html?roomId=${encodeURIComponent(roomId)}&playerId=${encodeURIComponent(myPlayerId)}`;
|
|
} else {
|
|
window.location.href = `/game.html?roomId=${encodeURIComponent(roomId)}`;
|
|
}
|
|
});
|
|
|
|
socket.emit('room:join', { roomId, playerId }, (resp)=>{
|
|
if(resp && resp.error){
|
|
console.warn('join error', resp);
|
|
// do not alert or force-redirect; show error in status and keep page for debugging/retry
|
|
try{ document.getElementById('status').textContent = resp.error || 'Impossible de rejoindre la room'; }catch(e){}
|
|
return;
|
|
}
|
|
myPlayerId = resp.playerId;
|
|
myColor = resp.color;
|
|
// server may or may not include hostId in the response; fall back to color
|
|
if(resp.hostId !== undefined && resp.hostId !== null){
|
|
roomHostId = resp.hostId;
|
|
} else if(resp.color === 'white'){
|
|
roomHostId = resp.playerId; // assume creator (first join) is white
|
|
}
|
|
log('Rejoint room', resp);
|
|
// update host UI immediately
|
|
if(hostLabelEl){ hostLabelEl.textContent = roomHostId || '-'; }
|
|
if(youAreHostEl){ youAreHostEl.style.display = (myPlayerId && roomHostId && myPlayerId === roomHostId) ? 'inline' : 'none'; }
|
|
if(myPlayerId && roomHostId && myPlayerId === roomHostId){
|
|
const btn = document.getElementById('startBtn');
|
|
btn.style.display = 'inline-block';
|
|
btn.disabled = true;
|
|
}
|
|
// after join, fetch room state to avoid missing a recent 'playing' state
|
|
fetch(`/rooms/${encodeURIComponent(roomId)}`).then(r => r.json()).then(roomInfo => {
|
|
try{
|
|
if(roomInfo && typeof roomInfo.autoDraw !== 'undefined'){
|
|
if(myPlayerId && roomHostId && myPlayerId === roomHostId){
|
|
// host: show control and set state
|
|
if(autoDrawLabelEl && autoDrawToggleEl){ autoDrawLabelEl.style.display = 'inline-flex'; autoDrawToggleEl.checked = !!roomInfo.autoDraw; autoDrawToggleEl.disabled = false; }
|
|
} else {
|
|
// non-host: hide control
|
|
if(autoDrawLabelEl) autoDrawLabelEl.style.display = 'none';
|
|
}
|
|
}
|
|
}catch(_){ }
|
|
if(roomInfo && roomInfo.status === 'playing'){
|
|
// server already marked room as playing; redirect immediately
|
|
if(myPlayerId){
|
|
window.location.href = `/game.html?roomId=${encodeURIComponent(roomId)}&playerId=${encodeURIComponent(myPlayerId)}`;
|
|
} else {
|
|
window.location.href = `/game.html?roomId=${encodeURIComponent(roomId)}`;
|
|
}
|
|
}
|
|
}).catch(e => { /* ignore */ });
|
|
});
|
|
}
|
|
|
|
connectAndJoin();
|
|
|
|
// Start button handler (host)
|
|
document.getElementById('startBtn').addEventListener('click', ()=>{
|
|
if(!socket) return;
|
|
socket.emit('game:start', { roomId }, (resp)=>{
|
|
if(resp && resp.error){ log('start error', resp); alert(resp.error); return; }
|
|
log('game:start acknowledged');
|
|
});
|
|
});
|
|
|
|
// Auto-draw toggle (host only)
|
|
if(autoDrawToggleEl){
|
|
autoDrawToggleEl.addEventListener('change', (ev)=>{
|
|
if(!socket) return;
|
|
const enabled = !!autoDrawToggleEl.checked;
|
|
socket.emit('room:auto_draw:set', { roomId, enabled }, (resp)=>{
|
|
if(resp && resp.error){ log('auto-draw error', resp); alert(resp.error); return; }
|
|
log('auto-draw updated', resp);
|
|
});
|
|
});
|
|
}
|
|
|
|
// Copy invite link (hidden link, no display)
|
|
document.getElementById('copyInviteBtn').addEventListener('click', async ()=>{
|
|
const link = `${window.location.origin}/waiting.html?roomId=${encodeURIComponent(roomId)}`;
|
|
try{
|
|
await navigator.clipboard.writeText(link);
|
|
alert('Lien d\'invitation copié dans le presse-papier');
|
|
}catch(e){
|
|
// fallback
|
|
window.prompt('Copie le lien ci-dessous', link);
|
|
}
|
|
});
|
|
|
|
// fallback: if socket already existed and server emits game:started earlier, ensure handler exists
|
|
// (handled after join)
|
|
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|