Add Democratic fundraising platform.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
51
src/app/api/leaderboard/route.ts
Normal file
51
src/app/api/leaderboard/route.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
export const revalidate = 0;
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const url = new URL(req.url);
|
||||
const limit = Math.min(parseInt(url.searchParams.get("limit") ?? "25"), 100);
|
||||
|
||||
// Aggregate total donated per user
|
||||
const rows = await prisma.donation.groupBy({
|
||||
by: ["userId"],
|
||||
where: { userId: { not: null } },
|
||||
_sum: { amountUsdCents: true },
|
||||
_count: { id: true },
|
||||
orderBy: { _sum: { amountUsdCents: "desc" } },
|
||||
take: limit,
|
||||
});
|
||||
|
||||
// Fetch display names
|
||||
const userIds = rows.map((r) => r.userId).filter((id): id is string => id != null);
|
||||
const users = await prisma.user.findMany({
|
||||
where: { id: { in: userIds } },
|
||||
select: { id: true, name: true, email: true },
|
||||
});
|
||||
|
||||
const userMap = new Map(users.map(u => [u.id, u]));
|
||||
|
||||
const leaderboard = rows.map((row, idx) => {
|
||||
const uid = row.userId!;
|
||||
const user = userMap.get(uid);
|
||||
// Show name if present, else obfuscate email
|
||||
let displayName = user?.name ?? "Anonymous";
|
||||
// Ghost donors have emails ending in leaderboard.local — show name only
|
||||
// Real donors: show first name + last initial, or truncated email
|
||||
const email = user?.email ?? "";
|
||||
if (!user?.name && !email.endsWith("leaderboard.local")) {
|
||||
const [local] = email.split("@");
|
||||
displayName = local.slice(0, 3) + "***";
|
||||
}
|
||||
return {
|
||||
rank: idx + 1,
|
||||
displayName,
|
||||
totalUsdCents: row._sum.amountUsdCents ?? 0,
|
||||
donationCount: row._count.id,
|
||||
};
|
||||
});
|
||||
|
||||
return NextResponse.json({ leaderboard });
|
||||
}
|
||||
Reference in New Issue
Block a user