This repository has been archived on 2024-10-29. You can view files and clone it, but cannot push or open issues or pull requests.
Files
scoresaber-reloadedv3/projects/website/src/components/leaderboard/leaderboard-data.tsx

79 lines
2.7 KiB
TypeScript
Raw Normal View History

2024-10-04 18:25:37 +01:00
"use client";
import LeaderboardScores from "@/components/leaderboard/leaderboard-scores";
import { LeaderboardInfo } from "@/components/leaderboard/leaderboard-info";
import { useQuery } from "@tanstack/react-query";
2024-10-09 02:35:34 +01:00
import { useCallback, useEffect, useState } from "react";
2024-10-04 18:25:37 +01:00
import BeatSaverMap from "@/common/database/types/beatsaver-map";
2024-10-09 01:17:00 +01:00
import ScoreSaberLeaderboardScoresPageToken from "@ssr/common/types/token/scoresaber/score-saber-leaderboard-scores-page-token";
import ScoreSaberLeaderboardToken from "@ssr/common/types/token/scoresaber/score-saber-leaderboard-token";
import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
2024-10-09 02:35:34 +01:00
import { lookupBeatSaverMap } from "@/common/beatsaver-utils";
2024-10-04 18:25:37 +01:00
type LeaderboardDataProps = {
/**
* The page to show when opening the leaderboard.
*/
initialPage?: number;
/**
* The initial scores to show.
*/
initialScores?: ScoreSaberLeaderboardScoresPageToken;
/**
* The leaderboard to display.
*/
initialLeaderboard: ScoreSaberLeaderboardToken;
};
export function LeaderboardData({ initialPage, initialScores, initialLeaderboard }: LeaderboardDataProps) {
const [beatSaverMap, setBeatSaverMap] = useState<BeatSaverMap | undefined>();
const [selectedLeaderboardId, setSelectedLeaderboardId] = useState(initialLeaderboard.id);
const [currentLeaderboard, setCurrentLeaderboard] = useState(initialLeaderboard);
const { data: leaderboard } = useQuery({
queryKey: ["leaderboard-" + initialLeaderboard.id, selectedLeaderboardId],
queryFn: () => scoresaberService.lookupLeaderboard(selectedLeaderboardId + ""),
initialData: initialLeaderboard,
staleTime: 30 * 1000, // Cache data for 30 seconds
});
2024-10-09 02:35:34 +01:00
const fetchBeatSaverData = useCallback(async () => {
const beatSaverMap = await lookupBeatSaverMap(initialLeaderboard.songHash);
setBeatSaverMap(beatSaverMap);
}, [initialLeaderboard.songHash]);
useEffect(() => {
fetchBeatSaverData();
}, [fetchBeatSaverData]);
2024-10-04 18:25:37 +01:00
/**
* When the leaderboard changes, update the previous and current leaderboards.
* This is to prevent flickering between leaderboards.
*/
useEffect(() => {
if (leaderboard) {
setCurrentLeaderboard(leaderboard);
}
}, [leaderboard]);
if (!currentLeaderboard) {
return null;
}
return (
<main className="flex flex-col-reverse xl:flex-row w-full gap-2">
<LeaderboardScores
leaderboard={currentLeaderboard}
initialScores={initialScores}
initialPage={initialPage}
showDifficulties
isLeaderboardPage
leaderboardChanged={id => setSelectedLeaderboardId(id)}
/>
<LeaderboardInfo leaderboard={currentLeaderboard} beatSaverMap={beatSaverMap} />
</main>
);
}