placeholder beatport playlist functionality

This commit is contained in:
Broque Thomas 2025-09-26 15:12:25 -07:00
parent cf33e17060
commit ccc686a892
3 changed files with 424 additions and 2 deletions

View file

@ -341,6 +341,9 @@
<button class="sync-tab-button" data-tab="youtube">
<span class="tab-icon youtube-icon"></span> YouTube
</button>
<button class="sync-tab-button" data-tab="beatport">
<span class="tab-icon beatport-icon"></span> Beatport
</button>
</div>
<!-- Spotify Tab Content -->
@ -375,6 +378,73 @@
<div class="playlist-placeholder">Parsed YouTube playlists will appear here.</div>
</div>
</div>
<!-- Beatport Tab Content -->
<div class="sync-tab-content" id="beatport-tab-content">
<!-- Beatport Nested Tabs -->
<div class="beatport-tabs">
<button class="beatport-tab-button active" data-beatport-tab="browse">
<span class="tab-icon browse-icon"></span> Browse Charts
</button>
<button class="beatport-tab-button" data-beatport-tab="playlists">
<span class="tab-icon playlist-icon"></span> My Playlists
</button>
</div>
<!-- Browse Charts Tab Content -->
<div class="beatport-tab-content active" id="beatport-browse-content">
<div class="beatport-hero">
<div class="beatport-hero-bg"></div>
<div class="beatport-hero-content">
<h2>Browse Beatport Charts</h2>
<p>Explore top electronic music charts and discover new tracks</p>
<div class="beatport-stats">
<span class="stat-item">39 Genres</span>
<span class="stat-divider"></span>
<span class="stat-item">Top 100</span>
<span class="stat-divider"></span>
<span class="stat-item">Weekly Updates</span>
</div>
</div>
</div>
<div class="beatport-navigation">
<div class="beatport-category-cards">
<div class="beatport-category-card" data-category="top-charts">
<div class="category-icon top-charts-icon"></div>
<h3>🔥 Top Charts</h3>
<p>Beatport Top 100, Hype Top 10, New Releases</p>
<span class="category-count">3 Charts</span>
</div>
<div class="beatport-category-card" data-category="genres">
<div class="category-icon genres-icon"></div>
<h3>🎵 Genre Explorer</h3>
<p>House, Techno, Trance, and 36 more genres</p>
<span class="category-count">39 Genres</span>
</div>
<div class="beatport-category-card" data-category="staff-picks">
<div class="category-icon staff-picks-icon"></div>
<h3>📊 Staff Picks</h3>
<p>Curated selections and secret weapons</p>
<span class="category-count">5 Collections</span>
</div>
</div>
</div>
</div>
<!-- My Playlists Tab Content -->
<div class="beatport-tab-content" id="beatport-playlists-content">
<div class="playlist-header">
<h3>My Beatport Playlists</h3>
<button class="refresh-button beatport" id="beatport-refresh-btn">🔄 Refresh</button>
</div>
<div class="playlist-scroll-container" id="beatport-playlist-container">
<div class="playlist-placeholder">Your created Beatport playlists will appear here.</div>
</div>
</div>
</div>
</div>
<!-- Right Panel: Sidebar with Options & Logging -->

View file

@ -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 = `<div class="playlist-placeholder">🔄 Loading Beatport playlists...</div>`;
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 = `
<div class="playlist-placeholder">
<h4 style="color: #01FF95; margin-bottom: 10px;">🎵 My Beatport Playlists</h4>
<p>Your created Beatport playlists will appear here.</p>
<p style="font-size: 12px; color: #888;">
Create playlists from Beatport charts using the Browse Charts tab,<br>
then sync them directly to your media server.
</p>
</div>
`;
showToast('Beatport playlists loaded successfully!', 'success');
} catch (error) {
container.innerHTML = `<div class="playlist-placeholder">❌ Error: ${error.message}</div>`;
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
// ===============================

View file

@ -4226,17 +4226,23 @@ body {
.tidal-icon {
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23ffffff"><path d="M12.012 3.992L8.008 7.996 12.012 12l4.004-4.004-4.004-4.004zm7.996 8.008L16.004 8.004 12 12.008l4.004 4.004L20.008 12zm-16.008 0L8.004 16.004 12 12l-4.004-4.004L3.996 12zm8.004 4.004L8.004 20.008 12.012 24l4.004-4.004-4.004-3.996z"/></svg>');
}
.youtube-icon {
.youtube-icon {
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23ff0000"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>');
}
.beatport-icon {
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%2301FF95"><path d="M2 6h20v2H2zm0 5h20v2H2zm0 5h20v2H2z"/></svg>');
}
/* 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,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23ffffff"><path d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.48.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.42 1.56-.299.421-1.02.599-1.559.3z"/></svg>');
}
.sync-tab-button.active .youtube-icon {
.sync-tab-button.active .youtube-icon {
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23ffffff"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>');
}
.sync-tab-button.active .beatport-icon {
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23ffffff"><path d="M2 6h20v2H2zm0 5h20v2H2zm0 5h20v2H2z"/></svg>');
}
.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,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23888888"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>');
}
.beatport-tab-button.active .browse-icon {
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23000000"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>');
}
.playlist-icon {
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23888888"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/></svg>');
}
.beatport-tab-button.active .playlist-icon {
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23000000"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/></svg>');
}
.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;