'use client'; import { useState, useEffect } from 'react'; import { Game, User, fetchGames, fetchUsers, getDisplayGameName } from '../utils/api'; import Link from 'next/link'; import { Line, Bar } from 'react-chartjs-2'; import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, BarElement, Title, Tooltip, Legend } from 'chart.js'; ChartJS.register( CategoryScale, LinearScale, PointElement, LineElement, BarElement, Title, Tooltip, Legend ); type TimeRange = '7d' | '30d' | '90d'; export default function Dashboard() { const [users, setUsers] = useState([]); const [games, setGames] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [gameTimeRange, setGameTimeRange] = useState('30d'); useEffect(() => { const loadData = async () => { try { const [gamesData, usersData] = await Promise.all([ fetchGames(), fetchUsers() ]); setGames(gamesData); setUsers(usersData); } catch (err) { setError('Failed to load data. Please try again later.'); console.error('Error loading data:', err); } finally { setLoading(false); } }; loadData(); }, []); const getDaysFromTimeRange = (range: TimeRange): number => { switch (range) { case '7d': return 7; case '30d': return 30; case '90d': return 90; } }; const getGameCountData = () => { const days = getDaysFromTimeRange(gameTimeRange); const lastDays = Array.from({ length: days }, (_, i) => { const date = new Date(); date.setDate(date.getDate() - i); return date.toISOString().split('T')[0]; }).reverse(); const gameCounts = lastDays.map(date => { return games.filter(game => { try { const gameDate = new Date(game.ended_time).toISOString().split('T')[0]; return gameDate === date; } catch (err) { console.error('Error parsing date:', err); return false; } }).length; }); return { labels: lastDays.map(date => new Date(date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })), datasets: [ { label: 'Games per Day', data: gameCounts, borderColor: '#FFA500', backgroundColor: 'rgba(255, 165, 0, 0.2)', tension: 0.4, fill: true } ] }; }; const getGamePopularityData = () => { const gameTypes = Array.from(new Set(games.map(game => game.game))); const gameCounts = gameTypes.map(type => ({ type, displayName: getDisplayGameName(type), count: games.filter(game => game.game === type).length })).sort((a, b) => b.count - a.count); return { labels: gameCounts.map(game => game.displayName), datasets: [ { label: 'Games Played', data: gameCounts.map(game => game.count), backgroundColor: 'rgba(255, 165, 0, 0.7)', borderColor: '#FFA500', borderWidth: 1 } ] }; }; const chartOptions = { responsive: true, plugins: { legend: { display: false, labels: { color: '#ffffff' } }, tooltip: { titleColor: '#ffffff', bodyColor: '#ffffff', backgroundColor: 'rgba(0, 0, 0, 0.8)', borderColor: 'rgba(255, 255, 255, 0.1)', borderWidth: 1 } }, scales: { y: { beginAtZero: true, grid: { color: 'rgba(255, 255, 255, 0.1)' }, ticks: { color: '#ffffff' } }, x: { grid: { color: 'rgba(255, 255, 255, 0.1)' }, ticks: { color: '#ffffff' } } } }; const barChartOptions = { responsive: true, plugins: { legend: { display: false, labels: { color: '#ffffff' } }, tooltip: { titleColor: '#ffffff', bodyColor: '#ffffff', backgroundColor: 'rgba(0, 0, 0, 0.8)', borderColor: 'rgba(255, 255, 255, 0.1)', borderWidth: 1 } }, scales: { y: { beginAtZero: true, grid: { color: 'rgba(255, 255, 255, 0.1)' }, ticks: { color: '#ffffff' } }, x: { grid: { color: 'rgba(255, 255, 255, 0.1)' }, ticks: { color: '#ffffff' } } } }; const TimeRangeButton = ({ range, currentRange, onChange }: { range: TimeRange; currentRange: TimeRange; onChange: (range: TimeRange) => void; }) => ( ); if (loading) { return (
Loading...
); } if (error) { return (
{error}
); } return (
{/* Users Card */}

Users - {users.length}

View All →
{/* Game Count Card */}

Games - {games.length}

View All →
{/* Game Popularity Card */}

Game Popularity

); }