diff --git a/api/chat.php b/api/chat.php index ae64843..a6a059e 100644 --- a/api/chat.php +++ b/api/chat.php @@ -21,9 +21,31 @@ if ($method === 'GET') { db()->query("DELETE FROM messages WHERE created_at < DATE_SUB(NOW(), INTERVAL 6 HOUR)"); - $stmt = db()->prepare("SELECT m.*, ul.custom_color FROM messages m LEFT JOIN user_likes ul ON m.username = ul.username ORDER BY m.created_at DESC LIMIT 50"); + $stmt = db()->prepare("SELECT m.*, f.points, f.is_fan_of_month FROM messages m LEFT JOIN fans f ON m.username = f.name ORDER BY m.created_at DESC LIMIT 50"); $stmt->execute(); $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); + + foreach ($messages as &$msg) { + $points = $msg['points'] ?? 0; + $msg['level_color'] = '#94a3b8'; + $msg['level_emoji'] = ''; + + if ($msg['is_fan_of_month']) { + $msg['level_color'] = '#facc15'; + } elseif ($points >= 2500) { + $msg['level_color'] = '#a855f7'; + $msg['level_emoji'] = '👑'; + } elseif ($points >= 1000) { + $msg['level_color'] = '#f97316'; + $msg['level_emoji'] = '🔥'; + } elseif ($points >= 500) { + $msg['level_color'] = '#22c55e'; + $msg['level_emoji'] = '⭐'; + } elseif ($points >= 100) { + $msg['level_color'] = '#3b82f6'; + } + } + echo json_encode(array_reverse($messages)); } catch (Exception $e) { echo json_encode(['error' => $e->getMessage()]); diff --git a/api/get_top_fans.php b/api/get_top_fans.php index 5e80f9d..20609bb 100644 --- a/api/get_top_fans.php +++ b/api/get_top_fans.php @@ -5,26 +5,89 @@ header('Content-Type: application/json'); try { $pdo = db(); + $username = $_GET['username'] ?? null; + // 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 username provided and not in top 5, fetch it specifically + if ($username) { + $found = false; + foreach ($fans as $f) { + if (strtolower($f['username']) === strtolower($username)) { + $found = true; + break; + } } - 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']; + if (!$found) { + $stmt = $pdo->prepare("SELECT name as username, points as total_likes, photo, is_fan_of_month FROM fans WHERE name = ?"); + $stmt->execute([$username]); + $userFan = $stmt->fetch(PDO::FETCH_ASSOC); + if ($userFan) { + $userFan['is_extra'] = true; + $fans[] = $userFan; + } } - - // Custom color fallback - $fan['custom_color'] = $fan['is_fan_of_month'] ? '#facc15' : '#38bdf8'; } + // Add level and progress logic +foreach ($fans as &$fan) { + $fan['badges'] = []; + $points = $fan['total_likes']; + + // Level Calculation + if ($points >= 2500) { + $fan['level'] = 5; + $fan['level_name'] = 'Leyenda'; + $fan['level_color'] = '#a855f7'; // Purple + $fan['next_level_points'] = 0; + $fan['level_progress'] = 100; + $fan['unlocked_emoji'] = '👑'; + } elseif ($points >= 1000) { + $fan['level'] = 4; + $fan['level_name'] = 'Super Fan'; + $fan['level_color'] = '#f97316'; // Orange + $fan['next_level_points'] = 2500; + $fan['level_progress'] = (($points - 1000) / (2500 - 1000)) * 100; + $fan['unlocked_emoji'] = '🔥'; + } elseif ($points >= 500) { + $fan['level'] = 3; + $fan['level_name'] = 'Fan Leal'; + $fan['level_color'] = '#22c55e'; // Green + $fan['next_level_points'] = 1000; + $fan['level_progress'] = (($points - 500) / (1000 - 500)) * 100; + $fan['unlocked_emoji'] = '⭐'; + } elseif ($points >= 100) { + $fan['level'] = 2; + $fan['level_name'] = 'Oyente Frecuente'; + $fan['level_color'] = '#3b82f6'; // Blue + $fan['next_level_points'] = 500; + $fan['level_progress'] = (($points - 100) / (500 - 100)) * 100; + $fan['unlocked_emoji'] = ''; + } else { + $fan['level'] = 1; + $fan['level_name'] = 'Novato'; + $fan['level_color'] = '#94a3b8'; // Slate + $fan['next_level_points'] = 100; + $fan['level_progress'] = ($points / 100) * 100; + $fan['unlocked_emoji'] = ''; + } + + if ($fan['is_fan_of_month']) { + $fan['badges'][] = ['icon' => 'bi-star-fill', 'color' => '#facc15', 'label' => 'Fan del Mes']; + } + if ($points >= 1000) { + $fan['badges'][] = ['icon' => 'bi-gem', 'color' => '#38bdf8', 'label' => 'Diamante']; + } elseif ($points >= 500) { + $fan['badges'][] = ['icon' => 'bi-shield-check', 'color' => '#00c853', 'label' => 'Veterano']; + } + + // Custom color based on level + $fan['custom_color'] = $fan['level_color']; + if ($fan['is_fan_of_month']) $fan['custom_color'] = '#facc15'; +} + echo json_encode(['success' => true, 'fans' => $fans]); } catch (Exception $e) { echo json_encode(['error' => $e->getMessage()]); diff --git a/index.php b/index.php index 207d23a..6e96944 100644 --- a/index.php +++ b/index.php @@ -1247,6 +1247,50 @@ $twitter_link = "https://twitter.com/"; .badge-icon { font-size: 0.8rem; } + + /* Level System Styles */ + .level-badge { + font-size: 0.65rem; + font-weight: 800; + padding: 2px 8px; + border-radius: 10px; + text-transform: uppercase; + letter-spacing: 0.5px; + color: white; + box-shadow: 0 2px 5px rgba(0,0,0,0.2); + } + .level-progress-container { + margin-top: 1rem; + background: rgba(255, 255, 255, 0.05); + border: 1px solid var(--glass-border); + border-radius: 20px; + padding: 1rem; + animation: fadeIn 0.5s ease; + } + .level-bar-bg { + width: 100%; + height: 8px; + background: rgba(255, 255, 255, 0.1); + border-radius: 4px; + margin-top: 8px; + overflow: hidden; + } + .level-bar-fill { + height: 100%; + background: linear-gradient(90deg, var(--primary-color), var(--accent-color)); + width: 0%; + transition: width 1s cubic-bezier(0.175, 0.885, 0.32, 1.275); + box-shadow: 0 0 10px var(--primary-color); + } + .unlocked-reward { + font-size: 0.7rem; + color: var(--accent-color); + margin-top: 5px; + display: flex; + align-items: center; + gap: 5px; + font-weight: 700; + } @@ -1388,7 +1432,7 @@ $twitter_link = "https://twitter.com/";
- +
@@ -1438,6 +1482,23 @@ $twitter_link = "https://twitter.com/";
+ + +
@@ -2042,7 +2103,8 @@ $twitter_link = "https://twitter.com/"; const div = document.createElement('div'); const isLike = msg.message.includes('❤️'); - const customColor = msg.custom_color ? `color: ${msg.custom_color} !important;` : ''; + const nameColor = msg.level_color || (msg.is_fan_of_month ? '#facc15' : 'var(--primary-color)'); + const levelEmoji = msg.level_emoji || ''; div.style.background = isLike ? 'rgba(255, 68, 68, 0.15)' : 'rgba(255,255,255,0.05)'; div.style.padding = '0.8rem'; @@ -2057,8 +2119,8 @@ $twitter_link = "https://twitter.com/"; } div.innerHTML = ` -
- ${msg.username} +
+ ${msg.username} ${levelEmoji ? `${levelEmoji}` : ''}
${content}
${new Date(msg.created_at).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}
@@ -2564,8 +2626,9 @@ $twitter_link = "https://twitter.com/"; async function fetchLeaderboard() { const container = document.getElementById('leaderboard-list'); + const currentUserName = document.getElementById('user-name').value.trim(); try { - const response = await fetch('api/get_top_fans.php'); + const response = await fetch(`api/get_top_fans.php?username=${encodeURIComponent(currentUserName)}`); const data = await response.json(); if (data.success) { @@ -2574,25 +2637,74 @@ $twitter_link = "https://twitter.com/"; return; } - container.innerHTML = data.fans.map((fan, index) => ` + // Filter out extra user if they are not in top 5 for the list display, + // but we use them for the progress bar. + const topFans = data.fans.filter(f => !f.is_extra); + + container.innerHTML = topFans.map((fan, index) => `
${index + 1}
${fan.username}
- ${fan.username} + ${fan.username} + ${fan.unlocked_emoji ? `${fan.unlocked_emoji}` : ''} ${fan.badges.map(b => ``).join('')}
-
${parseInt(fan.total_likes).toLocaleString()} puntos
+
+ Nivel ${fan.level} +
${parseInt(fan.total_likes).toLocaleString()} pts
+
`).join(''); + + // Update current user's progress + if (currentUserName) { + const currentUserData = data.fans.find(f => f.username.toLowerCase() === currentUserName.toLowerCase()); + if (currentUserData) { + showUserProgress(currentUserData); + } else { + document.getElementById('user-progress-container').style.display = 'none'; + } + } else { + document.getElementById('user-progress-container').style.display = 'none'; + } } } catch (error) { container.innerHTML = '
Error al cargar el ranking.
'; } } + function showUserProgress(fan) { + const container = document.getElementById('user-progress-container'); + const badge = document.getElementById('user-level-badge'); + const name = document.getElementById('user-level-name'); + const pointsDisplay = document.getElementById('user-points-display'); + const bar = document.getElementById('user-level-bar'); + const rewards = document.getElementById('unlocked-rewards-msg'); + + container.style.display = 'block'; + badge.innerText = `Nivel ${fan.level}`; + badge.style.background = fan.level_color; + name.innerText = fan.level_name; + name.style.color = fan.level_color; + + pointsDisplay.innerText = `${parseInt(fan.total_likes).toLocaleString()} / ${fan.next_level_points || 'MAX'} pts`; + bar.style.width = `${fan.level_progress}%`; + bar.style.boxShadow = `0 0 10px ${fan.level_color}`; + + let nextReward = ''; + switch(fan.level) { + case 1: nextReward = 'Siguiente: Color de chat azul (100 pts)'; break; + case 2: nextReward = 'Siguiente: Color verde + ⭐ Emoji (500 pts)'; break; + case 3: nextReward = 'Siguiente: Color naranja + 🔥 Emoji (1000 pts)'; break; + case 4: nextReward = 'Siguiente: Color púrpura + 👑 Emoji (2500 pts)'; break; + default: nextReward = '¡Nivel Máximo alcanzado! Eres una Leyenda.'; break; + } + rewards.innerHTML = ` ${nextReward}`; + } + async function fetchGallery() { const container = document.getElementById('gallery-container'); try { diff --git a/ranking.php b/ranking.php index e360ba9..e7b03da 100644 --- a/ranking.php +++ b/ranking.php @@ -137,6 +137,16 @@ try { .fan-name { font-weight: 700; font-size: 1.1rem; } .fan-points { font-size: 0.8rem; opacity: 0.6; } + .level-badge { + font-size: 0.6rem; + font-weight: 800; + padding: 2px 6px; + border-radius: 8px; + text-transform: uppercase; + color: white; + margin-left: 8px; + } + .trophy { color: #facc15; font-size: 1.2rem; } .empty-state { @@ -167,6 +177,16 @@ try { = 2500) { $level = 5; $levelColor = '#a855f7'; $emoji = '👑'; } + elseif ($points >= 1000) { $level = 4; $levelColor = '#f97316'; $emoji = '🔥'; } + elseif ($points >= 500) { $level = 3; $levelColor = '#22c55e'; $emoji = '⭐'; } + elseif ($points >= 100) { $level = 2; $levelColor = '#3b82f6'; $emoji = ''; } + else { $level = 1; $levelColor = '#94a3b8'; $emoji = ''; } + + if ($fan['is_fan_of_month']) $levelColor = '#facc15'; ?>
@@ -178,7 +198,11 @@ try {
<?= htmlspecialchars($fan['name']) ?>
-
+
+ + + Nivel +
puntos