Auto commit: 2026-02-19T19:32:43.296Z

This commit is contained in:
Flatlogic Bot 2026-02-19 19:32:43 +00:00
parent 71f83385d2
commit c9509afe45
4 changed files with 259 additions and 10 deletions

View File

@ -9,6 +9,11 @@ try {
$stmt->execute();
$tips = $stmt->fetchAll();
// Fetch recent thanks from the last 15 seconds
$stmt = $pdo->prepare("SELECT * FROM dj_tips WHERE thanked_at > (NOW() - INTERVAL 15 SECOND) ORDER BY thanked_at DESC LIMIT 5");
$stmt->execute();
$thanks = $stmt->fetchAll();
// Also get current DJ
$stmt = $pdo->query("SELECT setting_value FROM settings WHERE setting_key = 'current_dj'");
$dj = $stmt->fetchColumn() ?: "Lili";
@ -16,6 +21,7 @@ try {
echo json_encode([
"success" => true,
"tips" => $tips,
"thanks" => $thanks,
"current_dj" => $dj
]);
} catch (Exception $e) {

View File

@ -5,6 +5,7 @@ header("Content-Type: application/json");
$pdo = db();
$username = $_POST["username"] ?? "";
$amount = intval($_POST["amount"] ?? 100);
$message = $_POST["message"] ?? "";
if (!$username) {
echo json_encode(["success" => false, "error" => "Inicia sesión para enviar flores"]);
@ -34,8 +35,8 @@ try {
$stmt->execute([$amount, $username]);
// Log tip
$stmt = $pdo->prepare("INSERT INTO dj_tips (sender_name, dj_name, amount) VALUES (?, ?, ?)");
$stmt->execute([$username, $dj, $amount]);
$stmt = $pdo->prepare("INSERT INTO dj_tips (sender_name, dj_name, amount, message) VALUES (?, ?, ?, ?)");
$stmt->execute([$username, $dj, $amount, $message]);
$pdo->commit();

24
api/thank_tip.php Normal file
View File

@ -0,0 +1,24 @@
<?php
require_once __DIR__ . "/../db/config.php";
header("Content-Type: application/json");
$pdo = db();
$data = json_decode(file_get_contents("php://input"), true);
$tipId = intval($data["tip_id"] ?? 0);
if (!$tipId) {
echo json_encode(["success" => false, "error" => "ID de propina no válido"]);
exit;
}
try {
$stmt = $pdo->prepare("UPDATE dj_tips SET thanked_at = NOW() WHERE id = ?");
$stmt->execute([$tipId]);
echo json_encode([
"success" => true,
"message" => "¡Has agradecido la donación!"
]);
} catch (Exception $e) {
echo json_encode(["success" => false, "error" => $e->getMessage()]);
}

234
index.php
View File

@ -1418,6 +1418,63 @@ $twitter_link = "https://twitter.com/";
opacity: 0;
}
.donor-message {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(15, 23, 42, 0.8);
backdrop-filter: blur(12px);
padding: 25px 50px;
border-radius: 24px;
border: 2px solid #f472b6;
color: white;
text-align: center;
z-index: 2000;
animation: toast-celebration 5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
box-shadow: 0 20px 40px rgba(236, 72, 153, 0.4), 0 0 20px rgba(236, 72, 153, 0.2);
pointer-events: auto;
min-width: 300px;
}
.donor-message h4 {
margin: 0;
font-size: 1rem;
text-transform: uppercase;
letter-spacing: 2px;
color: #f472b6;
font-weight: 800;
}
.donor-message h2 {
margin: 10px 0 0;
font-size: 2.2rem;
font-weight: 900;
background: linear-gradient(to right, #ffffff, #f472b6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 20px rgba(244, 114, 182, 0.3);
}
.donor-message p {
margin: 15px 0 0;
font-size: 1.1rem;
font-style: italic;
color: rgba(255, 255, 255, 0.9);
border-top: 1px solid rgba(244, 114, 182, 0.3);
padding-top: 15px;
max-width: 400px;
line-height: 1.4;
}
@keyframes toast-celebration {
0% { opacity: 0; transform: translate(-50%, -30%) scale(0.8); }
10% { opacity: 1; transform: translate(-50%, -50%) scale(1.05); }
15% { transform: translate(-50%, -50%) scale(1); }
85% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
100% { opacity: 0; transform: translate(-50%, -70%) scale(0.9); }
}
@keyframes fall-and-sway {
0% { transform: translateY(-10vh) translateX(0) rotate(0deg); opacity: 0; }
10% { opacity: 1; }
@ -2112,6 +2169,26 @@ $twitter_link = "https://twitter.com/";
</div>
</div>
<!-- Flowers Modal -->
<div id="flowers-modal" class="sleep-modal" onclick="closeFlowersModal()">
<div class="sleep-modal-content" onclick="event.stopPropagation()" style="max-width: 450px;">
<h3 style="margin-top: 0; color: #f472b6;"><i class="bi bi-flower1"></i> Regalar Flores</h3>
<p style="opacity: 0.7; font-size: 0.9rem; margin-bottom: 1.5rem;">Envía un ramo de flores al DJ y personaliza tu mensaje.</p>
<div class="interaction-form" style="margin-top: 0;">
<div class="form-group" style="margin-bottom: 1.5rem;">
<label for="flower-message">MENSAJE PERSONALIZADO</label>
<textarea id="flower-message" placeholder="Escribe algo bonito para el DJ..." style="height: 80px;"></textarea>
</div>
<button onclick="confirmSendFlowers()" id="confirm-flowers-btn" class="send-whatsapp-btn" style="background-color: #f472b6; width: 100%;">
<i class="bi bi-send-fill"></i> ENVIAR POR 100 PTS
</button>
</div>
<button onclick="closeFlowersModal()" style="margin-top: 1.5rem; background: none; border: none; color: white; opacity: 0.5; cursor: pointer;">Cancelar</button>
</div>
</div>
<!-- Floating Social Links -->
<div class="social-float-container">
<a href="<?= $facebook_link ?>" class="social-float facebook" target="_blank" title="Facebook">
@ -2201,6 +2278,7 @@ $twitter_link = "https://twitter.com/";
<audio id="pop-sound" src="https://assets.mixkit.co/active_storage/sfx/2354/2354-preview.mp3" preload="none"></audio>
<script>
const isAdmin = <?php echo isset($_GET['admin']) && $_GET['admin'] === '1' ? 'true' : 'false'; ?>;
const audio = document.getElementById('radio-audio');
const playBtn = document.getElementById('play-pause');
const playIcon = document.getElementById('play-icon');
@ -3993,20 +4071,37 @@ $twitter_link = "https://twitter.com/";
let lastCelebrationId = 0;
const shownTips = new Set();
async function sendFlowersToDJ() {
function openFlowersModal() {
const userName = document.getElementById('user-name').value.trim();
if (!userName) {
alert('Por favor, ingresa tu nombre arriba para regalar flores.');
document.getElementById('user-name').focus();
return;
}
document.getElementById('flowers-modal').classList.add('show');
}
if (!confirm(`¿Quieres enviarle un ramo de flores al DJ por 100 puntos?`)) return;
function closeFlowersModal() {
document.getElementById('flowers-modal').classList.remove('show');
}
async function sendFlowersToDJ() {
openFlowersModal();
}
async function confirmSendFlowers() {
const userName = document.getElementById('user-name').value.trim();
const message = document.getElementById('flower-message').value.trim();
const btn = document.getElementById('confirm-flowers-btn');
try {
btn.disabled = true;
btn.innerHTML = '<i class="bi bi-hourglass-split"></i> ENVIANDO...';
const formData = new FormData();
formData.append('username', userName);
formData.append('amount', 100);
formData.append('message', message);
const response = await fetch('api/send_tip.php', {
method: 'POST',
@ -4015,14 +4110,18 @@ $twitter_link = "https://twitter.com/";
const data = await response.json();
if (data.success) {
alert(data.message);
launchFlowerCelebration(); // Local trigger
closeFlowersModal();
document.getElementById('flower-message').value = '';
launchFlowerCelebration(userName, message); // Local trigger with message
fetchLeaderboard(); // Update points
} else {
alert(data.error);
}
} catch (e) {
console.error('Error sending flowers:', e);
} finally {
btn.disabled = false;
btn.innerHTML = '<i class="bi bi-send-fill"></i> ENVIAR POR 100 PTS';
}
}
@ -4041,13 +4140,24 @@ $twitter_link = "https://twitter.com/";
data.tips.forEach(tip => {
if (!shownTips.has(tip.id)) {
shownTips.add(tip.id);
launchFlowerCelebration();
launchFlowerCelebration(tip.sender_name, tip.message, tip.id);
console.log(`Celebration for tip from ${tip.sender_name}`);
}
});
// Check for new thanks
if (data.thanks) {
data.thanks.forEach(thank => {
const thankKey = `thank_${thank.id}`;
if (!shownTips.has(thankKey)) {
shownTips.add(thankKey);
launchDJThanksCelebration(thank.sender_name);
}
});
}
// Cleanup set to keep it small
if (shownTips.size > 50) {
if (shownTips.size > 100) {
const it = shownTips.values();
shownTips.delete(it.next().value);
}
@ -4057,7 +4167,7 @@ $twitter_link = "https://twitter.com/";
}
}
function launchFlowerCelebration() {
function launchFlowerCelebration(senderName = "", donorMessage = "", tipId = null) {
// Celebration confetti burst
confetti({
particleCount: 150,
@ -4069,6 +4179,35 @@ $twitter_link = "https://twitter.com/";
});
const container = document.getElementById('celebration-overlay');
// Floating Name Message
if (senderName) {
const message = document.createElement('div');
message.className = 'donor-message';
message.innerHTML = `
<h4>¡DONACIÓN DE FLORES!</h4>
<h2>${senderName}</h2>
${donorMessage ? `<p>"${donorMessage}"</p>` : ''}
`;
if (isAdmin && tipId) {
const thankBtn = document.createElement('div');
thankBtn.style.marginTop = '15px';
thankBtn.style.pointerEvents = 'auto';
thankBtn.innerHTML = `
<button onclick="thankDonor(${tipId}, this)" style="background: var(--accent-color); color: white; border: none; padding: 10px 20px; border-radius: 50px; font-weight: 800; cursor: pointer; display: flex; align-items: center; gap: 8px; margin: 0 auto; box-shadow: 0 4px 10px rgba(0, 230, 118, 0.3); transition: transform 0.2s;">
<i class="bi bi-heart-fill"></i> Agradecer
</button>
`;
message.appendChild(thankBtn);
}
container.appendChild(message);
setTimeout(() => {
if (message.parentNode) message.remove();
}, 8000);
}
const emojis = ['🌸', '🌹', '🌺', '🌻', '🌼', '🌷', '✨', '💖'];
const count = 30;
@ -4089,11 +4228,90 @@ $twitter_link = "https://twitter.com/";
container.appendChild(flower);
setTimeout(() => flower.remove(), duration * 1000);
setTimeout(() => {
if (flower.parentNode) flower.remove();
}, duration * 1000);
}, i * 100);
}
}
async function thankDonor(tipId, btn) {
if (btn) {
btn.disabled = true;
btn.style.opacity = "0.7";
btn.innerHTML = '<i class="bi bi-hourglass-split"></i> Enviando...';
}
try {
const response = await fetch('api/thank_tip.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tip_id: tipId })
});
const data = await response.json();
if (data.success) {
if (btn) btn.innerHTML = '<i class="bi bi-check-circle-fill"></i> ¡Agradecido!';
} else {
if (btn) {
btn.disabled = false;
btn.style.opacity = "1";
btn.innerHTML = '<i class="bi bi-heart-fill"></i> Agradecer';
alert("Error: " + data.error);
}
}
} catch (e) {
console.error("Error thanking donor:", e);
if (btn) {
btn.disabled = false;
btn.style.opacity = "1";
btn.innerHTML = '<i class="bi bi-heart-fill"></i> Agradecer';
}
}
}
function launchDJThanksCelebration(donorName) {
const container = document.getElementById('celebration-overlay');
const message = document.createElement('div');
message.className = 'donor-message';
message.style.borderColor = '#00e676';
message.style.boxShadow = '0 20px 40px rgba(0, 230, 118, 0.4)';
message.innerHTML = `
<h4 style="color: #00e676;">¡EL DJ TE AGRADECE!</h4>
<h2 style="background: linear-gradient(to right, #ffffff, #00e676); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">${donorName}</h2>
<p>"¡Muchas gracias por tu regalo! ❤️"</p>
`;
container.appendChild(message);
setTimeout(() => {
if (message.parentNode) message.remove();
}, 6000);
// Heart confetti
const duration = 3 * 1000;
const end = Date.now() + duration;
(function frame() {
confetti({
particleCount: 3,
angle: 60,
spread: 55,
origin: { x: 0 },
colors: ['#ff0000', '#ff69b4', '#00e676'],
shapes: ['circle']
});
confetti({
particleCount: 3,
angle: 120,
spread: 55,
origin: { x: 1 },
colors: ['#ff0000', '#ff69b4', '#00e676'],
shapes: ['circle']
});
if (Date.now() < end) {
requestAnimationFrame(frame);
}
}());
}
// Initialize polling
// --- DJ Shoutout Functionality ---
async function adminOpenShoutout() {