placeholder beatport playlist functionality
This commit is contained in:
parent
cf33e17060
commit
ccc686a892
3 changed files with 424 additions and 2 deletions
|
|
@ -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 -->
|
||||
|
|
|
|||
|
|
@ -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
|
||||
// ===============================
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue