import Link from "next/link"; import { ContentCard, EmptyState, RankBadge } from "@/components/public/ui"; import { avatarImageUrl } from "@/lib/format"; import { prisma } from "@/lib/prisma"; import { siteSettings } from "@/lib/services/site-settings"; export const dynamic = "force-dynamic"; export const metadata = { title: "Leaderboard" }; // AtomCMS-faithful currency type ids (see prisma/schema.prisma UsersCurrency): // Credits = -1 (lives on users.credits), Duckets = 0, Diamonds = 5. const TABS = [ { key: "credits", label: "Credits", coin: "credits" }, { key: "diamonds", label: "Diamonds", coin: "diamonds" }, { key: "duckets", label: "Duckets", coin: "duckets" }, ] as const; type TabKey = (typeof TABS)[number]["key"]; const CURRENCY_TYPE: Record, number> = { diamonds: 5, duckets: 0, }; type Row = { username: string; look: string; value: number }; async function loadCreditsRows(): Promise { try { const users = await prisma.user.findMany({ orderBy: { credits: "desc" }, take: 20, select: { username: true, look: true, credits: true }, }); return users.map((u) => ({ username: u.username, look: u.look, value: u.credits })); } catch { return []; } } async function loadCurrencyRows(type: number): Promise { try { const top = await prisma.usersCurrency.findMany({ where: { type }, orderBy: { amount: "desc" }, take: 20, select: { userId: true, amount: true }, }); if (top.length === 0) return []; const users = await prisma.user.findMany({ where: { id: { in: top.map((t) => t.userId) } }, select: { id: true, username: true, look: true }, }); const byId = new Map(users.map((u) => [u.id, u])); return top .map((t) => { const u = byId.get(t.userId); if (!u) return null; return { username: u.username, look: u.look, value: t.amount }; }) .filter((r): r is Row => r !== null); } catch { return []; } } export default async function LeaderboardPage({ searchParams, }: { searchParams: Promise<{ type?: string }>; }) { const { type } = await searchParams; const active: TabKey = TABS.some((t) => t.key === type) ? (type as TabKey) : "credits"; const activeTab = TABS.find((t) => t.key === active)!; const [rows, imagerBase] = await Promise.all([ active === "credits" ? loadCreditsRows() : loadCurrencyRows(CURRENCY_TYPE[active as Exclude]), siteSettings.get("habbo_imaging_url", "https://www.habbo.com/habbo-imaging/avatarimage"), ]); return (
{TABS.map((t) => ( {t.label} ))}
{rows.length === 0 ? ( No rankings to show yet. ) : ( {rows.map((row, i) => { const avatar = avatarImageUrl(imagerBase ?? "", row.look, { size: "s", headOnly: true, }); return ( ); })}
# Avatar Player {activeTab.label}
{/* eslint-disable-next-line @next/next/no-img-element */} {`${row.username} {row.username} {row.value.toLocaleString()}
)}
); }