import { NextResponse } from "next/server"; import prisma from "@/lib/prisma"; function toYmdUTC(d: Date): string { const yy = d.getUTCFullYear(); const mm = String(d.getUTCMonth() + 1).padStart(2, "0"); const dd = String(d.getUTCDate()).padStart(2, "0"); return `${yy}-${mm}-${dd}`; } export async function GET() { // 전체 출석 누적 상위 (Top 10) const overallGroups = await prisma.attendance.groupBy({ by: ["userId"], _count: { _all: true }, orderBy: { _count: { _all: "desc" } }, take: 20, }); const overallUserIds = overallGroups.map((g) => g.userId); const overallUsers = await prisma.user.findMany({ where: { userId: { in: overallUserIds } }, select: { userId: true, nickname: true, profileImage: true, grade: true }, }); const userMeta = new Map(overallUsers.map((u) => [u.userId, u])); const overall = overallGroups.map((g) => ({ userId: g.userId, nickname: userMeta.get(g.userId)?.nickname ?? "회원", count: g._count._all, profileImage: userMeta.get(g.userId)?.profileImage ?? null, grade: userMeta.get(g.userId)?.grade ?? 0, })); // 연속 출석 상위 (Top 10, 현재 연속 기준) const now = new Date(); const todayUTC = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 0, 0, 0, 0)); const past = new Date(todayUTC); past.setUTCDate(past.getUTCDate() - 60); // 최근 60일 데이터만으로 streak 계산 const recent = await prisma.attendance.findMany({ where: { date: { gte: past } }, select: { userId: true, date: true }, orderBy: { userId: "asc" }, }); const map = new Map>(); for (const r of recent) { const set = map.get(r.userId) ?? new Set(); set.add(toYmdUTC(new Date(r.date))); map.set(r.userId, set); } const streakArr: { userId: string; streak: number }[] = []; for (const [userId, set] of map.entries()) { let streak = 0; let cursor = new Date(todayUTC); while (streak < 60) { const ymd = toYmdUTC(cursor); if (set.has(ymd)) { streak += 1; cursor.setUTCDate(cursor.getUTCDate() - 1); } else { break; } } if (streak > 0) streakArr.push({ userId, streak }); } streakArr.sort((a, b) => b.streak - a.streak); const topStreak = streakArr.slice(0, 20); const streakUserIds = topStreak.map((s) => s.userId); const streakUsers = await prisma.user.findMany({ where: { userId: { in: streakUserIds } }, select: { userId: true, nickname: true, profileImage: true, grade: true }, }); const streakMeta = new Map(streakUsers.map((u) => [u.userId, u])); const streak = topStreak.map((s) => ({ userId: s.userId, nickname: streakMeta.get(s.userId)?.nickname ?? "회원", streak: s.streak, profileImage: streakMeta.get(s.userId)?.profileImage ?? null, grade: streakMeta.get(s.userId)?.grade ?? 0, })); return NextResponse.json({ overall, streak }); }