Add admin study user enrollment list

This commit is contained in:
nmemmert
2026-05-21 12:08:15 -04:00
parent 376088a52b
commit 74e9f57ea5
2 changed files with 56 additions and 0 deletions
+24
View File
@@ -2931,6 +2931,29 @@ app.get('/api/admin-stats', requireAdminAuth, (_req, res) => {
count: enrollmentCountsBySlug[study.slug] ?? 0, count: enrollmentCountsBySlug[study.slug] ?? 0,
})) }))
.sort((a, b) => b.count - a.count) .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 enrolledUsers = studyUsers.filter(user => (user.enrolledStudySlugs?.length ?? 0) > 0).length
const totalEnrollments = Object.values(enrollmentCountsBySlug).reduce((sum, count) => sum + count, 0) const totalEnrollments = Object.values(enrollmentCountsBySlug).reduce((sum, count) => sum + count, 0)
@@ -2978,6 +3001,7 @@ app.get('/api/admin-stats', requireAdminAuth, (_req, res) => {
enrolledUsers, enrolledUsers,
totalEnrollments, totalEnrollments,
enrollmentsByStudy, enrollmentsByStudy,
users,
}, },
}) })
}) })
+32
View File
@@ -74,6 +74,12 @@ export interface AdminStats {
enrolledUsers: number enrolledUsers: number
totalEnrollments: number totalEnrollments: number
enrollmentsByStudy: Array<{ slug: string; title: string; count: 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) {
} }
</div> </div>
</div> </div>
<div className="admin-dashboard-activity" style={{ marginTop: '1rem' }}>
<div className="admin-dashboard-activity-col" style={{ gridColumn: '1 / -1' }}>
<h3 className="admin-dashboard-activity-heading">Study Users &amp; Enrollments</h3>
{stats?.studyEnrollment?.users?.length
? (
<div className="admin-dashboard-feed">
{stats.studyEnrollment.users.map(user => (
<div key={user.id} className="admin-dashboard-feed-item">
<div className="admin-dashboard-feed-meta">
<strong>{user.displayName || user.username}</strong>
{user.displayName && <span className="admin-dashboard-feed-email">{user.username}</span>}
</div>
<div className="admin-dashboard-feed-preview">
{user.enrolledStudies.length
? `Enrolled in: ${user.enrolledStudies.map(study => study.title).join(', ')}`
: 'Not enrolled in any studies yet.'}
</div>
</div>
))}
</div>
)
: <p className="admin-stats-note">No study users yet.</p>
}
</div>
</div>
</section> </section>
) )
})()} })()}