stopwatch / public /admin.js
krishgokul92's picture
Update public/admin.js
06d2070 verified
import { createSmoothRenderer } from "./shared.js";
const socket = io();
const display = document.getElementById("display");
const clientCountEl = document.getElementById("clientCount");
const tableBody = document.getElementById("clientsTable");
const colorPicker = document.getElementById("colorPicker");
const blackoutBtn = document.getElementById("blackout");
const wakeBtn = document.getElementById("wake");
const renderer = createSmoothRenderer({
setText: (t) => (display.textContent = t),
});
socket.on("connect", () => {
// Identify as admin to receive client list updates
socket.emit("admin:join");
});
// Stopwatch state (also brings color & blackout)
socket.on("state", (s) => {
renderer.applyServerState(s);
// Color reflection
if (s.color) {
display.style.color = s.color;
if (colorPicker && colorPicker.value.toLowerCase() !== s.color.toLowerCase()) {
colorPicker.value = s.color;
}
}
// Blackout button label reflect state
if (typeof s.blackout === "boolean" && blackoutBtn) {
blackoutBtn.textContent = s.blackout ? "Show Clock" : "Blackout";
blackoutBtn.style.background = s.blackout ? "#550000" : "#111";
}
});
// Render clients table
socket.on("clients:list", ({ count, clients }) => {
clientCountEl.textContent = count;
if (!clients || clients.length === 0) {
tableBody.innerHTML = `<tr><td colspan="6" class="muted">No clients connected yet.</td></tr>`;
return;
}
const rows = clients.map((c) => {
const since = new Date(c.connectedAt).toLocaleTimeString();
const lat = (c.latencyMs == null) ? "—" : `${c.latencyMs} ms`;
const shortId = c.id.slice(0, 6);
const ua = (c.ua || "").slice(0, 80);
const url = (c.url || "").slice(0, 64);
return `
<tr>
<td class="mono" title="${c.id}">${shortId}</td>
<td class="mono">${c.ip}</td>
<td>${lat}</td>
<td title="${c.url}">${url}</td>
<td title="${c.ua}">${ua}</td>
<td class="mono">${since}</td>
</tr>
`;
});
tableBody.innerHTML = rows.join("");
});
// Admin buttons
document.getElementById("start").onclick = () => socket.emit("cmd:start");
document.getElementById("stop").onclick = () => socket.emit("cmd:stop");
document.getElementById("reset").onclick = () => socket.emit("cmd:reset");
// Color (debounced a bit)
let colorDebounce;
colorPicker?.addEventListener("input", (e) => {
const hex = String(e.target.value || "").trim();
clearTimeout(colorDebounce);
colorDebounce = setTimeout(() => {
socket.emit("cmd:color", hex);
}, 50);
});
// Blackout toggle
let blackoutEnabled = false;
blackoutBtn?.addEventListener("click", () => {
blackoutEnabled = !blackoutEnabled;
socket.emit("cmd:blackout", blackoutEnabled);
blackoutBtn.textContent = blackoutEnabled ? "Show Clock" : "Blackout";
blackoutBtn.style.background = blackoutEnabled ? "#550000" : "#111";
});
// 🚀 Wake button
wakeBtn?.addEventListener("click", () => {
socket.emit("cmd:wake");
// Visual feedback pulse
wakeBtn.style.background = "#008800";
setTimeout(() => (wakeBtn.style.background = "#004400"), 300);
});