let me = null; let instruments = []; let songs = []; let searchQuery = ''; const expanded = new Set(); const editing = new Set(); function matchesSearch(song, query) { const q = query.trim().toLowerCase(); if (!q) return true; return song.title.toLowerCase().includes(q) || song.artist.toLowerCase().includes(q); } async function loadInstruments() { instruments = await api.get('/api/instruments'); } async function loadSongs() { songs = await api.get('/api/songs'); renderSongs(); } function instrumentOptions() { return instruments.map((i) => ``).join(''); } function songThumbTemplate(song) { const thumb = song.youtube_url ? youtubeThumbnailUrl(song.youtube_url) : null; if (thumb) { return `
`; } return `${escapeHtml(song.notes)}
` : ''} ${songLinksTemplate(song)}${escapeHtml(content)}
Aucun lien pour le moment.
'; return; } container.innerHTML = detail.tutorials.map(tutorialCardTemplate).join(''); container.querySelectorAll('.remove-tutorial').forEach((btn) => { btn.addEventListener('click', () => onRemoveTutorial(parseInt(btn.dataset.songId, 10), parseInt(btn.dataset.id, 10))); }); container.querySelectorAll('.tutorial-text-toggle').forEach((btn) => { btn.addEventListener('click', () => { const text = btn.previousElementSibling; const isExpanded = text.classList.toggle('expanded'); btn.textContent = isExpanded ? 'Voir moins' : 'Voir plus'; }); }); } catch (err) { showError(err.message); } } async function onAddTutorial(e) { e.preventDefault(); const form = e.target; const songId = parseInt(form.dataset.songId, 10); const instrumentId = parseInt(form.instrumentId.value, 10); const url = form.url.value.trim(); const content = form.content.value.trim(); const label = form.label.value.trim(); if (!url && !content) { showError('Renseignez un lien ou un texte pour le tuto.'); return; } try { await api.post(`/api/songs/${songId}/tutorials`, { instrumentId, url, content, label }); form.reset(); const song = songs.find((s) => s.id === songId); if (song) song.tutorial_count += 1; await loadTutorials(songId); renderSongs(); } catch (err) { showError(err.message); } } async function onRemoveTutorial(songId, tutorialId) { try { await api.del(`/api/songs/${songId}/tutorials/${tutorialId}`); const song = songs.find((s) => s.id === songId); if (song) song.tutorial_count -= 1; await loadTutorials(songId); renderSongs(); } catch (err) { showError(err.message); } } async function onAddSong(e) { e.preventDefault(); const form = e.target; const title = form.title.value.trim(); const artist = form.artist.value.trim(); const notes = form.notes.value.trim(); const youtubeUrl = form.youtubeUrl.value.trim(); const spotifyUrl = form.spotifyUrl.value.trim(); try { await api.post('/api/songs', { title, artist, notes, youtubeUrl, spotifyUrl }); form.reset(); document.getElementById('song-links-status').textContent = ''; songAutocomplete.close(); setAddSongPanelOpen(false); await loadSongs(); } catch (err) { showError(err.message); } } function setAddSongPanelOpen(open) { document.getElementById('add-song-panel').style.display = open ? 'block' : 'none'; document.getElementById('toggle-add-song').textContent = open ? 'Annuler' : '+ Ajouter un morceau'; } async function onSaveSong(e) { e.preventDefault(); const form = e.target; const id = parseInt(form.dataset.id, 10); const title = form.title.value.trim(); const artist = form.artist.value.trim(); const notes = form.notes.value.trim(); const youtubeUrl = form.youtubeUrl.value.trim(); const spotifyUrl = form.spotifyUrl.value.trim(); try { await api.patch(`/api/songs/${id}`, { title, artist, notes, youtubeUrl, spotifyUrl }); editing.delete(id); await loadSongs(); } catch (err) { showError(err.message); } } async function onDeleteSong(id) { try { await api.del(`/api/songs/${id}`); editing.delete(id); await loadSongs(); } catch (err) { showError(err.message); } } function showError(message) { document.getElementById('error').innerHTML = ``; } let songAutocomplete = null; async function onSongCandidateSelected(candidate) { document.getElementById('song-title-input').value = candidate.title; document.getElementById('song-artist-input').value = candidate.artist; const statusEl = document.getElementById('song-links-status'); statusEl.textContent = 'Recherche des liens YouTube / Spotify…'; try { const links = await api.get( `/api/music-search/links?title=${encodeURIComponent(candidate.title)}&artist=${encodeURIComponent(candidate.artist)}` ); const youtubeInput = document.getElementById('song-youtube-input'); const spotifyInput = document.getElementById('song-spotify-input'); if (links.youtubeUrl && !youtubeInput.value) youtubeInput.value = links.youtubeUrl; if (links.spotifyUrl && !spotifyInput.value) spotifyInput.value = links.spotifyUrl; if (links.youtubeUrl && links.spotifyUrl) statusEl.textContent = 'Liens YouTube et Spotify trouvés automatiquement.'; else if (links.youtubeUrl) statusEl.textContent = 'Lien YouTube trouvé automatiquement. Aucun lien Spotify trouvé — à saisir manuellement si besoin.'; else if (links.spotifyUrl) statusEl.textContent = 'Lien Spotify trouvé automatiquement. Aucun lien YouTube trouvé — à saisir manuellement si besoin.'; else statusEl.textContent = 'Aucun lien trouvé automatiquement — vous pouvez les saisir manuellement.'; } catch (err) { statusEl.textContent = ''; } } (async function init() { me = await initNav('repertoire'); await loadInstruments(); document.getElementById('add-song-form').addEventListener('submit', onAddSong); document.getElementById('toggle-add-song').addEventListener('click', () => { const isOpen = document.getElementById('add-song-panel').style.display !== 'none'; setAddSongPanelOpen(!isOpen); }); songAutocomplete = createTitleAutocomplete({ inputId: 'song-title-input', dropdownId: 'song-title-dropdown', onSelect: onSongCandidateSelected, }); document.getElementById('song-search-input').addEventListener('input', (e) => { searchQuery = e.target.value; renderSongs(); }); await loadSongs(); })();