67 lines
2.0 KiB
TypeScript
67 lines
2.0 KiB
TypeScript
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 });
|
|
}
|
|
|
|
|