diff --git a/server.js b/server.js index dfba3b1..7f3b7cb 100644 --- a/server.js +++ b/server.js @@ -2931,6 +2931,29 @@ app.get('/api/admin-stats', requireAdminAuth, (_req, res) => { count: enrollmentCountsBySlug[study.slug] ?? 0, })) .sort((a, b) => b.count - a.count) + const studyCatalogBySlug = new Map(getStudyCatalog().map(study => [study.slug, study])) + const users = studyUsers + .map(user => { + const enrolledStudySlugs = Array.isArray(user?.enrolledStudySlugs) ? user.enrolledStudySlugs : [] + const enrolledStudies = enrolledStudySlugs + .map(slug => { + const study = studyCatalogBySlug.get(slug) + if (!study) return null + return { slug: study.slug, title: study.title } + }) + .filter(Boolean) + + return { + id: user.id, + username: user.username, + displayName: user.displayName ?? '', + enrolledStudies, + } + }) + .sort((a, b) => { + if (b.enrolledStudies.length !== a.enrolledStudies.length) return b.enrolledStudies.length - a.enrolledStudies.length + return a.username.localeCompare(b.username) + }) const enrolledUsers = studyUsers.filter(user => (user.enrolledStudySlugs?.length ?? 0) > 0).length const totalEnrollments = Object.values(enrollmentCountsBySlug).reduce((sum, count) => sum + count, 0) @@ -2978,6 +3001,7 @@ app.get('/api/admin-stats', requireAdminAuth, (_req, res) => { enrolledUsers, totalEnrollments, enrollmentsByStudy, + users, }, }) }) diff --git a/src/AdminPage.tsx b/src/AdminPage.tsx index 4339bb3..37bf577 100644 --- a/src/AdminPage.tsx +++ b/src/AdminPage.tsx @@ -74,6 +74,12 @@ export interface AdminStats { enrolledUsers: number totalEnrollments: number enrollmentsByStudy: Array<{ slug: string; title: string; count: number }> + users: Array<{ + id: string + username: string + displayName: string + enrolledStudies: Array<{ slug: string; title: string }> + }> } } @@ -2332,6 +2338,32 @@ export default function AdminPage({ content, onSave, onLogout }: Props) { } + +
No study users yet.
+ } +