timer / public /admin.html
krishgokul92's picture
Upload 7 files
f40632a verified
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Timer Admin</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
:root { color-scheme: dark; }
body { margin:0; font-family: Inter, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; background:#0b0f14; color:#e6edf3; }
.wrap { max-width: 960px; margin: 40px auto; padding: 0 20px; }
.card { background: #121820; border: 1px solid #1f2933; border-radius: 16px; padding: 20px; box-shadow: 0 6px 24px rgba(0,0,0,.35); }
h1 { margin: 0 0 6px; font-weight: 700; letter-spacing: .2px; }
p.sub { margin: 0 16px 20px 0; color: #8ea0b5; }
.row { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; margin-bottom: 16px; }
.btn { border: 0; border-radius: 12px; padding: 12px 18px; font-weight: 600; cursor: pointer; background:#1e2936; color:#fff; transition: transform .02s ease, background .2s ease }
.btn:active { transform: translateY(1px); }
.btn.start { background: #2261ff; }
.btn.stop { background: #f43f5e; }
.btn.reset { background: #0ea5e9; }
.btn.blackon { background:#000; border:1px solid #2c3a4a; }
.btn.blackoff { background:#16a34a; }
.input { background: #0d141c; color:#e6edf3; border:1px solid #1f2933; border-radius:12px; padding: 10px 12px; min-width: 160px; }
.badge { background:#10161f; border:1px solid #223041; padding: 6px 10px; border-radius: 999px; color:#9fb4cc; display:inline-flex; gap:8px; align-items: center; }
.grid { display:grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; }
.stat { background:#0d141c; border: 1px solid #1f2933; border-radius:12px; padding: 14px; }
.stat b { font-size: 24px; }
code { background: #0d141c; border:1px solid #1f2933; padding:2px 6px; border-radius:6px; }
</style>
</head>
<body>
<div class="wrap">
<div class="card">
<h1>Timer Admin</h1>
<p class="sub">Controls all clients in the same room over WebSockets. Use a small start delay for tight sync.</p>
<div class="row">
<label>Start delay (ms)
<input id="delay" class="input" type="number" value="3000" min="200" step="100">
</label>
<label>Label
<input id="label" class="input" type="text" placeholder="e.g. Heat 1">
</label>
<button id="start" class="btn start">Start</button>
<button id="stop" class="btn stop">Stop</button>
<button id="reset" class="btn reset">Reset</button>
<span class="badge" id="stats">Clients: 0 • Admins: 1</span>
</div>
<div class="row">
<button id="blackOn" class="btn blackon">Blackout ON</button>
<button id="blackOff" class="btn blackoff">Show Timer</button>
</div>
<div class="grid">
<div class="stat">
<div>Room</div>
<b id="roomName">default</b>
</div>
<div class="stat">
<div>Server time (ms)</div>
<b id="serverNow">--</b>
</div>
<div class="stat">
<div>Hint</div>
<div>Open <code>/client</code> on each device. Use <code>?room=yourcode</code> to isolate groups.</div>
</div>
</div>
</div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script>
const params = new URLSearchParams(location.search);
const room = params.get('room') || 'default';
const socket = io({ query: { role: 'admin', room } });
const delayEl = document.getElementById('delay');
const labelEl = document.getElementById('label');
const statsEl = document.getElementById('stats');
const roomEl = document.getElementById('roomName');
const serverNowEl = document.getElementById('serverNow');
roomEl.textContent = room;
function syncOnce() { socket.emit('sync:ping', { t0: Date.now() }); }
socket.on('sync:pong', ({ t0, t1, t2 }) => {
const t3 = Date.now();
const offset = ((t1 - t0) + (t2 - t3)) / 2;
serverNowEl.textContent = String((Date.now() + offset)|0);
});
setInterval(syncOnce, 1000);
syncOnce();
socket.on('stats', ({ numAdmins, numClients }) => {
statsEl.textContent = `Clients: ${numClients} • Admins: ${numAdmins}`;
});
document.getElementById('start').onclick = () => {
socket.emit('admin:start', {
delayMs: Number(delayEl.value || 3000),
label: labelEl.value || ''
});
};
document.getElementById('stop').onclick = () => socket.emit('admin:stop');
document.getElementById('reset').onclick = () => socket.emit('admin:reset');
document.getElementById('blackOn').onclick = () => socket.emit('admin:blackout', { on: true });
document.getElementById('blackOff').onclick = () => socket.emit('admin:blackout', { on: false });
</script>
</body>
</html>