diff --git a/app/api/leaderboard/route.ts b/app/api/leaderboard/route.ts index 538e929..4797739 100644 --- a/app/api/leaderboard/route.ts +++ b/app/api/leaderboard/route.ts @@ -11,6 +11,7 @@ export async function GET() { select: { id: true, username: true, + email: true, score: true, level: true, avatar: true, @@ -24,6 +25,7 @@ export async function GET() { user: { id: string; username: string; + email: string; score: number; level: number; avatar: string | null; @@ -34,6 +36,7 @@ export async function GET() { ) => ({ rank: index + 1, username: user.username, + email: user.email, score: user.score, level: user.level, avatar: user.avatar, diff --git a/app/leaderboard/page.tsx b/app/leaderboard/page.tsx index fbe42d3..80e55cb 100644 --- a/app/leaderboard/page.tsx +++ b/app/leaderboard/page.tsx @@ -6,6 +6,7 @@ import { getBackgroundImage } from "@/lib/preferences"; interface LeaderboardEntry { rank: number; username: string; + email: string; score: number; level: number; avatar: string | null; @@ -22,6 +23,7 @@ export default async function LeaderboardPage() { select: { id: true, username: true, + email: true, score: true, level: true, avatar: true, @@ -33,6 +35,7 @@ export default async function LeaderboardPage() { const leaderboard: LeaderboardEntry[] = users.map((user, index) => ({ rank: index + 1, username: user.username, + email: user.email, score: user.score, level: user.level, avatar: user.avatar, diff --git a/components/Leaderboard.tsx b/components/Leaderboard.tsx index 8680090..97a75ec 100644 --- a/components/Leaderboard.tsx +++ b/components/Leaderboard.tsx @@ -5,6 +5,7 @@ import { useEffect, useState } from "react"; interface LeaderboardEntry { rank: number; username: string; + email: string; score: number; level: number; avatar?: string | null; @@ -20,6 +21,9 @@ const formatScore = (score: number): string => { export default function Leaderboard() { const [leaderboard, setLeaderboard] = useState([]); const [loading, setLoading] = useState(true); + const [selectedEntry, setSelectedEntry] = useState( + null + ); useEffect(() => { fetch("/api/leaderboard") @@ -83,82 +87,31 @@ export default function Leaderboard() { {entry.rank} -
- - {entry.username} - - {entry.characterClass && ( - - [{entry.characterClass === "WARRIOR" && "⚔️ Guerrier"} - {entry.characterClass === "MAGE" && "🔮 Mage"} - {entry.characterClass === "ROGUE" && "🗡️ Voleur"} - {entry.characterClass === "RANGER" && "🏹 Rôdeur"} - {entry.characterClass === "PALADIN" && "🛡️ Paladin"} - {entry.characterClass === "ENGINEER" && "⚙️ Ingénieur"} - {entry.characterClass === "MERCHANT" && "💰 Marchand"} - {entry.characterClass === "SCHOLAR" && "📚 Érudit"} - {entry.characterClass === "BERSERKER" && "🔥 Berserker"} - {entry.characterClass === "NECROMANCER" && - "💀 Nécromancien"} - ] +
+
setSelectedEntry(entry)} + > + + {entry.username} - )} - {(entry.bio || entry.characterClass) && ( -
- {entry.characterClass && ( -
-
- Classe -
-
- - {entry.characterClass === "WARRIOR" && "⚔️"} - {entry.characterClass === "MAGE" && "🔮"} - {entry.characterClass === "ROGUE" && "🗡️"} - {entry.characterClass === "RANGER" && "🏹"} - {entry.characterClass === "PALADIN" && "🛡️"} - {entry.characterClass === "ENGINEER" && "⚙️"} - {entry.characterClass === "MERCHANT" && "💰"} - {entry.characterClass === "SCHOLAR" && "📚"} - {entry.characterClass === "BERSERKER" && "🔥"} - {entry.characterClass === "NECROMANCER" && "💀"} - - - {entry.characterClass === "WARRIOR" && "Guerrier"} - {entry.characterClass === "MAGE" && "Mage"} - {entry.characterClass === "ROGUE" && "Voleur"} - {entry.characterClass === "RANGER" && "Rôdeur"} - {entry.characterClass === "PALADIN" && "Paladin"} - {entry.characterClass === "ENGINEER" && - "Ingénieur"} - {entry.characterClass === "MERCHANT" && - "Marchand"} - {entry.characterClass === "SCHOLAR" && "Érudit"} - {entry.characterClass === "BERSERKER" && - "Berserker"} - {entry.characterClass === "NECROMANCER" && - "Nécromancien"} - -
-
- )} - {entry.bio && ( - <> - {entry.characterClass && ( -
- )} -
-
- Bio -
-

- {entry.bio} -

-
- - )} -
- )} + {entry.characterClass && ( + + [{entry.characterClass === "WARRIOR" && "⚔️ Guerrier"} + {entry.characterClass === "MAGE" && "🔮 Mage"} + {entry.characterClass === "ROGUE" && "🗡️ Voleur"} + {entry.characterClass === "RANGER" && "🏹 Rôdeur"} + {entry.characterClass === "PALADIN" && "🛡️ Paladin"} + {entry.characterClass === "ENGINEER" && "⚙️ Ingénieur"} + {entry.characterClass === "MERCHANT" && "💰 Marchand"} + {entry.characterClass === "SCHOLAR" && "📚 Érudit"} + {entry.characterClass === "BERSERKER" && "🔥 Berserker"} + {entry.characterClass === "NECROMANCER" && + "💀 Nécromancien"} + ] + + )} +
@@ -180,6 +133,127 @@ export default function Leaderboard() {

Compete with players worldwide and climb the ranks!

+ + {/* Character Modal */} + {selectedEntry && ( +
setSelectedEntry(null)} + > +
e.stopPropagation()} + > +
+ {/* Header */} +
+

+ {selectedEntry.username} +

+ +
+ + {/* Avatar and Class */} +
+ {selectedEntry.avatar ? ( +
+ {selectedEntry.username} +
+ ) : ( +
+ + {selectedEntry.username.charAt(0).toUpperCase()} + +
+ )} +
+
+ Rank #{selectedEntry.rank} +
+
+ {selectedEntry.email} +
+ {selectedEntry.characterClass && ( +
+ + {selectedEntry.characterClass === "WARRIOR" && "⚔️"} + {selectedEntry.characterClass === "MAGE" && "🔮"} + {selectedEntry.characterClass === "ROGUE" && "🗡️"} + {selectedEntry.characterClass === "RANGER" && "🏹"} + {selectedEntry.characterClass === "PALADIN" && "🛡️"} + {selectedEntry.characterClass === "ENGINEER" && "⚙️"} + {selectedEntry.characterClass === "MERCHANT" && "💰"} + {selectedEntry.characterClass === "SCHOLAR" && "📚"} + {selectedEntry.characterClass === "BERSERKER" && "🔥"} + {selectedEntry.characterClass === "NECROMANCER" && "💀"} + + + {selectedEntry.characterClass === "WARRIOR" && + "Guerrier"} + {selectedEntry.characterClass === "MAGE" && "Mage"} + {selectedEntry.characterClass === "ROGUE" && "Voleur"} + {selectedEntry.characterClass === "RANGER" && "Rôdeur"} + {selectedEntry.characterClass === "PALADIN" && + "Paladin"} + {selectedEntry.characterClass === "ENGINEER" && + "Ingénieur"} + {selectedEntry.characterClass === "MERCHANT" && + "Marchand"} + {selectedEntry.characterClass === "SCHOLAR" && "Érudit"} + {selectedEntry.characterClass === "BERSERKER" && + "Berserker"} + {selectedEntry.characterClass === "NECROMANCER" && + "Nécromancien"} + +
+ )} +
+
+ + {/* Stats */} +
+
+
+ Score +
+
+ {formatScore(selectedEntry.score)} +
+
+
+
+ Niveau +
+
+ Lv.{selectedEntry.level} +
+
+
+ + {/* Bio */} + {selectedEntry.bio && ( +
+
+ Bio +
+

+ {selectedEntry.bio} +

+
+ )} +
+
+
+ )} ); } diff --git a/components/LeaderboardSection.tsx b/components/LeaderboardSection.tsx index 52bc934..cff9934 100644 --- a/components/LeaderboardSection.tsx +++ b/components/LeaderboardSection.tsx @@ -1,8 +1,11 @@ "use client"; +import { useState } from "react"; + interface LeaderboardEntry { rank: number; username: string; + email: string; score: number; level: number; avatar?: string | null; @@ -24,6 +27,10 @@ export default function LeaderboardSection({ leaderboard, backgroundImage, }: LeaderboardSectionProps) { + const [selectedEntry, setSelectedEntry] = useState( + null + ); + return (
{/* Background Image */} @@ -97,7 +104,7 @@ export default function LeaderboardSection({ {/* Player */} -
+
{entry.avatar ? (
)} - setSelectedEntry(entry)} > - {entry.username} - - {entry.characterClass && ( - - [{entry.characterClass === "WARRIOR" && "⚔️"} - {entry.characterClass === "MAGE" && "🔮"} - {entry.characterClass === "ROGUE" && "🗡️"} - {entry.characterClass === "RANGER" && "🏹"} - {entry.characterClass === "PALADIN" && "🛡️"} - {entry.characterClass === "ENGINEER" && "⚙️"} - {entry.characterClass === "MERCHANT" && "💰"} - {entry.characterClass === "SCHOLAR" && "📚"} - {entry.characterClass === "BERSERKER" && "🔥"} - {entry.characterClass === "NECROMANCER" && "💀"}] + + {entry.username} - )} - {entry.rank <= 3 && ( - - )} - {(entry.bio || entry.characterClass) && ( -
- {entry.characterClass && ( -
-
- Classe -
-
- - {entry.characterClass === "WARRIOR" && "⚔️"} - {entry.characterClass === "MAGE" && "🔮"} - {entry.characterClass === "ROGUE" && "🗡️"} - {entry.characterClass === "RANGER" && "🏹"} - {entry.characterClass === "PALADIN" && "🛡️"} - {entry.characterClass === "ENGINEER" && "⚙️"} - {entry.characterClass === "MERCHANT" && "💰"} - {entry.characterClass === "SCHOLAR" && "📚"} - {entry.characterClass === "BERSERKER" && "🔥"} - {entry.characterClass === "NECROMANCER" && "💀"} - - - {entry.characterClass === "WARRIOR" && "Guerrier"} - {entry.characterClass === "MAGE" && "Mage"} - {entry.characterClass === "ROGUE" && "Voleur"} - {entry.characterClass === "RANGER" && "Rôdeur"} - {entry.characterClass === "PALADIN" && "Paladin"} - {entry.characterClass === "ENGINEER" && - "Ingénieur"} - {entry.characterClass === "MERCHANT" && - "Marchand"} - {entry.characterClass === "SCHOLAR" && "Érudit"} - {entry.characterClass === "BERSERKER" && - "Berserker"} - {entry.characterClass === "NECROMANCER" && - "Nécromancien"} - -
-
- )} - {entry.bio && ( - <> - {entry.characterClass && ( -
- )} -
-
- Bio -
-

- {entry.bio} -

-
- - )} -
- )} + {entry.characterClass && ( + + [{entry.characterClass === "WARRIOR" && "⚔️"} + {entry.characterClass === "MAGE" && "🔮"} + {entry.characterClass === "ROGUE" && "🗡️"} + {entry.characterClass === "RANGER" && "🏹"} + {entry.characterClass === "PALADIN" && "🛡️"} + {entry.characterClass === "ENGINEER" && "⚙️"} + {entry.characterClass === "MERCHANT" && "💰"} + {entry.characterClass === "SCHOLAR" && "📚"} + {entry.characterClass === "BERSERKER" && "🔥"} + {entry.characterClass === "NECROMANCER" && "💀"}] + + )} + {entry.rank <= 3 && ( + + )} +
{/* Score */} @@ -223,6 +179,127 @@ export default function LeaderboardSection({

+ + {/* Character Modal */} + {selectedEntry && ( +
setSelectedEntry(null)} + > +
e.stopPropagation()} + > +
+ {/* Header */} +
+

+ {selectedEntry.username} +

+ +
+ + {/* Avatar and Class */} +
+ {selectedEntry.avatar ? ( +
+ {selectedEntry.username} +
+ ) : ( +
+ + {selectedEntry.username.charAt(0).toUpperCase()} + +
+ )} +
+
+ Rank #{selectedEntry.rank} +
+
+ {selectedEntry.email} +
+ {selectedEntry.characterClass && ( +
+ + {selectedEntry.characterClass === "WARRIOR" && "⚔️"} + {selectedEntry.characterClass === "MAGE" && "🔮"} + {selectedEntry.characterClass === "ROGUE" && "🗡️"} + {selectedEntry.characterClass === "RANGER" && "🏹"} + {selectedEntry.characterClass === "PALADIN" && "🛡️"} + {selectedEntry.characterClass === "ENGINEER" && "⚙️"} + {selectedEntry.characterClass === "MERCHANT" && "💰"} + {selectedEntry.characterClass === "SCHOLAR" && "📚"} + {selectedEntry.characterClass === "BERSERKER" && "🔥"} + {selectedEntry.characterClass === "NECROMANCER" && "💀"} + + + {selectedEntry.characterClass === "WARRIOR" && + "Guerrier"} + {selectedEntry.characterClass === "MAGE" && "Mage"} + {selectedEntry.characterClass === "ROGUE" && "Voleur"} + {selectedEntry.characterClass === "RANGER" && "Rôdeur"} + {selectedEntry.characterClass === "PALADIN" && + "Paladin"} + {selectedEntry.characterClass === "ENGINEER" && + "Ingénieur"} + {selectedEntry.characterClass === "MERCHANT" && + "Marchand"} + {selectedEntry.characterClass === "SCHOLAR" && "Érudit"} + {selectedEntry.characterClass === "BERSERKER" && + "Berserker"} + {selectedEntry.characterClass === "NECROMANCER" && + "Nécromancien"} + +
+ )} +
+
+ + {/* Stats */} +
+
+
+ Score +
+
+ {formatScore(selectedEntry.score)} +
+
+
+
+ Niveau +
+
+ Lv.{selectedEntry.level} +
+
+
+ + {/* Bio */} + {selectedEntry.bio && ( +
+
+ Bio +
+

+ {selectedEntry.bio} +

+
+ )} +
+
+
+ )}
); }