Files
got-gaming/components/Leaderboard.tsx

112 lines
3.8 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
interface LeaderboardEntry {
rank: number;
username: string;
score: number;
level: number;
avatar?: string | null;
}
// Format number with consistent locale to avoid hydration mismatch
const formatScore = (score: number): string => {
return score.toLocaleString("en-US");
};
export default function Leaderboard() {
const [leaderboard, setLeaderboard] = useState<LeaderboardEntry[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch("/api/leaderboard")
.then((res) => res.json())
.then((data) => {
setLeaderboard(data);
setLoading(false);
})
.catch((err) => {
console.error("Error fetching leaderboard:", err);
setLoading(false);
});
}, []);
if (loading) {
return (
<section className="w-full bg-black py-16 px-6 border-t-2 border-pixel-dark-purple">
<div className="max-w-4xl mx-auto text-center text-pixel-gold">
Chargement...
</div>
</section>
);
}
return (
<section className="w-full bg-black py-16 px-6 border-t-2 border-pixel-dark-purple">
<div className="max-w-4xl mx-auto">
<h2 className="text-4xl md:text-5xl font-bold text-center mb-12 text-pixel-gold text-pixel">
LEADERBOARD
</h2>
<div className="bg-black/80 border-2 border-pixel-gold/30 rounded-lg overflow-hidden backdrop-blur-sm">
{/* Header */}
<div className="bg-gray-900/80 border-b-2 border-pixel-gold/30 grid grid-cols-12 gap-4 p-4 font-bold text-sm text-gray-300">
<div className="col-span-1 text-center">Rank</div>
<div className="col-span-5">Player</div>
<div className="col-span-3 text-right">Score</div>
<div className="col-span-3 text-right">Level</div>
</div>
{/* Entries */}
<div className="divide-y divide-pixel-gold/10">
{leaderboard.map((entry) => (
<div
key={entry.rank}
className={`grid grid-cols-12 gap-4 p-4 hover:bg-gray-900/50 transition ${
entry.rank <= 3 ? "bg-gray-950/50" : "bg-black/40"
}`}
>
<div className="col-span-1 text-center">
<span
className={`inline-block w-8 h-8 rounded-full flex items-center justify-center font-bold ${
entry.rank === 1
? "bg-pixel-gold text-black"
: entry.rank === 2
? "bg-gray-600 text-white"
: entry.rank === 3
? "bg-orange-800 text-white"
: "bg-gray-900 text-gray-400 border border-gray-800"
}`}
>
{entry.rank}
</span>
</div>
<div className="col-span-5 flex items-center">
<span className="font-bold text-pixel-gold">
{entry.username}
</span>
</div>
<div className="col-span-3 text-right flex items-center justify-end">
<span className="font-mono text-gray-300">
{formatScore(entry.score)}
</span>
</div>
<div className="col-span-3 text-right flex items-center justify-end">
<span className="font-bold text-gray-400">
Lv.{entry.level}
</span>
</div>
</div>
))}
</div>
</div>
{/* Additional info */}
<div className="mt-8 text-center text-sm text-gray-500">
<p>Compete with players worldwide and climb the ranks!</p>
</div>
</div>
</section>
);
}