Auto commit: 2026-02-19T23:02:15.052Z
This commit is contained in:
parent
7b64e5daae
commit
e7457a62e5
11
api/chat.php
11
api/chat.php
@ -18,7 +18,7 @@ if ($method === 'GET') {
|
||||
unlink($path);
|
||||
}
|
||||
}
|
||||
db()->query("DELETE FROM messages WHERE (type = 'image' OR type = 'reaction') AND created_at < DATE_SUB(NOW(), INTERVAL 5 SECOND)");
|
||||
db()->query("DELETE FROM messages WHERE (type = 'image' OR type = 'reaction' OR type = 'flash_poll') AND created_at < DATE_SUB(NOW(), INTERVAL 5 SECOND)");
|
||||
|
||||
// Limpiar otros mensajes y archivos de más de 7 días
|
||||
$oldImages = db()->prepare("SELECT message FROM messages WHERE type = 'image' AND created_at < DATE_SUB(NOW(), INTERVAL 7 DAY)");
|
||||
@ -117,7 +117,14 @@ if ($method === 'GET') {
|
||||
|
||||
// Award points to the fan based on chat activity
|
||||
require_once __DIR__ . '/../includes/points_helper.php';
|
||||
$pts = ($type === 'reaction') ? 1 : 5;
|
||||
|
||||
if ($type === 'flash_poll_response') {
|
||||
awardLoyaltyPoints($username, 10);
|
||||
$pts = 10; // Also add to general ranking
|
||||
} else {
|
||||
$pts = ($type === 'reaction') ? 1 : 5;
|
||||
}
|
||||
|
||||
$newPoints = awardPoints($username, $pts);
|
||||
|
||||
// Auto-update Fan of the Month if this user has the highest points
|
||||
|
||||
@ -36,6 +36,29 @@ function awardPoints($username, $pointsToAdd) {
|
||||
return $newPoints;
|
||||
}
|
||||
|
||||
function awardLoyaltyPoints($username, $pointsToAdd) {
|
||||
if (empty($username) || $username === 'Anónimo') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$db = db();
|
||||
|
||||
// Get current loyalty points
|
||||
$stmt = $db->prepare("SELECT id, loyalty_points FROM fans WHERE name = ?");
|
||||
$stmt->execute([$username]);
|
||||
$fan = $stmt->fetch();
|
||||
|
||||
if ($fan) {
|
||||
$newPoints = $fan['loyalty_points'] + $pointsToAdd;
|
||||
$db->prepare("UPDATE fans SET loyalty_points = ? WHERE id = ?")->execute([$newPoints, $fan['id']]);
|
||||
} else {
|
||||
$newPoints = $pointsToAdd;
|
||||
$db->prepare("INSERT INTO fans (name, loyalty_points) VALUES (?, ?)")->execute([$username, $newPoints]);
|
||||
}
|
||||
|
||||
return $newPoints;
|
||||
}
|
||||
|
||||
function getNextLevelInfo($username) {
|
||||
$db = db();
|
||||
$stmt = $db->prepare("SELECT points FROM fans WHERE name = ?");
|
||||
|
||||
225
index.php
225
index.php
@ -1652,18 +1652,15 @@ $twitter_link = "https://twitter.com/";
|
||||
}
|
||||
|
||||
@keyframes flyUp {
|
||||
0% {
|
||||
transform: translateY(0) translateX(0) scale(0.5) rotate(0deg);
|
||||
opacity: 0;
|
||||
}
|
||||
10% {
|
||||
opacity: 1;
|
||||
transform: translateY(-20px) translateX(var(--drift)) scale(1.2) rotate(var(--rot));
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-100vh) translateX(calc(var(--drift) * 2)) scale(1) rotate(calc(var(--rot) * 2));
|
||||
opacity: 0;
|
||||
}
|
||||
0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: 0; }
|
||||
10% { opacity: 1; }
|
||||
100% { transform: translateY(-80vh) translateX(var(--drift)) rotate(var(--rot)); opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes floatUpFade {
|
||||
0% { transform: translate(-50%, -50%) scale(0.5); opacity: 0; }
|
||||
20% { opacity: 1; transform: translate(-50%, -80%) scale(1.2); }
|
||||
100% { transform: translate(-50%, -150%) scale(1); opacity: 0; }
|
||||
}
|
||||
|
||||
/* Reaction Buttons Container */
|
||||
@ -1680,6 +1677,73 @@ $twitter_link = "https://twitter.com/";
|
||||
animation: slideUpFade 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
|
||||
/* Flash Poll Styles */
|
||||
#flash-poll-container {
|
||||
position: fixed;
|
||||
top: 20%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%) scale(0.8);
|
||||
z-index: 9995;
|
||||
width: 90%;
|
||||
max-width: 400px;
|
||||
background: linear-gradient(145deg, rgba(30, 41, 59, 0.95), rgba(15, 23, 42, 0.98));
|
||||
border: 2px solid #facc15;
|
||||
border-radius: 24px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 0 50px rgba(250, 204, 21, 0.4), 0 20px 40px rgba(0,0,0,0.5);
|
||||
display: none;
|
||||
opacity: 0;
|
||||
transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
text-align: center;
|
||||
}
|
||||
#flash-poll-container.show {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
}
|
||||
.poll-question {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 800;
|
||||
color: #fff;
|
||||
margin-bottom: 15px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.poll-options {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
.poll-btn {
|
||||
background: rgba(255,255,255,0.1);
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border-radius: 12px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
flex: 1;
|
||||
}
|
||||
.poll-btn:hover {
|
||||
background: var(--primary-color);
|
||||
border-color: #fff;
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
.poll-timer-bar {
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background: rgba(255,255,255,0.1);
|
||||
border-radius: 2px;
|
||||
margin-top: 15px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.poll-timer-fill {
|
||||
height: 100%;
|
||||
background: #facc15;
|
||||
width: 100%;
|
||||
transition: width linear;
|
||||
}
|
||||
|
||||
/* Energy Thermometer for DJ */
|
||||
.energy-thermometer-container {
|
||||
display: none;
|
||||
@ -1893,6 +1957,11 @@ $twitter_link = "https://twitter.com/";
|
||||
<div class="track-info">
|
||||
<div id="dj-host-container" style="display: flex; align-items: center; gap: 8px;">
|
||||
<div class="dj-badge" onclick="adminOpenShoutout()" style="cursor: pointer;" title="DJ Panel (Admin)"><i class="bi bi-mic-fill"></i> <span id="current-dj-name">LILI</span></div>
|
||||
<div id="dj-flash-poll-control" style="display: none; margin-bottom: 8px;">
|
||||
<button onclick="promptFlashPoll()" style="background: rgba(250, 204, 21, 0.2); border: 1px solid #facc15; color: #facc15; font-size: 0.6rem; padding: 2px 8px; border-radius: 10px; font-weight: 800; cursor: pointer; transition: all 0.3s;" title="Lanzar Encuesta Flash">
|
||||
<i class="bi bi-lightning-fill"></i> PREGUNTA FLASH
|
||||
</button>
|
||||
</div>
|
||||
<div id="dj-energy-thermometer" class="energy-thermometer-container" title="Energía para la Fiesta Total">
|
||||
<span id="energy-text" class="energy-status-label">Cargando hype...</span>
|
||||
<div class="energy-thermometer">
|
||||
@ -2043,7 +2112,7 @@ $twitter_link = "https://twitter.com/";
|
||||
</div>
|
||||
|
||||
<!-- User Level Progress Section -->
|
||||
<div id="user-progress-container" class="level-progress-container" style="display: none;">
|
||||
<div id="user-progress-container" class="level-progress-container" style="display: none; margin-bottom: 1rem;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<span id="user-level-badge" class="level-badge">Nivel 1</span>
|
||||
@ -2054,6 +2123,23 @@ $twitter_link = "https://twitter.com/";
|
||||
<div class="level-bar-bg">
|
||||
<div id="user-level-bar" class="level-bar-fill"></div>
|
||||
</div>
|
||||
|
||||
<!-- Loyalty Wallet & Store -->
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 1rem; padding-top: 0.8rem; border-top: 1px solid rgba(255,255,255,0.05);">
|
||||
<div style="display: flex; align-items: center; gap: 10px;">
|
||||
<div style="width: 35px; height: 35px; background: rgba(0, 230, 118, 0.1); border: 1px solid rgba(0, 230, 118, 0.3); border-radius: 10px; display: flex; align-items: center; justify-content: center; color: #00e676; font-size: 1.2rem;">
|
||||
<i class="bi bi-coin"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 0.6rem; opacity: 0.6; text-transform: uppercase; font-weight: 700; letter-spacing: 1px;">Loyalty Points</div>
|
||||
<div id="loyalty-points-display" style="font-size: 1.1rem; font-weight: 800; color: #00e676;">0 LP</div>
|
||||
</div>
|
||||
</div>
|
||||
<button onclick="openShopModal()" style="background: linear-gradient(135deg, #00e676, #00c853); color: white; border: none; padding: 6px 15px; border-radius: 50px; font-size: 0.7rem; font-weight: 800; display: flex; align-items: center; gap: 5px; cursor: pointer; box-shadow: 0 4px 15px rgba(0, 230, 118, 0.3);">
|
||||
<i class="bi bi-cart-fill"></i> TIENDA
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="unlocked-rewards-msg" class="unlocked-reward">
|
||||
<i class="bi bi-unlock-fill"></i> Siguiente: Color de chat azul
|
||||
</div>
|
||||
@ -2428,6 +2514,22 @@ $twitter_link = "https://twitter.com/";
|
||||
<!-- Celebration Overlay -->
|
||||
<div id="celebration-overlay"></div>
|
||||
|
||||
<!-- Flash Poll Overlay -->
|
||||
<div id="flash-poll-container">
|
||||
<div style="font-size: 0.7rem; color: #facc15; font-weight: 800; text-transform: uppercase; margin-bottom: 5px; letter-spacing: 2px;">
|
||||
<i class="bi bi-lightning-fill"></i> Pregunta Flash del DJ
|
||||
</div>
|
||||
<div id="poll-question" class="poll-question">¿Qué canción prefieren para cerrar el set?</div>
|
||||
<div style="font-size: 0.65rem; color: #00e676; margin-bottom: 10px; font-weight: 700;">🎁 ¡RESPONDE Y GANA +10 LOYALTY POINTS!</div>
|
||||
<div class="poll-options">
|
||||
<button class="poll-btn" onclick="answerFlashPoll('SÍ')">¡SÍ! 🔥</button>
|
||||
<button class="poll-btn" onclick="answerFlashPoll('NO')">¡NO! 🎧</button>
|
||||
</div>
|
||||
<div class="poll-timer-bar">
|
||||
<div id="poll-timer-fill" class="poll-timer-fill"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Shoutout Modal -->
|
||||
<div id="shoutout-modal" class="shoutout-modal" onclick="this.classList.remove('show'); setTimeout(() => this.style.display = 'none', 500)">
|
||||
<div class="shoutout-card" onclick="event.stopPropagation()">
|
||||
@ -3018,12 +3120,17 @@ $twitter_link = "https://twitter.com/";
|
||||
showReactionButtons();
|
||||
}
|
||||
|
||||
// Trigger flash poll UI
|
||||
if (msg.type === 'flash_poll' && index >= lastMessageCount && lastMessageCount > 0) {
|
||||
showFlashPoll(msg.message);
|
||||
}
|
||||
|
||||
// Trigger flying emoji for reaction messages
|
||||
if (msg.type === 'reaction' && index >= lastMessageCount && lastMessageCount > 0) {
|
||||
spawnReactionEmoji(msg.message);
|
||||
}
|
||||
|
||||
if (msg.type === 'reaction') return;
|
||||
if (msg.type === 'reaction' || msg.type === 'flash_poll') return;
|
||||
|
||||
const div = document.createElement('div');
|
||||
const isLike = msg.message.includes('❤️');
|
||||
@ -3217,7 +3324,8 @@ $twitter_link = "https://twitter.com/";
|
||||
setTimeout(() => { emojiEl.remove(); }, duration * 1000);
|
||||
|
||||
// Massive Celebration Logic
|
||||
globalReactionCount++;
|
||||
const boost = window.isPollActive ? 10 : 1;
|
||||
globalReactionCount += boost;
|
||||
|
||||
// Update Energy Thermometer for DJ
|
||||
const energyFill = document.getElementById('energy-fill');
|
||||
@ -3260,6 +3368,87 @@ $twitter_link = "https://twitter.com/";
|
||||
}
|
||||
}
|
||||
|
||||
async function promptFlashPoll() {
|
||||
const question = prompt("Ingresa la Pregunta Flash para la audiencia:");
|
||||
if (!question) return;
|
||||
const userName = document.getElementById('user-name').value.trim() || 'Lili';
|
||||
await sendChatMessage(question, 'flash_poll', userName);
|
||||
}
|
||||
|
||||
function showFlashPoll(question) {
|
||||
const container = document.getElementById('flash-poll-container');
|
||||
const qEl = document.getElementById('poll-question');
|
||||
const timerFill = document.getElementById('poll-timer-fill');
|
||||
|
||||
qEl.innerText = question;
|
||||
container.style.display = 'block';
|
||||
setTimeout(() => container.classList.add('show'), 10);
|
||||
|
||||
timerFill.style.transition = 'none';
|
||||
timerFill.style.width = '100%';
|
||||
|
||||
setTimeout(() => {
|
||||
timerFill.style.transition = 'width 30s linear';
|
||||
timerFill.style.width = '0%';
|
||||
}, 100);
|
||||
|
||||
window.isPollActive = true;
|
||||
showReactionButtons(); // Activar botones de reacción para el combo
|
||||
|
||||
setTimeout(() => {
|
||||
container.classList.remove('show');
|
||||
window.isPollActive = false;
|
||||
setTimeout(() => { container.style.display = 'none'; }, 500);
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
async function answerFlashPoll(answer) {
|
||||
const emoji = answer === 'SÍ' ? '🔥' : '🎧';
|
||||
const userName = document.getElementById('user-name').value.trim() || 'Anónimo';
|
||||
|
||||
try {
|
||||
await fetch('api/chat.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
username: userName,
|
||||
message: emoji,
|
||||
type: 'flash_poll_response'
|
||||
})
|
||||
});
|
||||
|
||||
// Show floating +10 LP animation
|
||||
showFloatingPoints('+10 LP', '#00e676');
|
||||
|
||||
spawnReactionEmoji(emoji);
|
||||
} catch (error) {
|
||||
console.error('Error sending poll response:', error);
|
||||
}
|
||||
|
||||
document.getElementById('flash-poll-container').classList.remove('show');
|
||||
window.isPollActive = false;
|
||||
}
|
||||
|
||||
function showFloatingPoints(text, color) {
|
||||
const container = document.getElementById('flash-poll-container');
|
||||
const floating = document.createElement('div');
|
||||
floating.innerText = text;
|
||||
floating.style.position = 'absolute';
|
||||
floating.style.top = '50%';
|
||||
floating.style.left = '50%';
|
||||
floating.style.transform = 'translate(-50%, -50%)';
|
||||
floating.style.color = color;
|
||||
floating.style.fontWeight = '900';
|
||||
floating.style.fontSize = '2rem';
|
||||
floating.style.zIndex = '10005';
|
||||
floating.style.pointerEvents = 'none';
|
||||
floating.style.animation = 'floatUpFade 1.5s forwards';
|
||||
floating.style.textShadow = '0 0 10px rgba(0,0,0,0.5)';
|
||||
|
||||
container.appendChild(floating);
|
||||
setTimeout(() => floating.remove(), 1500);
|
||||
}
|
||||
|
||||
async function sendReaction(emoji) {
|
||||
const userName = document.getElementById('user-name').value.trim() || 'Anónimo';
|
||||
try {
|
||||
@ -3457,6 +3646,10 @@ $twitter_link = "https://twitter.com/";
|
||||
const thermometer = document.getElementById('dj-energy-thermometer');
|
||||
if (thermometer) thermometer.style.display = isGuestDj ? 'flex' : 'none';
|
||||
|
||||
// Show/hide Flash Poll control
|
||||
const pollControl = document.getElementById('dj-flash-poll-control');
|
||||
if (pollControl) pollControl.style.display = isGuestDj ? 'block' : 'none';
|
||||
|
||||
if (result.success) {
|
||||
const list = document.getElementById('song-requests-list');
|
||||
if (result.requests.length === 0) {
|
||||
@ -4024,8 +4217,10 @@ $twitter_link = "https://twitter.com/";
|
||||
// Update shop points display
|
||||
const shopPoints = document.getElementById('shop-user-points');
|
||||
const shopLoyalty = document.getElementById('shop-user-loyalty');
|
||||
const mainLoyalty = document.getElementById('loyalty-points-display');
|
||||
if (shopPoints) shopPoints.innerText = `${parseInt(fan.total_likes).toLocaleString()} PTS`;
|
||||
if (shopLoyalty) shopLoyalty.innerText = `${parseInt(fan.loyalty_points || 0).toLocaleString()} LP`;
|
||||
if (mainLoyalty) mainLoyalty.innerText = `${parseInt(fan.loyalty_points || 0).toLocaleString()} LP`;
|
||||
|
||||
container.style.display = 'block';
|
||||
badge.innerText = `Nivel ${fan.level}`;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user