From ccc686a892386d716ce7db5a038fb1e3593421b1 Mon Sep 17 00:00:00 2001 From: Broque Thomas Date: Fri, 26 Sep 2025 15:12:25 -0700 Subject: [PATCH] placeholder beatport playlist functionality --- webui/index.html | 70 +++++++++++ webui/static/script.js | 90 ++++++++++++++ webui/static/style.css | 266 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 424 insertions(+), 2 deletions(-) diff --git a/webui/index.html b/webui/index.html index 8cda418a..185c80a1 100644 --- a/webui/index.html +++ b/webui/index.html @@ -341,6 +341,9 @@ + @@ -375,6 +378,73 @@
Parsed YouTube playlists will appear here.
+ + +
+ +
+ + +
+ + +
+
+
+
+

Browse Beatport Charts

+

Explore top electronic music charts and discover new tracks

+
+ 39 Genres + + Top 100 + + Weekly Updates +
+
+
+ +
+
+
+
+

🔥 Top Charts

+

Beatport Top 100, Hype Top 10, New Releases

+ 3 Charts +
+ +
+
+

🎵 Genre Explorer

+

House, Techno, Trance, and 36 more genres

+ 39 Genres +
+ +
+
+

📊 Staff Picks

+

Curated selections and secret weapons

+ 5 Collections +
+
+
+
+ + +
+
+

My Beatport Playlists

+ +
+
+
Your created Beatport playlists will appear here.
+
+
+
diff --git a/webui/static/script.js b/webui/static/script.js index 18c64485..7315d8c8 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -9190,6 +9190,39 @@ function initializeSyncPage() { tidalRefreshBtn.addEventListener('click', loadTidalPlaylists); } + // Logic for the Beatport refresh button + const beatportRefreshBtn = document.getElementById('beatport-refresh-btn'); + if (beatportRefreshBtn) { + beatportRefreshBtn.addEventListener('click', loadBeatportCharts); + } + + // Logic for Beatport nested tabs + const beatportTabButtons = document.querySelectorAll('.beatport-tab-button'); + beatportTabButtons.forEach(button => { + button.addEventListener('click', () => { + const tabId = button.dataset.beatportTab; + + // Update button active state + beatportTabButtons.forEach(btn => btn.classList.remove('active')); + button.classList.add('active'); + + // Update content active state + document.querySelectorAll('.beatport-tab-content').forEach(content => { + content.classList.remove('active'); + }); + document.getElementById(`beatport-${tabId}-content`).classList.add('active'); + }); + }); + + // Logic for Beatport category cards + const beatportCategoryCards = document.querySelectorAll('.beatport-category-card'); + beatportCategoryCards.forEach(card => { + card.addEventListener('click', () => { + const category = card.dataset.category; + handleBeatportCategoryClick(category); + }); + }); + // Logic for the Start Sync button const startSyncBtn = document.getElementById('start-sync-btn'); if (startSyncBtn) { @@ -9467,6 +9500,63 @@ async function clearWishlist(playlistId) { } +// =============================== +// BEATPORT CHARTS FUNCTIONALITY +// =============================== + +async function loadBeatportCharts() { + const container = document.getElementById('beatport-playlist-container'); + const refreshBtn = document.getElementById('beatport-refresh-btn'); + + container.innerHTML = `
🔄 Loading Beatport playlists...
`; + refreshBtn.disabled = true; + refreshBtn.textContent = '🔄 Loading...'; + + try { + // Placeholder functionality - will be implemented later with actual Beatport playlist management + await new Promise(resolve => setTimeout(resolve, 1000)); // Simulate loading + + container.innerHTML = ` +
+

🎵 My Beatport Playlists

+

Your created Beatport playlists will appear here.

+

+ Create playlists from Beatport charts using the Browse Charts tab,
+ then sync them directly to your media server. +

