diff --git a/api/get_top_fans.php b/api/get_top_fans.php index 56409bf..5e80f9d 100644 --- a/api/get_top_fans.php +++ b/api/get_top_fans.php @@ -5,9 +5,26 @@ header('Content-Type: application/json'); try { $pdo = db(); - $stmt = $pdo->query("SELECT username, total_likes, custom_color FROM user_likes ORDER BY total_likes DESC LIMIT 5"); + // Get top fans from the fans table + $stmt = $pdo->query("SELECT name as username, points as total_likes, photo, is_fan_of_month FROM fans ORDER BY points DESC LIMIT 5"); $fans = $stmt->fetchAll(PDO::FETCH_ASSOC); + // Add badge logic + foreach ($fans as &$fan) { + $fan['badges'] = []; + if ($fan['is_fan_of_month']) { + $fan['badges'][] = ['icon' => 'bi-star-fill', 'color' => '#facc15', 'label' => 'Fan del Mes']; + } + if ($fan['total_likes'] >= 1000) { + $fan['badges'][] = ['icon' => 'bi-gem', 'color' => '#38bdf8', 'label' => 'Diamante']; + } elseif ($fan['total_likes'] >= 500) { + $fan['badges'][] = ['icon' => 'bi-shield-check', 'color' => '#00c853', 'label' => 'Veterano']; + } + + // Custom color fallback + $fan['custom_color'] = $fan['is_fan_of_month'] ? '#facc15' : '#38bdf8'; + } + echo json_encode(['success' => true, 'fans' => $fans]); } catch (Exception $e) { echo json_encode(['error' => $e->getMessage()]); diff --git a/api/song_requests.php b/api/song_requests.php index 3968b37..1fc8e6f 100644 --- a/api/song_requests.php +++ b/api/song_requests.php @@ -45,6 +45,21 @@ if ($method === 'POST') { try { $stmt = $db->prepare("INSERT INTO song_requests (artist, song, requester) VALUES (?, ?, ?)"); $stmt->execute([$artist, $song, $requester]); + + // Award points for song request + if ($requester !== 'Anónimo') { + $fanStmt = $db->prepare("SELECT id, points FROM fans WHERE name = ?"); + $fanStmt->execute([$requester]); + $fan = $fanStmt->fetch(); + + if ($fan) { + $newPoints = $fan['points'] + 25; // More points for a request + $db->prepare("UPDATE fans SET points = ? WHERE id = ?")->execute([$newPoints, $fan['id']]); + } else { + $db->prepare("INSERT INTO fans (name, points) VALUES (?, ?)")->execute([$requester, 25]); + } + } + echo json_encode(['success' => true]); } catch (Exception $e) { echo json_encode(['success' => false, 'error' => $e->getMessage()]); diff --git a/index.php b/index.php index 0addb94..207d23a 100644 --- a/index.php +++ b/index.php @@ -1194,6 +1194,59 @@ $twitter_link = "https://twitter.com/"; opacity: 0.6; text-transform: uppercase; } + + /* Leaderboard Styles */ + .leaderboard-list { + display: flex; + flex-direction: column; + gap: 0.8rem; + } + .leaderboard-item { + display: flex; + align-items: center; + gap: 12px; + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); + padding: 0.8rem; + border-radius: 16px; + transition: all 0.3s ease; + } + .leaderboard-item:hover { + background: rgba(255, 255, 255, 0.1); + transform: translateX(5px); + border-color: var(--primary-color); + } + .leaderboard-rank { + font-weight: 800; + font-size: 1.1rem; + width: 25px; + text-align: center; + color: var(--primary-color); + } + .leaderboard-avatar { + width: 45px; + height: 45px; + border-radius: 50%; + border: 2px solid var(--glass-border); + object-fit: cover; + } + .leaderboard-info { + flex: 1; + } + .leaderboard-name { + font-weight: 700; + font-size: 0.95rem; + display: flex; + align-items: center; + gap: 5px; + } + .leaderboard-points { + font-size: 0.75rem; + opacity: 0.6; + } + .badge-icon { + font-size: 0.8rem; + } @@ -1513,6 +1566,22 @@ $twitter_link = "https://twitter.com/"; + + +
+
+

+ TOP FANS +

+ VER TODO +
+
+
Cargando ranking...
+
+
+ Suma puntos participando en el chat y pidiendo canciones. +
+
@@ -2493,11 +2562,35 @@ $twitter_link = "https://twitter.com/"; } } - // Fetch Now Playing Metadata from RadioKing - let progressInterval = null; - - async function updateMetadata() { - // ... (keeping existing logic) + async function fetchLeaderboard() { + const container = document.getElementById('leaderboard-list'); + try { + const response = await fetch('api/get_top_fans.php'); + const data = await response.json(); + + if (data.success) { + if (data.fans.length === 0) { + container.innerHTML = '
No hay fans destacados aún.
'; + return; + } + + container.innerHTML = data.fans.map((fan, index) => ` +
+
${index + 1}
+ ${fan.username} +
+
+ ${fan.username} + ${fan.badges.map(b => ``).join('')} +
+
${parseInt(fan.total_likes).toLocaleString()} puntos
+
+
+ `).join(''); + } + } catch (error) { + container.innerHTML = '
Error al cargar el ranking.
'; + } } async function fetchGallery() { @@ -2546,18 +2639,27 @@ $twitter_link = "https://twitter.com/"; document.body.style.overflow = 'auto'; } - // Initial fetch - fetchGallery(); - setInterval(fetchGallery, 60000); // Update every minute + // Fetch Now Playing Metadata + let progressInterval = null; - } + async function updateMetadata() { + try { + const response = await fetch('https://www.radioking.com/widgets/api/v1/radio/828046/track/current'); + const data = await response.json(); + + if (data && data.title) { + const title = data.title; + const artist = data.artist; + const album = data.album || ''; + const coverUrl = data.cover || './assets/pasted-20260215-163754-def41f49.png'; + const fullDisplay = `${artist} - ${title}`; + if (trackTitle.textContent !== title) { trackTitle.style.opacity = '0'; if (trackArtist) trackArtist.style.opacity = '0'; if (trackAlbum) trackAlbum.style.opacity = '0'; if (trackCover) trackCover.style.opacity = '0'; - // Reset Like Button const likeIcon = document.querySelector('#like-song-btn i'); if (likeIcon) { likeIcon.classList.remove('bi-heart-fill'); @@ -2633,14 +2735,12 @@ $twitter_link = "https://twitter.com/"; if (coverPlaceholder) coverPlaceholder.style.display = 'none'; trackCover.style.opacity = '1'; - // Record History in Database fetch('api/record_history.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: title, artist: artist, cover: coverUrl }) }).catch(err => console.error("Error recording history:", err)); - // Dynamic Color Extraction trackCover.onload = function() { try { const canvas = document.createElement('canvas'); @@ -2652,13 +2752,11 @@ $twitter_link = "https://twitter.com/"; if (rgb[0] + rgb[1] + rgb[2] > 30) { const color = `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`; document.documentElement.style.setProperty('--primary-color', color); - // Dynamic glow removed for stability } } catch(e) {} }; } - // Dynamic Background Update fetch(`api/pexels.php?query=${encodeURIComponent(artist + " " + title + " music background")}`) .then(res => res.json()) .then(pData => { @@ -2667,7 +2765,6 @@ $twitter_link = "https://twitter.com/"; } }).catch(() => {}); - // Progress Bar Logic const progContainer = document.getElementById('track-progress-container'); const progBar = document.getElementById('track-progress-bar'); @@ -2688,12 +2785,12 @@ $twitter_link = "https://twitter.com/"; } updateProgressBar(); + if (progressInterval) clearInterval(progressInterval); progressInterval = setInterval(updateProgressBar, 1000); } else if (progContainer) { progContainer.style.display = 'none'; } - // Fetch likes for this song try { const lResp = await fetch(`api/get_likes.php?song_title=${encodeURIComponent(fullDisplay)}`); const lData = await lResp.json(); @@ -2702,13 +2799,11 @@ $twitter_link = "https://twitter.com/"; } } catch (e) {} - // Check if scrolling is needed if (trackTitle.scrollWidth > trackTitle.clientWidth) { trackTitle.classList.add('scrolling'); trackTitle.innerHTML = `${title}      ${title}     `; } - // Update Sticky Bar const stickyBar = document.getElementById('sticky-now-playing'); const stickyCover = document.getElementById('sticky-track-cover'); const stickyInfo = document.getElementById('sticky-track-info'); @@ -2722,16 +2817,12 @@ $twitter_link = "https://twitter.com/"; document.title = `▶ ${fullDisplay} | Lili Records Radio`; - // Media Session API for System Controls if ('mediaSession' in navigator) { navigator.mediaSession.metadata = new MediaMetadata({ title: title, artist: artist, album: 'Lili Records Radio', - artwork: [ - { src: data.cover || './assets/pasted-20260215-163754-def41f49.png', sizes: '512x512', type: 'image/png' }, - { src: data.cover || './assets/pasted-20260215-163754-def41f49.png', sizes: '256x256', type: 'image/png' } - ] + artwork: [{ src: coverUrl, sizes: '512x512', type: 'image/png' }] }); } } else { @@ -2745,13 +2836,17 @@ $twitter_link = "https://twitter.com/"; } } - // Update every 30 seconds + // Initial fetch updateMetadata(); fetchTopSongs(); - setInterval(() => { - updateMetadata(); - fetchTopSongs(); - }, 30000); + fetchGallery(); + fetchLeaderboard(); + + // Update cycles + setInterval(updateMetadata, 30000); + setInterval(fetchTopSongs, 60000); + setInterval(fetchGallery, 60000); + setInterval(fetchLeaderboard, 60000); // Theme Toggle Functionality function toggleTheme() {