// ARTISTS PAGE FUNCTIONALITY - ELEGANT SEARCH & DISCOVERY // ============================================================================ /** * Initialize the artists page when navigated to (only runs once) */ function initializeArtistsPage() { console.log('๐ต Initializing Artists Page (first time)'); // Get DOM elements const searchInput = document.getElementById('artists-search-input'); const headerSearchInput = document.getElementById('artists-header-search-input'); const searchStatus = document.getElementById('artists-search-status'); const backButton = document.getElementById('artists-back-button'); const detailBackButton = document.getElementById('artist-detail-back-button'); // Set up event listeners (only need to do this once) if (searchInput) { searchInput.addEventListener('input', handleArtistsSearchInput); searchInput.addEventListener('keypress', handleArtistsSearchKeypress); } if (headerSearchInput) { headerSearchInput.addEventListener('input', handleArtistsHeaderSearchInput); headerSearchInput.addEventListener('keypress', handleArtistsSearchKeypress); } if (backButton) { backButton.addEventListener('click', () => showArtistsSearchState()); } if (detailBackButton) { detailBackButton.addEventListener('click', () => { // If there are no search results (user navigated directly to artist), // go straight to the main search view instead of showing an empty results page if (!artistsPageState.searchResults || artistsPageState.searchResults.length === 0) { showArtistsSearchState(); } else { showArtistsResultsState(); } }); } // Initialize tabs (only need to do this once) initializeArtistTabs(); // Mark as initialized artistsPageState.isInitialized = true; // Restore previous state instead of always resetting to search restoreArtistsPageState(); console.log('โ Artists Page initialized successfully (ready for navigation)'); } /** * Restore the artists page to its previous state */ function restoreArtistsPageState() { console.log(`๐ Restoring artists page state: ${artistsPageState.currentView}`); switch (artistsPageState.currentView) { case 'results': // Restore search results state if (artistsPageState.searchQuery && artistsPageState.searchResults.length > 0) { console.log(`๐ฆ Restoring search results for: "${artistsPageState.searchQuery}"`); // Restore search input values const searchInput = document.getElementById('artists-search-input'); const headerSearchInput = document.getElementById('artists-header-search-input'); if (searchInput) searchInput.value = artistsPageState.searchQuery; if (headerSearchInput) headerSearchInput.value = artistsPageState.searchQuery; // Display the cached results displayArtistsResults(artistsPageState.searchQuery, artistsPageState.searchResults); } else { // No valid results state, fall back to search showArtistsSearchState(); } break; case 'detail': // Restore artist detail state if (artistsPageState.selectedArtist && artistsPageState.artistDiscography) { console.log(`๐ค Restoring artist detail for: ${artistsPageState.selectedArtist.name}`); // First restore search results if they exist if (artistsPageState.searchQuery && artistsPageState.searchResults.length > 0) { const searchInput = document.getElementById('artists-search-input'); const headerSearchInput = document.getElementById('artists-header-search-input'); if (searchInput) searchInput.value = artistsPageState.searchQuery; if (headerSearchInput) headerSearchInput.value = artistsPageState.searchQuery; } // Show artist detail state showArtistDetailState(); // Update artist info in header updateArtistDetailHeader(artistsPageState.selectedArtist); // Display cached discography if (artistsPageState.artistDiscography.albums || artistsPageState.artistDiscography.singles) { displayArtistDiscography(artistsPageState.artistDiscography); // Restore cached completion data instead of re-scanning restoreCachedCompletionData(artistsPageState.selectedArtist.id); } } else { // No valid detail state, fall back to search or results if (artistsPageState.searchQuery && artistsPageState.searchResults.length > 0) { displayArtistsResults(artistsPageState.searchQuery, artistsPageState.searchResults); } else { showArtistsSearchState(); } } break; default: case 'search': // Show search state (but preserve any existing search query) if (artistsPageState.searchQuery) { const searchInput = document.getElementById('artists-search-input'); if (searchInput) searchInput.value = artistsPageState.searchQuery; } showArtistsSearchState(); break; } } /** * Handle search input with debouncing */ function handleArtistsSearchInput(event) { const query = event.target.value.trim(); updateArtistsSearchStatus('searching'); // Clear existing timeout if (artistsSearchTimeout) { clearTimeout(artistsSearchTimeout); } // Cancel any active search if (artistsSearchController) { artistsSearchController.abort(); } if (query === '') { updateArtistsSearchStatus('default'); return; } // Set up new debounced search artistsSearchTimeout = setTimeout(() => { performArtistsSearch(query); }, 1000); // 1 second debounce } /** * Handle header search input (already in results state) */ function handleArtistsHeaderSearchInput(event) { const query = event.target.value.trim(); // Update main search input to match const mainInput = document.getElementById('artists-search-input'); if (mainInput) { mainInput.value = query; } // Trigger search with same debouncing logic handleArtistsSearchInput(event); } /** * Handle Enter key press in search inputs */ function handleArtistsSearchKeypress(event) { if (event.key === 'Enter') { event.preventDefault(); const query = event.target.value.trim(); if (query && query !== artistsPageState.searchQuery) { // Clear timeout and search immediately if (artistsSearchTimeout) { clearTimeout(artistsSearchTimeout); } performArtistsSearch(query); } } } /** * Perform artist search with API call */ async function performArtistsSearch(query) { console.log(`๐ Searching for artists: "${query}"`); // Check cache first if (artistsPageState.cache.searches[query]) { console.log('๐ฆ Using cached search results'); displayArtistsResults(query, artistsPageState.cache.searches[query]); return; } // Update status updateArtistsSearchStatus('searching'); // Show loading cards immediately if we're in results view if (artistsPageState.currentView === 'results') { showSearchLoadingCards(); } try { // Set up abort controller artistsSearchController = new AbortController(); const response = await fetch('/api/match/search', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: query, context: 'artist' }), signal: artistsSearchController.signal }); if (!response.ok) { throw new Error(`Search failed: ${response.status}`); } const data = await response.json(); console.log(`โ Found ${data.results?.length || 0} artists`); // Transform the results to flatten the nested artist data const transformedResults = (data.results || []).map(result => { // Extract artist data from the nested structure const artist = result.artist || result; return { id: artist.id, name: artist.name, image_url: artist.image_url, genres: artist.genres, popularity: artist.popularity, confidence: result.confidence || 0 }; }); console.log('๐ง Transformed results:', transformedResults); // Cache the transformed results artistsPageState.cache.searches[query] = transformedResults; // Display results displayArtistsResults(query, transformedResults); } catch (error) { if (error.name !== 'AbortError') { console.error('โ Artist search failed:', error); // Provide specific error messages based on the error type let errorMessage = 'Search failed. Please try again.'; if (error.message.includes('401') || error.message.includes('authentication')) { errorMessage = 'Spotify not authenticated. Please check your API settings.'; } else if (error.message.includes('network') || error.message.includes('fetch')) { errorMessage = 'Network error. Please check your connection.'; } else if (error.message.includes('timeout')) { errorMessage = 'Search timed out. Please try again.'; } updateArtistsSearchStatus('error', errorMessage); } } finally { artistsSearchController = null; } } /** * Display artist search results */ function displayArtistsResults(query, results) { console.log(`๐ Displaying ${results.length} artist results`); // Update state artistsPageState.searchQuery = query; artistsPageState.searchResults = results; artistsPageState.currentView = 'results'; // Update header search input if different const headerInput = document.getElementById('artists-header-search-input'); if (headerInput && headerInput.value !== query) { headerInput.value = query; } // Show results state showArtistsResultsState(); // Populate results const container = document.getElementById('artists-cards-container'); if (!container) return; if (results.length === 0) { container.innerHTML = `
Search results will appear here when you select an album or track.
Active download processes
Active download processes
Active chart download processes