diff --git a/src/app/rankings/RankingsClient.tsx b/src/app/rankings/RankingsClient.tsx new file mode 100644 index 0000000..1e6c304 --- /dev/null +++ b/src/app/rankings/RankingsClient.tsx @@ -0,0 +1,241 @@ +"use client" + +import { useState } from "react" +import Link from "next/link" + +// Define the Player type with all rating relationships +interface PlayerWithRatings { + id: number + name: string + currentElo: number + gamesPlayed: number + wins: number + losses: number + eloRating: { rating: number; gamesPlayed: number; wins: number; losses: number } | null + glicko2Rating: { rating: number; gamesPlayed: number; wins: number; losses: number } | null + openSkillRating: { rating: number; gamesPlayed: number; wins: number; losses: number } | null +} + +export default function RankingsClient({ players }: { players: PlayerWithRatings[] }) { + const [activeTab, setActiveTab] = useState<"elo" | "openskill" | "glicko2">("elo") + + return ( + <> + {/* Tab Navigation */} +
+ +
+ + {/* Elo Rating Tab */} + {activeTab === "elo" && ( +
+

+ Elo Rating Rankings +

+ + + + + + + + + + + + {players.map((player, index) => ( + + + + + + + + ))} + +
+ Rank + + Player + + Elo Rating + + Games Played + + Win Rate +
+ {index + 1} + + + {player.name} + + + {player.eloRating?.rating ?? player.currentElo} + + {player.gamesPlayed} + + {player.gamesPlayed > 0 + ? `${((player.wins / player.gamesPlayed) * 100).toFixed(1)}%` + : "N/A"} +
+
+ )} + + {/* OpenSkill Rating Tab */} + {activeTab === "openskill" && ( +
+

+ OpenSkill Rating Rankings +

+ + + + + + + + + + + + {players + .filter(p => p.openSkillRating) + .sort((a, b) => (b.openSkillRating?.rating ?? 0) - (a.openSkillRating?.rating ?? 0)) + .map((player, index) => ( + + + + + + + + ))} + +
+ Rank + + Player + + OpenSkill Rating + + Games Played + + Win Rate +
+ {index + 1} + + + {player.name} + + + {player.openSkillRating?.rating?.toFixed(1) ?? 'N/A'} + + {player.openSkillRating?.gamesPlayed ?? 0} + + {player.openSkillRating && player.openSkillRating.gamesPlayed > 0 + ? `${((player.openSkillRating.wins / player.openSkillRating.gamesPlayed) * 100).toFixed(1)}%` + : "N/A"} +
+
+ )} + + {/* Glicko2 Rating Tab */} + {activeTab === "glicko2" && ( +
+

+ Glicko2 Rating Rankings +

+ + + + + + + + + + + + {players + .filter(p => p.glicko2Rating) + .sort((a, b) => (b.glicko2Rating?.rating ?? 0) - (a.glicko2Rating?.rating ?? 0)) + .map((player, index) => ( + + + + + + + + ))} + +
+ Rank + + Player + + Glicko2 Rating + + Games Played + + Win Rate +
+ {index + 1} + + + {player.name} + + + {player.glicko2Rating?.rating?.toFixed(1) ?? 'N/A'} + + {player.glicko2Rating?.gamesPlayed ?? 0} + + {player.glicko2Rating && player.glicko2Rating.gamesPlayed > 0 + ? `${((player.glicko2Rating.wins / player.glicko2Rating.gamesPlayed) * 100).toFixed(1)}%` + : "N/A"} +
+
+ )} + + ) +} diff --git a/src/app/rankings/page.tsx b/src/app/rankings/page.tsx index 39151a6..8288561 100644 --- a/src/app/rankings/page.tsx +++ b/src/app/rankings/page.tsx @@ -1,15 +1,18 @@ import { prisma } from "@/lib/prisma" import Navigation from "@/components/Navigation" -import Link from "next/link" +import RankingsClient from "./RankingsClient" export default async function RankingsPage() { - // Fetch players ordered by Elo rating + // Fetch players with all rating systems const players = await prisma.player.findMany({ orderBy: { currentElo: "desc" }, take: 50, include: { partnershipStats: true, partnershipStats2: true, + eloRating: true, + glicko2Rating: true, + openSkillRating: true, }, }) @@ -23,57 +26,7 @@ export default async function RankingsPage() { Player Rankings -
- - - - - - - - - - - - {players.map((player, index) => ( - - - - - - - - ))} - -
- Rank - - Player - - Elo Rating - - Games Played - - Win Rate -
- {index + 1} - - - {player.name} - - - {player.currentElo} - - {player.gamesPlayed} - - {player.gamesPlayed > 0 - ? `${((player.wins / player.gamesPlayed) * 100).toFixed(1)}%` - : "N/A"} -
-
+