'use client'; import { useState, useEffect } from 'react'; import { Typography, Box, Breadcrumbs, Link, Card, CardContent, Grid, FormControl, InputLabel, Select, MenuItem, CircularProgress, Alert, Chip, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Avatar } from '@mui/material'; import { Home, Analytics, People, TrendingUp, Schedule, Assignment } from '@mui/icons-material'; import { LineChart, Line, AreaChart, Area, BarChart, Bar, PieChart, Pie, Cell, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; interface UserAnalyticsData { period: number; timeline: { registrations: Array<{ date: string; registrations: number }>; }; activity: { patterns: Array<{ id: string; email: string; name: string | null; role: string; createdAt: string; lastLoginAt: string | null; _count: { chatConversations: number; prayerRequests: number; bookmarks: number; notes: number; }; }>; mostActive: Array<{ id: string; email: string; name: string | null; role: string; totalActivity: number; _count: { chatConversations: number; prayerRequests: number; bookmarks: number; notes: number; }; }>; }; retention: { rate: number; newUsers: number; activeUsers: number; }; engagement: { featureUsage: { chat: number; prayers: number; bookmarks: number; notes: number; }; avgSessionLength: number; avgMessagesPerSession: number; }; demographics: Array<{ role: string; _count: { role: number }; _min: { createdAt: string }; _max: { createdAt: string }; }>; } const COLORS = ['#8884d8', '#82ca9d', '#ffc658', '#ff7300', '#0088fe', '#00c49f']; export default function UserAnalyticsPage() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [period, setPeriod] = useState('30'); useEffect(() => { const fetchUserAnalytics = async () => { setLoading(true); try { const response = await fetch(`/api/admin/analytics/users?period=${period}`, { credentials: 'include' }); if (response.ok) { const analyticsData = await response.json(); setData(analyticsData); } else { setError('Failed to load user analytics data'); } } catch (error) { setError('Network error loading user analytics'); } finally { setLoading(false); } }; fetchUserAnalytics(); }, [period]); if (loading) { return ( ); } if (error) { return ( {error} ); } if (!data) return null; const featureUsageData = Object.entries(data.engagement.featureUsage).map(([key, value]) => ({ name: key.charAt(0).toUpperCase() + key.slice(1), value })); return ( {/* Breadcrumbs */} Admin Analytics User Analytics {/* Page Header */} User Analytics Detailed insights into user behavior, engagement, and retention Time Period {/* Key Metrics */} Retention Rate {data.retention.rate}% Avg Session (min) {data.engagement.avgSessionLength} Avg Messages/Session {data.engagement.avgMessagesPerSession} Active/New Users {data.retention.activeUsers}/{data.retention.newUsers} {/* User Registration Timeline */} User Registration Timeline {/* Feature Usage Distribution */} Feature Usage Distribution `${name} ${(percent * 100).toFixed(0)}%`} > {featureUsageData.map((entry, index) => ( ))} {/* Most Active Users */} Most Active Users User Role Total Activity {data.activity.mostActive.slice(0, 10).map((user) => ( {(user.name || user.email)[0].toUpperCase()} {user.name || 'Unknown User'} {user.email} {user.totalActivity} {user._count.chatConversations}c {user._count.prayerRequests}p {user._count.bookmarks}b ))}
{/* User Demographics */} User Demographics by Role Role Count First User Latest User {data.demographics.map((demo) => ( {demo._count.role} {new Date(demo._min.createdAt).toLocaleDateString()} {new Date(demo._max.createdAt).toLocaleDateString()} ))}
); }