// DOM Elements const queueTab = document.getElementById('queueTab'); const usersTab = document.getElementById('usersTab'); const cacheTab = document.getElementById('cacheTab'); const logoutButton = document.getElementById('logoutButton'); const queueSection = document.getElementById('queueSection'); const usersSection = document.getElementById('usersSection'); const cacheSection = document.getElementById('cacheSection'); const nowPlaying = document.getElementById('nowPlaying'); const queueList = document.getElementById('queueList'); const clearQueueButton = document.getElementById('clearQueueButton'); const usersTable = document.getElementById('usersTable'); const addUserButton = document.getElementById('addUserButton'); const addUserModal = document.getElementById('addUserModal'); const addUserForm = document.getElementById('addUserForm'); const cancelAddUser = document.getElementById('cancelAddUser'); const cacheSongCount = document.getElementById('cacheSongCount'); const cacheSize = document.getElementById('cacheSize'); const cacheMaxSize = document.getElementById('cacheMaxSize'); const cacheUsage = document.getElementById('cacheUsage'); const clearCacheButton = document.getElementById('clearCacheButton'); // Tab switching function switchTab(tab, section) { // Remove active class from all tabs and sections [queueTab, usersTab, cacheTab].forEach(t => t.classList.remove('active')); [queueSection, usersSection, cacheSection].forEach(s => s.classList.remove('active')); // Add active class to selected tab and section tab.classList.add('active'); section.classList.add('active'); } queueTab.addEventListener('click', () => switchTab(queueTab, queueSection)); usersTab.addEventListener('click', () => switchTab(usersTab, usersSection)); cacheTab.addEventListener('click', () => switchTab(cacheTab, cacheSection)); // Logout logoutButton.addEventListener('click', async () => { try { await fetch('/api/logout', { method: 'POST', credentials: 'include', // Important for cookies to work }); window.location.href = '/login'; } catch (error) { console.error('Logout failed:', error); } }); // Queue management function formatDuration(seconds) { const minutes = Math.floor(seconds / 60); const secs = seconds % 60; return `${minutes}:${secs.toString().padStart(2, '0')}`; } async function loadQueue() { try { const response = await fetch('/api/queue', { credentials: 'include', // Important for cookies to work }); const responseData = await response.json(); // Update now playing if (responseData.current_song) { nowPlaying.innerHTML = `

${responseData.current_song.title}

${formatDuration(responseData.current_song.duration)}

${responseData.state}
`; } else { nowPlaying.innerHTML = '

Nothing playing

'; } // Update queue if (responseData.queue && responseData.queue.length > 0) { queueList.innerHTML = responseData.queue.map((songItem, idx) => { if (songItem.is_current) { return `
  • ${songItem.title} ${formatDuration(songItem.duration)}
    Now Playing
  • `; } else { return `
  • ${idx + 1}. ${songItem.title} ${formatDuration(songItem.duration)}
  • `; } }).join(''); } else { queueList.innerHTML = '
  • Queue is empty
  • '; } } catch (error) { console.error('Failed to load queue:', error); queueList.innerHTML = '
  • Failed to load queue
  • '; } } clearQueueButton.addEventListener('click', async () => { if (!confirm('Are you sure you want to clear the queue?')) return; try { await fetch('/api/queue', { method: 'DELETE', credentials: 'include', // Important for cookies to work }); loadQueue(); } catch (error) { console.error('Failed to clear queue:', error); alert('Failed to clear queue'); } }); // User management async function loadUsers() { try { const response = await fetch('/api/users', { credentials: 'include', // Important for cookies to work }); const responseData = await response.json(); if (responseData.users && responseData.users.length > 0) { const tbody = usersTable.querySelector('tbody'); tbody.innerHTML = responseData.users.map(userItem => ` ${userItem.username} `).join(''); // Add event listeners to save buttons document.querySelectorAll('.save-permission').forEach(button => { button.addEventListener('click', async () => { const username = button.dataset.username; const select = document.querySelector(`.permission-select[data-username="${username}"]`); const permissionLevel = parseInt(select.value); try { await fetch(`/api/users/${username}/permissions`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ permission_level: permissionLevel }), credentials: 'include', // Important for cookies to work }); alert(`Permission updated for ${username}`); } catch (error) { console.error('Failed to update permission:', error); alert('Failed to update permission'); } }); }); } else { usersTable.querySelector('tbody').innerHTML = 'No users found'; } } catch (error) { console.error('Failed to load users:', error); usersTable.querySelector('tbody').innerHTML = 'Failed to load users'; } } // Add user modal addUserButton.addEventListener('click', () => { addUserModal.classList.add('active'); }); cancelAddUser.addEventListener('click', () => { addUserModal.classList.remove('active'); addUserForm.reset(); }); addUserForm.addEventListener('submit', async (e) => { e.preventDefault(); const username = document.getElementById('newUsername').value; const permissionLevel = parseInt(document.getElementById('newPermissionLevel').value); try { await fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username, permission_level: permissionLevel }), credentials: 'include', // Important for cookies to work }); addUserModal.classList.remove('active'); addUserForm.reset(); loadUsers(); } catch (error) { console.error('Failed to add user:', error); alert('Failed to add user'); } }); // Cache management async function loadCacheStats() { try { const response = await fetch('/api/cache', { credentials: 'include', // Important for cookies to work headers: { 'Accept': 'application/json' } }); const stats = await response.json(); cacheSongCount.textContent = stats.songCount; cacheSize.textContent = `${stats.totalSizeMb} MB`; cacheMaxSize.textContent = `${stats.maxSizeMb} MB`; const usagePercent = stats.maxSizeMb > 0 ? (stats.totalSizeMb / stats.maxSizeMb) * 100 : 0; cacheUsage.style.width = `${Math.min(usagePercent, 100)}%`; // Change color based on usage if (usagePercent > 90) { cacheUsage.style.backgroundColor = 'var(--danger-color)'; } else if (usagePercent > 70) { cacheUsage.style.backgroundColor = 'var(--accent-color)'; } else { cacheUsage.style.backgroundColor = 'var(--primary-color)'; } } catch (error) { console.error('Failed to load cache stats:', error); } } clearCacheButton.addEventListener('click', async () => { if (!confirm('Are you sure you want to clear the cache? This will delete all downloaded audio files.')) return; try { await fetch('/api/cache', { method: 'DELETE', credentials: 'include', // Important for cookies to work }); loadCacheStats(); } catch (error) { console.error('Failed to clear cache:', error); alert('Failed to clear cache'); } }); // Initial load document.addEventListener('DOMContentLoaded', () => { loadQueue(); loadUsers(); loadCacheStats(); // Refresh data periodically setInterval(loadQueue, 10000); // Every 10 seconds setInterval(loadCacheStats, 30000); // Every 30 seconds });