diff --git a/src/app/api/ranking/route.ts b/src/app/api/ranking/route.ts new file mode 100644 index 0000000..9e78da1 --- /dev/null +++ b/src/app/api/ranking/route.ts @@ -0,0 +1,27 @@ +import { NextResponse } from "next/server"; +import prisma from "@/lib/prisma"; + +export async function GET(req: Request) { + const { searchParams } = new URL(req.url); + const period = searchParams.get("period") || "monthly"; // daily/weekly/monthly/all + let since: Date | undefined; + const now = new Date(); + if (period === "daily") since = new Date(now.getFullYear(), now.getMonth(), now.getDate()); + else if (period === "weekly") since = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 7); + else if (period === "monthly") since = new Date(now.getFullYear(), now.getMonth(), 1); + + const where = since ? { createdAt: { gte: since } } : {}; + const agg = await prisma.pointTransaction.groupBy({ + by: ["userId"], + where, + _sum: { amount: true }, + orderBy: { _sum: { amount: "desc" } }, + take: 50, + }); + const userIds = agg.map((a) => a.userId); + const users = await prisma.user.findMany({ where: { userId: { in: userIds } }, select: { userId: true, nickname: true } }); + const items = agg.map((a) => ({ userId: a.userId, points: a._sum.amount ?? 0, nickname: users.find((u) => u.userId === a.userId)?.nickname || "" })); + return NextResponse.json({ period, items }); +} + + diff --git a/src/app/ranking/page.tsx b/src/app/ranking/page.tsx new file mode 100644 index 0000000..cb3be54 --- /dev/null +++ b/src/app/ranking/page.tsx @@ -0,0 +1,29 @@ +"use client"; +import useSWR from "swr"; + +const fetcher = (url: string) => fetch(url).then((r) => r.json()); + +export default function RankingPage({ searchParams }: { searchParams?: { period?: string } }) { + const period = searchParams?.period ?? "monthly"; + const { data } = useSWR<{ period: string; items: { userId: string; nickname: string; points: number }[] }>(`/api/ranking?period=${period}`, fetcher); + return ( +
+

회원랭킹

+
+ 일간 + 주간 + 월간 + 전체 +
+
    + {(data?.items ?? []).map((i) => ( +
  1. + {i.nickname} — {i.points}점 +
  2. + ))} +
+
+ ); +} + +