feat: Update dashboard to display real data from database
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
- Replaced mock data with actual API calls to /admin/users - Calculate real stats: totalUsers, activeUsers, totalFamilies, totalChildren - Generate user growth chart from actual user creation dates - Display top 5 most recent users sorted by creation date - Added TODO comments for activity tracking and AI stats (endpoints don't exist yet)
This commit is contained in:
@@ -64,86 +64,85 @@ export default function DashboardPage() {
|
||||
const fetchDashboardData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
// Simulate API calls - replace with actual calls
|
||||
const analyticsData = await apiClient.getAnalytics();
|
||||
const growthData = await apiClient.getUserGrowth();
|
||||
const activityStats = await apiClient.getActivityStats();
|
||||
// Fetch all users to calculate stats
|
||||
const usersResponse = await apiClient.get('/admin/users');
|
||||
const users = usersResponse.users || [];
|
||||
|
||||
// Calculate real stats from user data
|
||||
const totalUsers = users.length;
|
||||
const activeUsers = users.filter((u: any) => u.emailVerified).length;
|
||||
const totalFamilies = users.reduce((sum: number, u: any) => sum + (u.familyCount || 0), 0);
|
||||
const totalChildren = users.reduce((sum: number, u: any) => sum + (u.childrenCount || 0), 0);
|
||||
|
||||
// Calculate users created today
|
||||
const today = startOfDay(new Date());
|
||||
const newUsersToday = users.filter((u: any) => {
|
||||
const createdAt = new Date(u.createdAt);
|
||||
return createdAt >= today;
|
||||
}).length;
|
||||
|
||||
// Mock data for now - replace with actual API response
|
||||
setStats({
|
||||
totalUsers: 1250,
|
||||
totalFamilies: 420,
|
||||
totalChildren: 680,
|
||||
activeUsers: 890,
|
||||
newUsersToday: 23,
|
||||
activitiesLogged: 15420,
|
||||
aiQueriesTotal: 3250,
|
||||
totalUsers,
|
||||
totalFamilies,
|
||||
totalChildren,
|
||||
activeUsers,
|
||||
newUsersToday,
|
||||
activitiesLogged: 0, // TODO: Implement when tracking endpoints exist
|
||||
aiQueriesTotal: 0, // TODO: Implement when AI endpoints exist
|
||||
systemStatus: 'healthy',
|
||||
});
|
||||
|
||||
// Mock user growth data
|
||||
const mockGrowthData = Array.from({ length: 30 }, (_, i) => {
|
||||
// Calculate user growth from creation dates
|
||||
const growthMap = new Map<string, number>();
|
||||
users.forEach((u: any) => {
|
||||
const date = format(new Date(u.createdAt), 'MMM dd');
|
||||
growthMap.set(date, (growthMap.get(date) || 0) + 1);
|
||||
});
|
||||
|
||||
const growthData = Array.from({ length: 30 }, (_, i) => {
|
||||
const date = subDays(new Date(), 29 - i);
|
||||
const dateKey = format(date, 'MMM dd');
|
||||
return {
|
||||
date: format(date, 'MMM dd'),
|
||||
users: Math.floor(Math.random() * 50) + 20,
|
||||
activities: Math.floor(Math.random() * 200) + 100,
|
||||
date: dateKey,
|
||||
users: growthMap.get(dateKey) || 0,
|
||||
activities: 0, // TODO: Add when activity data available
|
||||
};
|
||||
});
|
||||
setUserGrowthData(mockGrowthData);
|
||||
setUserGrowthData(growthData);
|
||||
|
||||
// Mock activity distribution
|
||||
// Activity distribution - placeholder until we have real tracking data
|
||||
setActivityData([
|
||||
{ name: 'Feeding', value: 4500, color: '#FF8B7D' },
|
||||
{ name: 'Sleep', value: 3200, color: '#FFB5A0' },
|
||||
{ name: 'Diapers', value: 2800, color: '#FFD4CC' },
|
||||
{ name: 'Milestones', value: 1200, color: '#81C784' },
|
||||
{ name: 'Other', value: 3720, color: '#FFB74D' },
|
||||
{ name: 'Feeding', value: 0, color: '#FF8B7D' },
|
||||
{ name: 'Sleep', value: 0, color: '#FFB5A0' },
|
||||
{ name: 'Diapers', value: 0, color: '#FFD4CC' },
|
||||
{ name: 'Milestones', value: 0, color: '#81C784' },
|
||||
{ name: 'Other', value: 0, color: '#FFB74D' },
|
||||
]);
|
||||
|
||||
// Mock recent users
|
||||
setRecentUsers([
|
||||
{ id: 1, name: 'Sarah Johnson', email: 'sarah@example.com', joinedAt: new Date() },
|
||||
{ id: 2, name: 'Mike Chen', email: 'mike@example.com', joinedAt: new Date() },
|
||||
{ id: 3, name: 'Emma Davis', email: 'emma@example.com', joinedAt: new Date() },
|
||||
]);
|
||||
// Get most recent users (last 5)
|
||||
const sortedUsers = [...users].sort((a: any, b: any) =>
|
||||
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
||||
).slice(0, 5);
|
||||
|
||||
setRecentUsers(sortedUsers.map((u: any) => ({
|
||||
id: u.id,
|
||||
name: u.name,
|
||||
email: u.email,
|
||||
joinedAt: new Date(u.createdAt),
|
||||
})));
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch dashboard data:', error);
|
||||
// Use mock data even on error for development
|
||||
// Set empty/error state
|
||||
setStats({
|
||||
totalUsers: 1250,
|
||||
totalFamilies: 420,
|
||||
totalChildren: 680,
|
||||
activeUsers: 890,
|
||||
newUsersToday: 23,
|
||||
activitiesLogged: 15420,
|
||||
aiQueriesTotal: 3250,
|
||||
systemStatus: 'healthy',
|
||||
totalUsers: 0,
|
||||
totalFamilies: 0,
|
||||
totalChildren: 0,
|
||||
activeUsers: 0,
|
||||
newUsersToday: 0,
|
||||
activitiesLogged: 0,
|
||||
aiQueriesTotal: 0,
|
||||
systemStatus: 'error',
|
||||
});
|
||||
|
||||
const mockGrowthData = Array.from({ length: 30 }, (_, i) => {
|
||||
const date = subDays(new Date(), 29 - i);
|
||||
return {
|
||||
date: format(date, 'MMM dd'),
|
||||
users: Math.floor(Math.random() * 50) + 20,
|
||||
activities: Math.floor(Math.random() * 200) + 100,
|
||||
};
|
||||
});
|
||||
setUserGrowthData(mockGrowthData);
|
||||
|
||||
setActivityData([
|
||||
{ name: 'Feeding', value: 4500, color: '#FF8B7D' },
|
||||
{ name: 'Sleep', value: 3200, color: '#FFB5A0' },
|
||||
{ name: 'Diapers', value: 2800, color: '#FFD4CC' },
|
||||
{ name: 'Milestones', value: 1200, color: '#81C784' },
|
||||
{ name: 'Other', value: 3720, color: '#FFB74D' },
|
||||
]);
|
||||
|
||||
setRecentUsers([
|
||||
{ id: 1, name: 'Sarah Johnson', email: 'sarah@example.com', joinedAt: new Date() },
|
||||
{ id: 2, name: 'Mike Chen', email: 'mike@example.com', joinedAt: new Date() },
|
||||
{ id: 3, name: 'Emma Davis', email: 'emma@example.com', joinedAt: new Date() },
|
||||
]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user