const socket = io(); // DOM Elements const counterDisplay = document.getElementById('counter-display'); const incrementBtn = document.getElementById('increment-btn'); const usernameInput = document.getElementById('username'); const quoteInput = document.getElementById('quote'); const errorMessage = document.getElementById('error-message'); const timerDisplay = document.getElementById('timer-display'); // Cookie Helpers function setCookie(name, value, days) { const expires = new Date(Date.now() + days * 864e5).toUTCString(); document.cookie = name + '=' + encodeURIComponent(value) + '; expires=' + expires + '; path=/'; } function getCookie(name) { return document.cookie.split('; ').reduce((r, v) => { const parts = v.split('='); return parts[0] === name ? decodeURIComponent(parts[1]) : r; }, ''); } // Load name from cookie const savedName = getCookie('username'); if (savedName) { usernameInput.value = savedName; } // Socket Events socket.on('update', (data) => { counterDisplay.innerText = data.count; // Animate counterDisplay.parentElement.classList.remove('pop-anim'); void counterDisplay.parentElement.offsetWidth; // trigger reflow counterDisplay.parentElement.classList.add('pop-anim'); }); socket.on('error', (msg) => { showError(msg); }); // Logic usernameInput.addEventListener('input', (e) => { setCookie('username', e.target.value, 365); }); incrementBtn.addEventListener('click', () => { const name = usernameInput.value.trim(); if (!name) { showError("Please enter your name!"); usernameInput.focus(); return; } const quote = quoteInput.value.trim(); // Optimistic disable startCooldown(); socket.emit('increment', { name, quote }); }); function showError(msg) { errorMessage.innerText = msg; errorMessage.classList.remove('hidden'); setTimeout(() => { errorMessage.classList.add('hidden'); }, 3000); } let cooldownInterval; function startCooldown() { incrementBtn.disabled = true; let secondsLeft = 30; timerDisplay.classList.remove('hidden'); timerDisplay.innerText = `Wait ${secondsLeft}s`; clearInterval(cooldownInterval); cooldownInterval = setInterval(() => { secondsLeft--; timerDisplay.innerText = `Wait ${secondsLeft}s`; if (secondsLeft <= 0) { clearInterval(cooldownInterval); incrementBtn.disabled = false; timerDisplay.classList.add('hidden'); } }, 1000); }