import { prisma } from "../prisma"; import { DashboardStats } from "@/types"; /** * Get number of workouts this week (Mon-Sun) */ export async function getWeeklyWorkoutCount(userId: string): Promise { const now = new Date(); const dayOfWeek = now.getDay(); const daysBack = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // Monday is 0 const mondayStart = new Date(now); mondayStart.setDate(mondayStart.getDate() - daysBack); mondayStart.setHours(0, 0, 0, 0); const sundayEnd = new Date(mondayStart); sundayEnd.setDate(sundayEnd.getDate() + 6); sundayEnd.setHours(23, 59, 59, 999); const count = await prisma.workout.count({ where: { userId, date: { gte: mondayStart, lte: sundayEnd, }, }, }); return count; } /** * Get total workouts ever for user */ export async function getTotalWorkoutCount(userId: string): Promise { return prisma.workout.count({ where: { userId }, }); } /** * Get number of workouts this month (1st to end of month) */ export async function getMonthlyWorkoutCount(userId: string): Promise { const now = new Date(); const monthStart = new Date(now.getFullYear(), now.getMonth(), 1); monthStart.setHours(0, 0, 0, 0); const monthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0); monthEnd.setHours(23, 59, 59, 999); return prisma.workout.count({ where: { userId, date: { gte: monthStart, lte: monthEnd, }, }, }); } /** * Get number of workouts this year (Jan 1 to Dec 31) */ export async function getYearlyWorkoutCount(userId: string): Promise { const now = new Date(); const yearStart = new Date(now.getFullYear(), 0, 1); yearStart.setHours(0, 0, 0, 0); const yearEnd = new Date(now.getFullYear(), 11, 31); yearEnd.setHours(23, 59, 59, 999); return prisma.workout.count({ where: { userId, date: { gte: yearStart, lte: yearEnd, }, }, }); } /** * Get current streak (consecutive days with workouts, working backwards from today) */ export async function getCurrentStreak(userId: string): Promise { const workouts = await prisma.workout.findMany({ where: { userId }, select: { date: true }, orderBy: { date: "desc" }, }); if (workouts.length === 0) { return 0; } let streak = 0; let currentDate = new Date(); currentDate.setHours(0, 0, 0, 0); for (const workout of workouts) { const workoutDate = new Date(workout.date); workoutDate.setHours(0, 0, 0, 0); const daysDiff = Math.floor( (currentDate.getTime() - workoutDate.getTime()) / (1000 * 60 * 60 * 24) ); if (daysDiff === streak) { streak++; } else { break; } } return streak; } /** * Get total volume (sum of reps * weight) for this week */ export async function getWeeklyVolume(userId: string): Promise { const now = new Date(); const dayOfWeek = now.getDay(); const daysBack = dayOfWeek === 0 ? 6 : dayOfWeek - 1; const mondayStart = new Date(now); mondayStart.setDate(mondayStart.getDate() - daysBack); mondayStart.setHours(0, 0, 0, 0); const sundayEnd = new Date(mondayStart); sundayEnd.setDate(sundayEnd.getDate() + 6); sundayEnd.setHours(23, 59, 59, 999); const setLogs = await prisma.setLog.findMany({ where: { workout: { userId, date: { gte: mondayStart, lte: sundayEnd, }, }, }, select: { reps: true, weight: true, }, }); const totalVolume = setLogs.reduce((sum, set) => { const reps = set.reps || 0; const weight = set.weight || 0; return sum + reps * weight; }, 0); return totalVolume; } /** * Get all dashboard stats combined */ export async function getDashboardStats(userId: string): Promise { const [ totalWorkouts, _weeklyWorkoutCount, _currentStreak, weeklyVolume, recentWorkouts, ] = await Promise.all([ getTotalWorkoutCount(userId), getWeeklyWorkoutCount(userId), getCurrentStreak(userId), getWeeklyVolume(userId), prisma.workout.findMany({ where: { userId }, include: { setLogs: { include: { exercise: true, }, orderBy: { setNumber: "asc", }, }, }, orderBy: { date: "desc", }, take: 5, }), ]); // Calculate total sets and reps from recent workouts let totalSets = 0; let totalReps = 0; const personalBests: DashboardStats["personalBests"] = []; for (const workout of recentWorkouts) { for (const set of (workout as any).setLogs) { totalSets++; if (set.reps) { totalReps += set.reps; } } } return { totalWorkouts, totalVolume: weeklyVolume, totalSets, totalReps, personalBests, recentWorkouts: recentWorkouts as any, }; }