default to the page the players score is on when showing the leaderboard for a score

This commit is contained in:
Lee 2024-10-01 09:37:51 +01:00
parent 43d52e335e
commit 73b039dca8
5 changed files with 42 additions and 14 deletions

@ -1,19 +1,28 @@
import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player";
import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token";
import Image from "next/image";
import Link from "next/link";
type Props = {
/**
* The claimed player.
*/
player: ScoreSaberPlayer;
/**
* The score to display.
*/
score: ScoreSaberScoreToken;
};
export default function LeaderboardPlayer({ score }: Props) {
const player = score.leaderboardPlayerInfo;
export default function LeaderboardPlayer({ player, score }: Props) {
const scorePlayer = score.leaderboardPlayerInfo;
return (
<div className="flex gap-2">
<Image
unoptimized
src={`https://img.fascinated.cc/upload/w_48,h_48/${player.profilePicture}`}
src={`https://img.fascinated.cc/upload/w_48,h_48/${scorePlayer.profilePicture}`}
width={48}
height={48}
alt="Song Artwork"
@ -21,11 +30,11 @@ export default function LeaderboardPlayer({ score }: Props) {
priority
/>
<Link
href={`/player/${player.id}`}
href={`/player/${scorePlayer.id}`}
target="_blank"
className="h-fit hover:brightness-75 transition-all transform-gpu"
>
<p>{player.name}</p>
<p className={`${scorePlayer.id === player.id && "text-pp"}`}>{scorePlayer.name}</p>
</Link>
</div>
);

@ -5,8 +5,14 @@ import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-sc
import LeaderboardPlayer from "./leaderboard-player";
import LeaderboardScoreStats from "./leaderboard-score-stats";
import ScoreRankInfo from "@/components/score/score-rank-info";
import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player";
type Props = {
/**
* The claimed player.
*/
player: ScoreSaberPlayer;
/**
* The score to display.
*/
@ -18,12 +24,12 @@ type Props = {
leaderboard: ScoreSaberLeaderboardToken;
};
export default function LeaderboardScore({ score, leaderboard }: Props) {
export default function LeaderboardScore({ player, score, leaderboard }: Props) {
return (
<div className="pb-1 pt-1">
<div className="grid items-center w-full gap-2 first:pt-0 last:pb-0 grid-cols-[20px 1fr_1fr] lg:grid-cols-[130px_4fr_300px]">
<ScoreRankInfo score={score} />
<LeaderboardPlayer score={score} />
<LeaderboardPlayer player={player} score={score} />
<LeaderboardScoreStats score={score} leaderboard={leaderboard} />
</div>
</div>

@ -11,17 +11,23 @@ import Card from "../card";
import Pagination from "../input/pagination";
import LeaderboardScore from "./leaderboard-score";
import { scoreAnimation } from "@/components/score/score-animation";
import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player";
type LeaderboardScoresProps = {
initialPage?: number;
player: ScoreSaberPlayer;
leaderboard: ScoreSaberLeaderboardToken;
};
export default function LeaderboardScores({ leaderboard }: LeaderboardScoresProps) {
export default function LeaderboardScores({ initialPage, player, leaderboard }: LeaderboardScoresProps) {
if (!initialPage) {
initialPage = 1;
}
const { width } = useWindowDimensions();
const controls = useAnimation();
const [previousPage, setPreviousPage] = useState(1);
const [currentPage, setCurrentPage] = useState(1);
const [previousPage, setPreviousPage] = useState(initialPage);
const [currentPage, setCurrentPage] = useState(initialPage);
const [currentScores, setCurrentScores] = useState<ScoreSaberLeaderboardScoresPageToken | undefined>();
const topOfScoresRef = useRef<HTMLDivElement>(null);
@ -98,7 +104,7 @@ export default function LeaderboardScores({ leaderboard }: LeaderboardScoresProp
>
{currentScores.scores.map((playerScore, index) => (
<motion.div key={index} variants={scoreAnimation}>
<LeaderboardScore key={index} score={playerScore} leaderboard={leaderboard} />
<LeaderboardScore key={index} player={player} score={playerScore} leaderboard={leaderboard} />
</motion.div>
))}
</motion.div>

@ -205,7 +205,7 @@ export default function PlayerScores({ initialScoreData, initialSearch, player,
>
{currentScores.playerScores.map((playerScore, index) => (
<motion.div key={index} variants={scoreAnimation}>
<Score playerScore={playerScore} />
<Score player={player} playerScore={playerScore} />
</motion.div>
))}
</motion.div>

@ -9,15 +9,21 @@ import ScoreButtons from "./score-buttons";
import ScoreSongInfo from "./score-info";
import ScoreRankInfo from "./score-rank-info";
import ScoreStats from "./score-stats";
import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player";
type Props = {
/**
* The claimed player
*/
player: ScoreSaberPlayer;
/**
* The score to display.
*/
playerScore: ScoreSaberPlayerScoreToken;
};
export default function Score({ playerScore }: Props) {
export default function Score({ player, playerScore }: Props) {
const { score, leaderboard } = playerScore;
const [beatSaverMap, setBeatSaverMap] = useState<BeatSaverMap | undefined>();
const [isLeaderboardExpanded, setIsLeaderboardExpanded] = useState(false);
@ -31,6 +37,7 @@ export default function Score({ playerScore }: Props) {
fetchBeatSaverData();
}, [fetchBeatSaverData]);
const page = Math.floor(score.rank / 12) + 1;
return (
<div className="pb-2 pt-2">
<div
@ -46,7 +53,7 @@ export default function Score({ playerScore }: Props) {
/>
<ScoreStats score={score} leaderboard={leaderboard} />
</div>
{isLeaderboardExpanded && <LeaderboardScores leaderboard={leaderboard} />}
{isLeaderboardExpanded && <LeaderboardScores initialPage={page} player={player} leaderboard={leaderboard} />}
</div>
);
}