+
+ `; + + showToast('Beatport playlists loaded successfully!', 'success'); + + } catch (error) { + container.innerHTML = `
❌ Error: ${error.message}
`; + showToast(`Error loading Beatport playlists: ${error.message}`, 'error'); + } finally { + refreshBtn.disabled = false; + refreshBtn.textContent = '🔄 Refresh'; + } +} + +function handleBeatportCategoryClick(category) { + console.log(`🎵 Beatport category clicked: ${category}`); + + // Placeholder functionality for category navigation + switch(category) { + case 'top-charts': + showToast('🔥 Top Charts navigation coming soon!', 'info'); + break; + case 'genres': + showToast('🎵 Genre Explorer navigation coming soon!', 'info'); + break; + case 'staff-picks': + showToast('📊 Staff Picks navigation coming soon!', 'info'); + break; + default: + showToast(`Category "${category}" clicked`, 'info'); + } +} + // =============================== // YOUTUBE PLAYLIST FUNCTIONALITY // =============================== diff --git a/webui/static/style.css b/webui/static/style.css index 52a88b4d..3d2c5075 100644 --- a/webui/static/style.css +++ b/webui/static/style.css @@ -4226,17 +4226,23 @@ body { .tidal-icon { background-image: url('data:image/svg+xml;charset=utf-8,'); } -.youtube-icon { +.youtube-icon { background-image: url('data:image/svg+xml;charset=utf-8,'); } +.beatport-icon { + background-image: url('data:image/svg+xml;charset=utf-8,'); +} /* Active tab icons - make them white for better contrast */ .sync-tab-button.active .spotify-icon { background-image: url('data:image/svg+xml;charset=utf-8,'); } -.sync-tab-button.active .youtube-icon { +.sync-tab-button.active .youtube-icon { background-image: url('data:image/svg+xml;charset=utf-8,'); } +.sync-tab-button.active .beatport-icon { + background-image: url('data:image/svg+xml;charset=utf-8,'); +} .sync-tab-content { @@ -4279,6 +4285,262 @@ body { .refresh-button:hover { transform: scale(1.05); } .refresh-button.tidal { background: #ff6600; color: #fff; } .refresh-button.tidal:hover { background: #ff7700; } +.refresh-button.beatport { background: #01FF95; color: #000; } +.refresh-button.beatport:hover { background: #00E085; } + +/* ================================= */ +/* BEATPORT NESTED TABS SYSTEM */ +/* ================================= */ + +.beatport-tabs { + display: flex; + gap: 5px; + margin-bottom: 20px; + padding: 5px; + background: rgba(20, 20, 20, 0.6); + border-radius: 12px; + border: 1px solid rgba(255, 255, 255, 0.08); +} + +.beatport-tab-button { + flex: 1; + background: transparent; + border: none; + padding: 12px 20px; + border-radius: 8px; + color: #888; + font-size: 13px; + font-weight: 500; + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; + gap: 8px; +} + +.beatport-tab-button:hover { + background: rgba(1, 255, 149, 0.1); + color: #01FF95; +} + +.beatport-tab-button.active { + background: linear-gradient(135deg, #01FF95 0%, #00E085 100%); + color: #000; + font-weight: 600; +} + +.beatport-tab-button .tab-icon { + width: 14px; + height: 14px; +} + +.browse-icon { + background-image: url('data:image/svg+xml;charset=utf-8,'); +} + +.beatport-tab-button.active .browse-icon { + background-image: url('data:image/svg+xml;charset=utf-8,'); +} + +.playlist-icon { + background-image: url('data:image/svg+xml;charset=utf-8,'); +} + +.beatport-tab-button.active .playlist-icon { + background-image: url('data:image/svg+xml;charset=utf-8,'); +} + +.beatport-tab-content { + display: none; + height: 100%; + overflow: hidden; +} + +.beatport-tab-content.active { + display: flex; + flex-direction: column; +} + +/* ================================= */ +/* BEATPORT HERO SECTION */ +/* ================================= */ + +.beatport-hero { + position: relative; + height: 200px; + border-radius: 16px; + margin-bottom: 25px; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; +} + +.beatport-hero-bg { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, + rgba(1, 255, 149, 0.15) 0%, + rgba(0, 224, 133, 0.1) 50%, + rgba(20, 20, 20, 0.9) 100%); + backdrop-filter: blur(20px); + border: 1px solid rgba(1, 255, 149, 0.2); +} + +.beatport-hero-bg::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: + radial-gradient(circle at 20% 30%, rgba(1, 255, 149, 0.3) 0%, transparent 50%), + radial-gradient(circle at 80% 70%, rgba(0, 224, 133, 0.2) 0%, transparent 50%); + opacity: 0.7; +} + +.beatport-hero-content { + position: relative; + z-index: 2; + text-align: center; + color: #ffffff; +} + +.beatport-hero-content h2 { + font-size: 32px; + font-weight: 700; + margin: 0 0 8px 0; + background: linear-gradient(135deg, #01FF95 0%, #00E085 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.beatport-hero-content p { + font-size: 16px; + color: #b3b3b3; + margin: 0 0 15px 0; +} + +.beatport-stats { + display: flex; + align-items: center; + justify-content: center; + gap: 10px; + font-size: 14px; + color: #01FF95; + font-weight: 500; +} + +.stat-divider { + color: #555; +} + +/* ================================= */ +/* BEATPORT NAVIGATION CARDS */ +/* ================================= */ + +.beatport-navigation { + flex: 1; + overflow-y: auto; + padding: 0 5px; +} + +.beatport-category-cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 20px; + padding: 10px 0; +} + +.beatport-category-card { + background: linear-gradient(135deg, + rgba(25, 25, 25, 0.95) 0%, + rgba(15, 15, 15, 0.98) 100%); + backdrop-filter: blur(20px); + border-radius: 16px; + border: 1px solid rgba(255, 255, 255, 0.08); + border-top: 1px solid rgba(255, 255, 255, 0.12); + padding: 25px; + cursor: pointer; + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +.beatport-category-card::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, + rgba(1, 255, 149, 0.1) 0%, + transparent 50%); + opacity: 0; + transition: opacity 0.3s ease; +} + +.beatport-category-card:hover { + transform: translateY(-5px); + border-color: rgba(1, 255, 149, 0.3); + box-shadow: + 0 20px 40px rgba(0, 0, 0, 0.4), + 0 0 30px rgba(1, 255, 149, 0.2); +} + +.beatport-category-card:hover::before { + opacity: 1; +} + +.category-icon { + width: 48px; + height: 48px; + background: linear-gradient(135deg, #01FF95 0%, #00E085 100%); + border-radius: 12px; + margin-bottom: 15px; + display: flex; + align-items: center; + justify-content: center; + position: relative; +} + +.beatport-category-card h3 { + font-size: 18px; + font-weight: 600; + color: #ffffff; + margin: 0 0 8px 0; + position: relative; + z-index: 2; +} + +.beatport-category-card p { + font-size: 14px; + color: #888; + margin: 0 0 15px 0; + line-height: 1.4; + position: relative; + z-index: 2; +} + +.category-count { + display: inline-block; + background: rgba(1, 255, 149, 0.15); + color: #01FF95; + font-size: 12px; + font-weight: 600; + padding: 6px 12px; + border-radius: 20px; + border: 1px solid rgba(1, 255, 149, 0.3); + position: relative; + z-index: 2; +} .playlist-scroll-container { flex-grow: 1;