This commit is contained in:
66
src/app/api/attendance/me-stats/route.ts
Normal file
66
src/app/api/attendance/me-stats/route.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import prisma from "@/lib/prisma";
|
||||
import { getUserIdFromRequest } from "@/lib/auth";
|
||||
|
||||
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(req: Request) {
|
||||
const userId = getUserIdFromRequest(req);
|
||||
if (!userId) return NextResponse.json({ total: 0, currentStreak: 0, maxStreak: 0 });
|
||||
|
||||
// 총 출석일
|
||||
const total = await prisma.attendance.count({ where: { userId } });
|
||||
|
||||
// 모든 출석일(UTC 자정 기준) 가져와서 streak 계산
|
||||
const rows = await prisma.attendance.findMany({
|
||||
where: { userId },
|
||||
select: { date: true },
|
||||
orderBy: { date: "asc" },
|
||||
});
|
||||
const days = Array.from(new Set(rows.map((r) => toYmdUTC(new Date(r.date))))); // unique, asc
|
||||
|
||||
// 현재 연속 출석
|
||||
let currentStreak = 0;
|
||||
if (days.length > 0) {
|
||||
const set = new Set(days);
|
||||
const now = new Date();
|
||||
let cursor = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 0, 0, 0, 0));
|
||||
while (true) {
|
||||
const ymd = toYmdUTC(cursor);
|
||||
if (set.has(ymd)) {
|
||||
currentStreak += 1;
|
||||
cursor.setUTCDate(cursor.getUTCDate() - 1);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 최대 연속 출석
|
||||
let maxStreak = 0;
|
||||
if (days.length > 0) {
|
||||
// scan through sorted list
|
||||
let localMax = 1;
|
||||
for (let i = 1; i < days.length; i++) {
|
||||
const prev = new Date(days[i - 1] + "T00:00:00.000Z");
|
||||
const cur = new Date(days[i] + "T00:00:00.000Z");
|
||||
const diff = (cur.getTime() - prev.getTime()) / (24 * 60 * 60 * 1000);
|
||||
if (diff === 1) {
|
||||
localMax += 1;
|
||||
} else if (diff > 1) {
|
||||
if (localMax > maxStreak) maxStreak = localMax;
|
||||
localMax = 1;
|
||||
}
|
||||
}
|
||||
if (localMax > maxStreak) maxStreak = localMax;
|
||||
}
|
||||
|
||||
return NextResponse.json({ total, currentStreak, maxStreak });
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user