// API Base URL const API_BASE = window.location.origin; // Load dashboard stats on page load document.addEventListener('DOMContentLoaded', () => { loadDashboard(); updateSubsonicUrl(); }); // Switch between tabs function switchTab(tabName) { // Hide all tabs document.querySelectorAll('.tab-content').forEach(tab => { tab.classList.remove('active'); }); document.querySelectorAll('.tab').forEach(tab => { tab.classList.remove('active'); }); // Show selected tab document.getElementById(tabName).classList.add('active'); event.target.classList.add('active'); // Load data for the tab if (tabName === 'tracks') loadTracks(); if (tabName === 'albums') loadAlbums(); if (tabName === 'playlists') loadPlaylists(); } // Load dashboard statistics async function loadDashboard() { try { const [tracksRes, albumsRes, playlistsRes] = await Promise.all([ fetch(`${API_BASE}/api/tracks`), fetch(`${API_BASE}/api/albums`), fetch(`${API_BASE}/api/playlists`) ]); const tracks = await tracksRes.json(); const albums = await albumsRes.json(); const playlists = await playlistsRes.json(); const singles = tracks.tracks.filter(t => t.isSingle).length; document.getElementById('totalTracks').textContent = tracks.tracks.length; document.getElementById('totalAlbums').textContent = albums.albums.length; document.getElementById('totalSingles').textContent = singles; document.getElementById('totalPlaylists').textContent = playlists.playlists.length; } catch (error) { console.error('Error loading dashboard:', error); } } // Load all tracks async function loadTracks() { const trackList = document.getElementById('trackList'); trackList.innerHTML = '
  • Loading tracks...
  • '; try { const res = await fetch(`${API_BASE}/api/tracks`); const data = await res.json(); if (data.tracks.length === 0) { trackList.innerHTML = '
  • No tracks found. Scan your library first.
  • '; return; } trackList.innerHTML = data.tracks.map(track => `
  • ${track.title} ${track.isSingle ? 'Single' : 'Album'}
    ${track.artist} • ${track.album}
  • `).join(''); } catch (error) { trackList.innerHTML = '
  • Error loading tracks
  • '; console.error('Error loading tracks:', error); } } // Search tracks function searchTracks() { const searchTerm = document.getElementById('searchTracks').value.toLowerCase(); const items = document.querySelectorAll('.track-item'); items.forEach(item => { const text = item.textContent.toLowerCase(); item.style.display = text.includes(searchTerm) ? 'flex' : 'none'; }); } // Toggle single/album status async function toggleSingle(trackId, isSingle) { try { const res = await fetch(`${API_BASE}/api/tracks/${trackId}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ isSingle }) }); if (res.ok) { loadTracks(); loadDashboard(); } } catch (error) { console.error('Error updating track:', error); alert('Failed to update track'); } } // Load albums async function loadAlbums() { const albumList = document.getElementById('albumList'); albumList.innerHTML = '
  • Loading albums...
  • '; try { const res = await fetch(`${API_BASE}/api/albums`); const data = await res.json(); if (data.albums.length === 0) { albumList.innerHTML = '
  • No albums found
  • '; return; } albumList.innerHTML = data.albums.map(album => `
  • ${album.name}
    ${album.artist} • ${album.trackCount} tracks
  • `).join(''); } catch (error) { albumList.innerHTML = '
  • Error loading albums
  • '; console.error('Error loading albums:', error); } } // Load playlists async function loadPlaylists() { const playlistList = document.getElementById('playlistList'); playlistList.innerHTML = '
  • Loading playlists...
  • '; try { const res = await fetch(`${API_BASE}/api/playlists`); const data = await res.json(); if (data.playlists.length === 0) { playlistList.innerHTML = '
  • No playlists yet. Create one!
  • '; return; } playlistList.innerHTML = data.playlists.map(playlist => `
  • ${playlist.name}
    ${playlist.trackCount} tracks
  • `).join(''); } catch (error) { playlistList.innerHTML = '
  • Error loading playlists
  • '; console.error('Error loading playlists:', error); } } // Show create playlist modal function showCreatePlaylist() { document.getElementById('createPlaylistModal').classList.add('active'); } // Close modal function closeModal() { document.getElementById('createPlaylistModal').classList.remove('active'); document.getElementById('playlistName').value = ''; document.getElementById('playlistDescription').value = ''; } // Create playlist async function createPlaylist() { const name = document.getElementById('playlistName').value; const description = document.getElementById('playlistDescription').value; if (!name) { alert('Please enter a playlist name'); return; } try { const res = await fetch(`${API_BASE}/api/playlists`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, description }) }); if (res.ok) { closeModal(); loadPlaylists(); loadDashboard(); } } catch (error) { console.error('Error creating playlist:', error); alert('Failed to create playlist'); } } // Delete playlist async function deletePlaylist(playlistId) { if (!confirm('Are you sure you want to delete this playlist?')) { return; } try { const res = await fetch(`${API_BASE}/api/playlists/${playlistId}`, { method: 'DELETE' }); if (res.ok) { loadPlaylists(); loadDashboard(); } } catch (error) { console.error('Error deleting playlist:', error); alert('Failed to delete playlist'); } } // Scan library async function scanLibrary() { const scanStatus = document.getElementById('scanStatus'); scanStatus.style.display = 'block'; try { // Note: This would need a scan endpoint on the server alert('Library scanning is currently done via CLI: npm run scan\n\nWe can add a web-based scan button if needed!'); scanStatus.style.display = 'none'; } catch (error) { console.error('Error scanning library:', error); alert('Failed to scan library'); scanStatus.style.display = 'none'; } } // Upload audio file async function uploadAudio() { const fileInput = document.getElementById('uploadFile'); const file = fileInput.files[0]; if (!file) return; const isSingle = confirm('Is this a single track? (Click Cancel if it\'s part of an album)'); const formData = new FormData(); formData.append('audio', file); formData.append('isSingle', isSingle); try { const res = await fetch(`${API_BASE}/api/upload`, { method: 'POST', body: formData }); if (res.ok) { alert('File uploaded successfully!'); loadDashboard(); if (document.getElementById('tracks').classList.contains('active')) { loadTracks(); } } else { alert('Failed to upload file'); } } catch (error) { console.error('Error uploading file:', error); alert('Failed to upload file'); } fileInput.value = ''; } // Update Subsonic URL function updateSubsonicUrl() { const url = `${window.location.protocol}//${window.location.hostname}:${window.location.port}/rest`; document.getElementById('subsonicUrl').value = url; }