feat: implement real-time leaderboard system with XP and voice channel tracking features

This commit is contained in:
2026-07-25 21:26:53 +07:00 Unverified
parent bb6740fcee
commit 3f4b670170
18 changed files with 531 additions and 178 deletions
@@ -16,9 +16,15 @@ function visiblePages(page: number, totalPages: number) {
.sort((a, b) => a - b);
}
function pageHref(path: string, page: number, channelId?: string) {
function pageHref(
path: string,
page: number,
channelId?: string,
searchQuery?: string,
) {
const params = new URLSearchParams();
if (channelId) params.set("channel", channelId);
if (searchQuery) params.set("q", searchQuery);
if (page > 1) params.set("page", String(page));
const query = params.toString();
return query ? `${path}?${query}` : path;
@@ -29,11 +35,13 @@ export function LeaderboardPagination({
page,
totalPages,
channelId,
searchQuery,
}: {
path: string;
page: number;
totalPages: number;
channelId?: string;
searchQuery?: string;
}) {
if (totalPages <= 1) return null;
const pages = visiblePages(page, totalPages);
@@ -44,7 +52,7 @@ export function LeaderboardPagination({
{page > 1 && (
<PaginationItem>
<PaginationPrevious
href={pageHref(path, page - 1, channelId)}
href={pageHref(path, page - 1, channelId, searchQuery)}
text="ก่อนหน้า"
aria-label="ไปหน้าก่อนหน้า"
/>
@@ -60,7 +68,7 @@ export function LeaderboardPagination({
)}
<PaginationItem>
<PaginationLink
href={pageHref(path, value, channelId)}
href={pageHref(path, value, channelId, searchQuery)}
isActive={value === page}
aria-label={`ไปหน้า ${value}`}
>
@@ -73,7 +81,7 @@ export function LeaderboardPagination({
{page < totalPages && (
<PaginationItem>
<PaginationNext
href={pageHref(path, page + 1, channelId)}
href={pageHref(path, page + 1, channelId, searchQuery)}
text="ถัดไป"
aria-label="ไปหน้าถัดไป"
/>