feat: integrate real data into dashboard
- Created dashboard service with DB queries for users, economy, events - Added client stats provider with 30s caching for Discord metrics - Implemented /api/stats endpoint aggregating all dashboard data - Created useDashboardStats React hook with auto-refresh - Updated Dashboard.tsx to display real data with loading/error states - Added comprehensive test coverage (11 tests passing) - Replaced all mock values with live Discord and database metrics
This commit is contained in:
78
web/src/hooks/use-dashboard-stats.ts
Normal file
78
web/src/hooks/use-dashboard-stats.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
interface DashboardStats {
|
||||
guilds: {
|
||||
count: number;
|
||||
};
|
||||
users: {
|
||||
active: number;
|
||||
total: number;
|
||||
};
|
||||
commands: {
|
||||
total: number;
|
||||
};
|
||||
ping: {
|
||||
avg: number;
|
||||
};
|
||||
economy: {
|
||||
totalWealth: string;
|
||||
avgLevel: number;
|
||||
topStreak: number;
|
||||
};
|
||||
recentEvents: Array<{
|
||||
type: 'success' | 'error' | 'info';
|
||||
message: string;
|
||||
timestamp: string;
|
||||
icon?: string;
|
||||
}>;
|
||||
uptime: number;
|
||||
lastCommandTimestamp: number | null;
|
||||
}
|
||||
|
||||
interface UseDashboardStatsResult {
|
||||
stats: DashboardStats | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom hook to fetch and auto-refresh dashboard statistics
|
||||
* Polls the API every 30 seconds
|
||||
*/
|
||||
export function useDashboardStats(): UseDashboardStatsResult {
|
||||
const [stats, setStats] = useState<DashboardStats | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchStats = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/stats");
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
setStats(data);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch dashboard stats:", err);
|
||||
setError(err instanceof Error ? err.message : "Failed to fetch stats");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Initial fetch
|
||||
fetchStats();
|
||||
|
||||
// Set up polling every 30 seconds
|
||||
const interval = setInterval(fetchStats, 30000);
|
||||
|
||||
// Cleanup on unmount
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
return { stats, loading, error };
|
||||
}
|
||||
Reference in New Issue
Block a user