feat: Add real activity distribution and stats to admin dashboard
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 / 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
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled

Backend changes:
- Created DashboardModule with controller and service
- Added /admin/dashboard/stats endpoint for aggregated statistics
- Added /admin/dashboard/activity-distribution endpoint for real activity data
- Query activities table to get actual counts by type (feeding, sleep, diaper, etc.)
- Query ai_conversations table for AI query totals

Frontend changes:
- Updated dashboard to fetch stats from new backend endpoint
- Replaced mock activity distribution with real data from database
- Added minWidth: 500px to all cards and charts for consistent layout
- Now displays actual activity counts: 9,965 feedings, 5,727 diapers, 4,633 sleep, etc.
This commit is contained in:
Andrei
2025-10-08 08:04:19 +00:00
parent a295bfc718
commit aca7061851
5 changed files with 128 additions and 29 deletions

View File

@@ -64,16 +64,13 @@ export default function DashboardPage() {
const fetchDashboardData = async () => {
setLoading(true);
try {
// Fetch all users to calculate stats
// Fetch dashboard stats from new endpoint
const statsResponse = await apiClient.get('/admin/dashboard/stats');
// Fetch all users to calculate additional metrics
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) => {
@@ -82,14 +79,14 @@ export default function DashboardPage() {
}).length;
setStats({
totalUsers,
totalFamilies,
totalChildren,
activeUsers,
totalUsers: statsResponse.totalUsers,
totalFamilies: statsResponse.totalFamilies,
totalChildren: statsResponse.totalChildren,
activeUsers: statsResponse.activeUsers,
newUsersToday,
activitiesLogged: 0, // TODO: Implement when tracking endpoints exist
aiQueriesTotal: 0, // TODO: Implement when AI endpoints exist
systemStatus: 'healthy',
activitiesLogged: statsResponse.activitiesLogged,
aiQueriesTotal: statsResponse.aiQueriesTotal,
systemStatus: statsResponse.systemStatus || 'healthy',
});
// Calculate user growth from creation dates
@@ -110,14 +107,9 @@ export default function DashboardPage() {
});
setUserGrowthData(growthData);
// Activity distribution - placeholder until we have real tracking data
setActivityData([
{ 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' },
]);
// Fetch real activity distribution
const activityDistribution = await apiClient.get('/admin/dashboard/activity-distribution');
setActivityData(activityDistribution);
// Get most recent users (last 5)
const sortedUsers = [...users].sort((a: any, b: any) =>
@@ -153,7 +145,7 @@ export default function DashboardPage() {
}, []);
const StatCard = ({ icon, title, value, change, color }: any) => (
<Card sx={{ height: '100%' }}>
<Card sx={{ height: '100%', minWidth: 500 }}>
<CardContent>
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
<Avatar sx={{ bgcolor: `${color}.light`, color: `${color}.main`, mr: 2 }}>
@@ -248,7 +240,7 @@ export default function DashboardPage() {
{/* Charts Row */}
<Grid container spacing={3} sx={{ mb: 3 }}>
<Grid item xs={12} md={8}>
<Paper sx={{ p: 3 }}>
<Paper sx={{ p: 3, minWidth: 500 }}>
<Typography variant="h6" gutterBottom>
User Growth (Last 30 Days)
</Typography>
@@ -270,7 +262,7 @@ export default function DashboardPage() {
</Paper>
</Grid>
<Grid item xs={12} md={4}>
<Paper sx={{ p: 3 }}>
<Paper sx={{ p: 3, minWidth: 500 }}>
<Typography variant="h6" gutterBottom>
Activity Distribution
</Typography>
@@ -300,7 +292,7 @@ export default function DashboardPage() {
{/* Recent Activity and System Status */}
<Grid container spacing={3}>
<Grid item xs={12} md={6}>
<Paper sx={{ p: 3 }}>
<Paper sx={{ p: 3, minWidth: 500 }}>
<Typography variant="h6" gutterBottom>
Recent Users
</Typography>
@@ -329,7 +321,7 @@ export default function DashboardPage() {
</Paper>
</Grid>
<Grid item xs={12} md={6}>
<Paper sx={{ p: 3 }}>
<Paper sx={{ p: 3, minWidth: 500 }}>
<Typography variant="h6" gutterBottom>
System Status
</Typography>