PromptWar / static /js /queue.js
Mr-TD's picture
feat: Add operator dashboard, alerts, analytics, and simulator pages
aefe381
/**
* VenueFlow — Queue Management UI
*/
// Filter queue stations by category
document.addEventListener('DOMContentLoaded', () => {
const filterBtns = document.querySelectorAll('.queue-filter');
filterBtns.forEach(btn => {
btn.addEventListener('click', () => {
const category = btn.dataset.category;
// Update active state
filterBtns.forEach(b => {
b.classList.remove('active');
b.classList.replace('btn-primary', 'btn-secondary');
b.setAttribute('aria-selected', 'false');
});
btn.classList.add('active');
btn.classList.replace('btn-secondary', 'btn-primary');
btn.setAttribute('aria-selected', 'true');
// Filter cards
const cards = document.querySelectorAll('#queue-stations-list .queue-card');
cards.forEach(card => {
if (category === 'all' || card.dataset.category === category) {
card.style.display = 'flex';
} else {
card.style.display = 'none';
}
});
});
});
// Auto-refresh queue data
setInterval(refreshQueues, 5000);
});
async function refreshQueues() {
try {
const data = await apiCall('/api/queue/summary');
if (!data || !data.stations) return;
data.stations.forEach(station => {
const card = document.querySelector(`[data-station-id="${station.id}"]`);
if (!card) return;
const waitEl = card.querySelector('.queue-wait');
if (waitEl) {
waitEl.textContent = Math.round(station.estimated_wait_minutes) + ' min';
waitEl.style.color = station.wait_color;
}
const metaEl = card.querySelector('.queue-meta');
if (metaEl) {
metaEl.textContent = `${station.category_label}${station.current_length} in line`;
}
const progressBar = card.querySelector('.progress-bar');
if (progressBar) {
const w = Math.min(station.estimated_wait_minutes * 3.3, 100);
progressBar.style.width = w + '%';
progressBar.className = `progress-bar ${station.wait_level}`;
}
});
} catch (e) {
// Silent fail for background refresh
}
}
async function joinQueue(stationId) {
try {
const ticket = await apiCall('/api/queue/join', {
method: 'POST',
body: JSON.stringify({ station_id: stationId }),
});
if (ticket && ticket.id) {
showToast(
'Queue Joined! 🎫',
`Ticket #${ticket.id} — Position ${ticket.position} at ${ticket.station_name}`,
'success',
8000
);
// Refresh the page to show updated tickets
setTimeout(() => location.reload(), 1500);
}
} catch (err) {
showToast('Could not join queue', err.message || 'Please try again', 'error');
}
}
async function cancelTicket(ticketId) {
if (!confirm('Cancel this virtual queue ticket?')) return;
try {
await apiCall('/api/queue/cancel', {
method: 'POST',
body: JSON.stringify({ ticket_id: ticketId }),
});
showToast('Ticket Cancelled', 'Your virtual queue spot has been released.', 'info');
setTimeout(() => location.reload(), 1000);
} catch (err) {
showToast('Could not cancel', err.message || 'Please try again', 'error');
}
}
console.log('⏱️ Queue UI loaded');