diff --git a/app/api/leaderboard/route.ts b/app/api/leaderboard/route.ts
new file mode 100644
index 0000000..31a5c89
--- /dev/null
+++ b/app/api/leaderboard/route.ts
@@ -0,0 +1,40 @@
+import { NextResponse } from "next/server";
+import { prisma } from "../../../lib/prisma";
+
+export async function GET() {
+ const users = await prisma.user.findMany({
+ include: { games: true },
+ });
+
+ const rows = users
+ .map((u) => {
+ const all = u.games;
+ const solo = all.filter((g) => g.mode === "solo");
+ const multi = all.filter((g) => g.mode === "multi");
+ const wins = all.filter((g) => g.won);
+ const wonGames = all.filter((g) => g.won && g.clicks > 0);
+ const avgClicks = wonGames.length
+ ? Math.round(wonGames.reduce((s, g) => s + g.clicks, 0) / wonGames.length)
+ : null;
+ const bestTime = wins.length
+ ? Math.min(...wins.map((g) => g.timeSeconds))
+ : null;
+
+ return {
+ id: u.id,
+ name: u.name,
+ totalGames: all.length,
+ wins: wins.length,
+ soloGames: solo.length,
+ soloWins: solo.filter((g) => g.won).length,
+ multiGames: multi.length,
+ multiWins: multi.filter((g) => g.won).length,
+ avgClicks,
+ bestTime,
+ };
+ })
+ .filter((r) => r.totalGames > 0)
+ .sort((a, b) => b.wins - a.wins || b.totalGames - a.totalGames);
+
+ return NextResponse.json(rows);
+}
diff --git a/app/components/HomeScreen.tsx b/app/components/HomeScreen.tsx
index c035543..7122d79 100644
--- a/app/components/HomeScreen.tsx
+++ b/app/components/HomeScreen.tsx
@@ -17,16 +17,20 @@ type HomeScreenProps = {
session: Session | null;
onShowAuth: () => void;
onShowProfile: () => void;
+ onShowLeaderboard: () => void;
};
export function HomeScreen({
playerName, setPlayerName, joinCode, setJoinCode,
error, setError, loading, onCreateRoom, onJoinRoom, onSolo,
- session, onShowAuth, onShowProfile,
+ session, onShowAuth, onShowProfile, onShowLeaderboard,
}: HomeScreenProps) {
return (
+
{session?.user ? (