alejandro-ao's picture
alejandro-ao HF Staff
add some fake data to make it look realistic
0c61018 verified
// Initialize charts
let userChart, revenueChart, performanceChart, activityChart;
document.addEventListener('DOMContentLoaded', () => {
setupCharts();
startDataUpdates();
});
function setupCharts() {
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
labels: {
color: window.matchMedia('(prefers-color-scheme: dark)').matches ? '#fff' : '#000'
}
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'
},
ticks: {
color: window.matchMedia('(prefers-color-scheme: dark)').matches ? '#fff' : '#000'
}
},
x: {
grid: {
color: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'
},
ticks: {
color: window.matchMedia('(prefers-color-scheme: dark)').matches ? '#fff' : '#000'
}
}
}
};
// User Growth Chart
const userCtx = document.getElementById('userChart').getContext('2d');
userChart = new Chart(userCtx, {
type: 'line',
data: {
labels: Array.from({length: 12}, (_, i) => `${i+1}AM`),
datasets: [{
label: 'Active Users',
data: Array(12).fill(0).map((_,i) => {
const hourFactor = Math.sin((i / 11) * Math.PI) * 0.5 + 0.7;
return Math.floor(3000 + (hourFactor * 2000) + Math.random() * 500 - 250);
}),
borderColor: '#6366f1',
backgroundColor: 'rgba(99, 102, 241, 0.1)',
tension: 0.4,
fill: true
}]
},
options: chartOptions
});
// Revenue Chart
const revenueCtx = document.getElementById('revenueChart').getContext('2d');
revenueChart = new Chart(revenueCtx, {
type: 'doughnut',
data: {
labels: ['Subscriptions', 'Ads', 'Merchandise', 'Services'],
datasets: [{
data: [35, 25, 20, 20].map(v => v + Math.floor(Math.random() * 10 - 5)),
backgroundColor: [
'#6366f1',
'#8b5cf6',
'#ec4899',
'#f43f5e'
],
borderWidth: 0
}]
},
options: {
...chartOptions,
cutout: '70%'
}
});
// Performance Chart
const performanceCtx = document.getElementById('performanceChart').getContext('2d');
performanceChart = new Chart(performanceCtx, {
type: 'bar',
data: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
datasets: [
{
label: 'Page Load (ms)',
data: Array(7).fill(0).map(() => 100 + Math.floor(Math.random() * 300)),
backgroundColor: '#6366f1'
},
{
label: 'API Response (ms)',
data: Array(7).fill(0).map(() => 50 + Math.floor(Math.random() * 150)),
backgroundColor: '#8b5cf6'
}
]
},
options: chartOptions
});
// Activity Chart
const activityCtx = document.getElementById('activityChart').getContext('2d');
activityChart = new Chart(activityCtx, {
type: 'line',
data: {
labels: Array.from({length: 24}, (_, i) => i),
datasets: [
{
label: 'API Calls',
data: Array(24).fill(0).map((_, i) => {
const isDaytime = i >= 9 && i < 18;
const base = isDaytime ? 800 : 300;
const hourFactor = Math.sin((i / 24) * Math.PI * 1.5) * (isDaytime ? 400 : 150);
const noise = Math.random() * 150 - 75;
return Math.max(100, base + hourFactor + noise);
}),
borderColor: '#6366f1',
backgroundColor: 'rgba(99, 102, 241, 0.1)',
tension: 0.3,
fill: true
}
]
},
options: chartOptions
});
}
function startDataUpdates() {
// Update metric cards every 3 seconds
setInterval(() => {
const cards = document.querySelectorAll('metrics-card');
const now = new Date();
const hour = now.getHours();
// Active Users - follows daily pattern with peak around 2PM
const userBase = hour < 6 ? 2000 : hour < 12 ? 4000 : hour < 18 ? 6000 : 3000;
const users = userBase + Math.floor(Math.random() * 500 - 250);
const userChange = (Math.random() > 0.6 ? 1 : -1) * (0.5 + Math.random() * 2);
cards[0].setAttribute('value', users.toLocaleString());
cards[0].setAttribute('change', userChange.toFixed(1));
// Conversion Rate - higher during business hours
const conversionBase = hour >= 9 && hour < 17 ? 3.5 : 1.8;
const conversion = (conversionBase + Math.random() * 0.8 - 0.4).toFixed(2);
const conversionChange = (Math.random() * 0.4 - 0.2).toFixed(2);
cards[1].setAttribute('value', conversion + '%');
cards[1].setAttribute('change', conversionChange);
// API Latency - degrades slightly during peak hours
const latencyBase = hour >= 10 && hour < 16 ? 80 : 40;
const latency = Math.floor(latencyBase + Math.random() * 30);
const latencyChange = (Math.random() > 0.3 ? 1 : -1) * (1 + Math.random() * 4);
cards[2].setAttribute('value', latency + 'ms');
cards[2].setAttribute('change', latencyChange.toFixed(1));
// Revenue Today - follows similar pattern to users but with larger random fluctuations
const revenueBase = hour < 6 ? 8000 : hour < 12 ? 12000 : hour < 18 ? 15000 : 9000;
const revenue = revenueBase + Math.floor(Math.random() * 3000 - 1500);
const revenueChange = (Math.random() > 0.5 ? 1 : -1) * (2 + Math.random() * 5);
cards[3].setAttribute('value', '// Update charts with new data points
updateCharts();
}, 3000);
}
function updateCharts() {
// User Chart - follows daily pattern with realistic variations
const userData = userChart.data.datasets[0].data;
userData.shift();
const userTrend = hour < 6 ? 0.8 : hour < 12 ? 1.2 : hour < 18 ? 1.5 : 0.9;
userData.push(Math.max(0, userData[userData.length-1] * (0.98 + Math.random() * 0.04) * userTrend));
userChart.update();
// Revenue Chart - more stable proportions with slight variations
revenueChart.data.datasets[0].data = [30, 25, 25, 20].map(v => v * (0.95 + Math.random() * 0.1));
revenueChart.update();
// Performance Chart - weekday patterns with better/worse performance
const weekday = now.getDay();
const isWeekday = weekday > 0 && weekday < 6;
performanceChart.data.datasets[0].data = Array(7).fill(0).map((_,i) =>
isWeekday ? 80 + Math.floor(Math.random() * 120) : 60 + Math.floor(Math.random() * 80));
performanceChart.data.datasets[1].data = Array(7).fill(0).map((_,i) =>
isWeekday ? 40 + Math.floor(Math.random() * 70) : 30 + Math.floor(Math.random() * 40));
performanceChart.update();
// Activity Chart - more realistic API call patterns
const activityData = activityChart.data.datasets[0].data;
activityData.shift();
const activityTrend = hour < 6 ? 0.7 : hour < 9 ? 0.9 : hour < 17 ? 1.3 : 1.0;
const newActivity = Math.max(100, activityData[activityData.length-1] * (0.97 + Math.random() * 0.06) * activityTrend);
activityData.push(newActivity);
activityChart.update();
}
// Handle dark mode changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
document.documentElement.classList.toggle('dark', e.matches);
setupCharts();
}); + revenue.toLocaleString());
cards[3].setAttribute('change', revenueChange.toFixed(1));
// Update charts with new data points
updateCharts();
}, 3000);
}
function updateCharts() {
// User Chart - add new point and remove oldest
const userData = userChart.data.datasets[0].data;
userData.shift();
userData.push(Math.floor(Math.random() * 5000));
userChart.update();
// Revenue Chart - update values with slight variations
revenueChart.data.datasets[0].data = [35, 25, 20, 20].map(v => v + Math.floor(Math.random() * 10 - 5));
revenueChart.update();
// Performance Chart - update with new random values
performanceChart.data.datasets[0].data = Array(7).fill(0).map(() => 100 + Math.floor(Math.random() * 300));
performanceChart.data.datasets[1].data = Array(7).fill(0).map(() => 50 + Math.floor(Math.random() * 150));
performanceChart.update();
// Activity Chart - shift data and add new point
const activityData = activityChart.data.datasets[0].data;
activityData.shift();
const lastValue = activityData[activityData.length - 1];
activityData.push(Math.max(0, lastValue + (Math.random() * 100 - 50)));
activityChart.update();
}
// Handle dark mode changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
document.documentElement.classList.toggle('dark', e.matches);
setupCharts();
});