feat: implement real-time leaderboard system with XP and voice channel tracking features
This commit is contained in:
@@ -5,7 +5,7 @@ import { LeaderboardError } from "@/components/leaderboard/leaderboard-error";
|
||||
import { LeaderboardShell } from "@/components/leaderboard/leaderboard-shell";
|
||||
import { RealtimeRefresh } from "@/components/realtime-refresh";
|
||||
import { getXpLeaderboardPage } from "@/lib/leaderboard/database";
|
||||
import { normalizeRequestedPage } from "@/lib/leaderboard/ranking";
|
||||
import { normalizeLeaderboardSearch, normalizeRequestedPage } from "@/lib/leaderboard/ranking";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
@@ -20,6 +20,7 @@ export const metadata: Metadata = {
|
||||
type XpLeaderboardPageProps = {
|
||||
searchParams: Promise<{
|
||||
page?: string | string[];
|
||||
q?: string | string[];
|
||||
}>;
|
||||
};
|
||||
|
||||
@@ -28,10 +29,11 @@ export default async function XpLeaderboardPage({
|
||||
}: XpLeaderboardPageProps) {
|
||||
const query = await searchParams;
|
||||
const requestedPage = normalizeRequestedPage(query.page);
|
||||
const searchQuery = normalizeLeaderboardSearch(query.q);
|
||||
|
||||
let data;
|
||||
try {
|
||||
data = await getXpLeaderboardPage(requestedPage);
|
||||
data = await getXpLeaderboardPage(requestedPage, searchQuery);
|
||||
} catch (error) {
|
||||
console.error("Failed to load XP leaderboard", error);
|
||||
return (
|
||||
@@ -39,6 +41,7 @@ export default async function XpLeaderboardPage({
|
||||
active="xp"
|
||||
title="อันดับ XP"
|
||||
description="จัดอันดับจาก XP รวมของสมาชิกที่มีเลเวล 1 ขึ้นไป อันดับที่มี XP เท่ากันจะแชร์อันดับเดียวกัน"
|
||||
searchQuery={searchQuery}
|
||||
>
|
||||
<LeaderboardError source="database" />
|
||||
</LeaderboardShell>
|
||||
@@ -46,7 +49,11 @@ export default async function XpLeaderboardPage({
|
||||
}
|
||||
|
||||
if (query.page !== undefined && query.page !== String(data.page)) {
|
||||
redirect(data.page > 1 ? `/leaderboard/xp?page=${data.page}` : "/leaderboard/xp");
|
||||
const params = new URLSearchParams();
|
||||
if (searchQuery) params.set("q", searchQuery);
|
||||
if (data.page > 1) params.set("page", String(data.page));
|
||||
const redirectQuery = params.toString();
|
||||
redirect(redirectQuery ? `/leaderboard/xp?${redirectQuery}` : "/leaderboard/xp");
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -54,9 +61,10 @@ export default async function XpLeaderboardPage({
|
||||
active="xp"
|
||||
title="อันดับ XP"
|
||||
description="จัดอันดับจาก XP รวมของสมาชิกที่มีเลเวล 1 ขึ้นไป อันดับที่มี XP เท่ากันจะแชร์อันดับเดียวกัน"
|
||||
searchQuery={searchQuery}
|
||||
>
|
||||
<RealtimeRefresh topic="leaderboards" leaderboard="xp" />
|
||||
<LeaderboardBoard kind="xp" data={data} />
|
||||
<LeaderboardBoard kind="xp" data={data} searchQuery={searchQuery} />
|
||||
</LeaderboardShell>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user