Autosave: 20260217-171612
This commit is contained in:
parent
4326c4f960
commit
55ebbe45e6
55
admin.php
55
admin.php
@ -29,6 +29,7 @@ $locations = $stmt->fetchAll();
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<style>
|
||||
body { background: #0f172a; color: white; font-family: 'Inter', sans-serif; }
|
||||
.card { background: rgba(30, 41, 59, 0.7); border: 1px solid rgba(255,255,255,0.1); color: white; backdrop-filter: blur(10px); }
|
||||
@ -114,7 +115,18 @@ $locations = $stmt->fetchAll();
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<div class="card p-4">
|
||||
<h5><i class="bi bi-graph-up-arrow text-success"></i> Volumen de Peticiones (Últimas 24h)</h5>
|
||||
<div style="height: 250px;">
|
||||
<canvas id="volumeChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<div class="card p-4">
|
||||
@ -161,6 +173,38 @@ $locations = $stmt->fetchAll();
|
||||
.bindPopup(`<b>${loc.country}</b><br>${loc.count} usuario(s)`);
|
||||
}
|
||||
});
|
||||
|
||||
let volumeChart;
|
||||
function initChart() {
|
||||
const ctx = document.getElementById('volumeChart').getContext('2d');
|
||||
volumeChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: Array.from({length: 24}, (_, i) => `${i}:00`),
|
||||
datasets: [{
|
||||
label: 'Peticiones',
|
||||
data: new Array(24).fill(0),
|
||||
borderColor: '#00e676',
|
||||
backgroundColor: 'rgba(0, 230, 118, 0.1)',
|
||||
borderWidth: 2,
|
||||
fill: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
y: { beginAtZero: true, grid: { color: 'rgba(255,255,255,0.05)' }, ticks: { color: '#94a3b8' } },
|
||||
x: { grid: { display: false }, ticks: { color: '#94a3b8' } }
|
||||
},
|
||||
plugins: {
|
||||
legend: { display: false }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
initChart();
|
||||
|
||||
async function fetchRequests() {
|
||||
const tbody = document.getElementById('requests-body');
|
||||
@ -239,6 +283,15 @@ $locations = $stmt->fetchAll();
|
||||
</div>
|
||||
`).join('') + '</div>';
|
||||
}
|
||||
|
||||
if (data.volume_stats && volumeChart) {
|
||||
const hourlyData = new Array(24).fill(0);
|
||||
data.volume_stats.forEach(stat => {
|
||||
hourlyData[stat.hour] = stat.count;
|
||||
});
|
||||
volumeChart.data.datasets[0].data = hourlyData;
|
||||
volumeChart.update();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching stats:', error);
|
||||
|
||||
@ -65,10 +65,15 @@ if ($method === 'GET') {
|
||||
$stmt = $db->query("SELECT artist, song, COUNT(*) as count FROM song_requests GROUP BY artist, song ORDER BY count DESC LIMIT 5");
|
||||
$top_songs = $stmt->fetchAll();
|
||||
|
||||
// Request volume by hour (last 24 hours)
|
||||
$stmt = $db->query("SELECT HOUR(created_at) as hour, COUNT(*) as count FROM song_requests WHERE created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR) GROUP BY hour ORDER BY hour ASC");
|
||||
$volume_stats = $stmt->fetchAll();
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'top_artists' => $top_artists,
|
||||
'top_songs' => $top_songs
|
||||
'top_songs' => $top_songs,
|
||||
'volume_stats' => $volume_stats
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user