// /components/dashboard/dashboardService.js 'use strict'; const User = require('../users/userModel'); const Professor = require('../professors/professorModel'); const Course = require('../courses/courseModel'); const Session = require('../sessions/sessionModel'); /** * Returns aggregated statistics for the admin dashboard */ const getAdminStats = async () => { const [ totalUsers, activeUsers, totalProfessors, activeProfessors, totalCourses, totalSessions, recentSessions ] = await Promise.all([ User.countDocuments({}), User.countDocuments({ isActive: true }), Professor.countDocuments({}), Professor.countDocuments({ isActive: true }), Course.countDocuments({}), Session.countDocuments({}), Session.find({}) .sort({ day: -1 }) .limit(8) .populate('course', 'title type') .populate('class', 'name') .populate('professor', 'name surname') .lean() ]); // Daily enrollment trend (last 14 days via User.createdAt) const daysBack = 13; const rangeStart = new Date(); rangeStart.setHours(0, 0, 0, 0); rangeStart.setDate(rangeStart.getDate() - daysBack); const dailyUsersRaw = await User.aggregate([ { $match: { createdAt: { $gte: rangeStart } } }, { $group: { _id: { year: { $year: '$createdAt' }, month: { $month: '$createdAt' }, day: { $dayOfMonth: '$createdAt' } }, count: { $sum: 1 } } }, { $sort: { '_id.year': 1, '_id.month': 1, '_id.day': 1 } } ]); // Fill every day in the range so the chart stays continuous const dailyUsers = []; for (let i = 0; i <= daysBack; i += 1) { const date = new Date(rangeStart); date.setDate(rangeStart.getDate() + i); const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); const match = dailyUsersRaw.find( (item) => item._id.year === year && item._id.month === month && item._id.day === day ); dailyUsers.push({ _id: { year, month, day }, date: date.toISOString(), count: match ? match.count : 0 }); } // Daily sessions trend (same window) const dailySessionsRaw = await Session.aggregate([ { $match: { createdAt: { $gte: rangeStart } } }, { $group: { _id: { year: { $year: '$createdAt' }, month: { $month: '$createdAt' }, day: { $dayOfMonth: '$createdAt' } }, count: { $sum: 1 } } }, { $sort: { '_id.year': 1, '_id.month': 1, '_id.day': 1 } } ]); const dailySessions = dailyUsers.map((day) => { const match = dailySessionsRaw.find( (item) => item._id.year === day._id.year && item._id.month === day._id.month && item._id.day === day._id.day ); return { _id: day._id, date: day.date, count: match ? match.count : 0 }; }); return { totals: { users: totalUsers, activeUsers, professors: totalProfessors, activeProfessors, courses: totalCourses, sessions: totalSessions }, recentSessions, charts: { dailyUsers, dailySessions } }; }; module.exports = { getAdminStats };