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 ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
type Props = { type Props = {
/**
* The claimed player.
*/
player: ScoreSaberPlayer;
/**
* The score to display.
*/
score: ScoreSaberScoreToken; score: ScoreSaberScoreToken;
}; };
export default function LeaderboardPlayer({ score }: Props) { export default function LeaderboardPlayer({ player, score }: Props) {
const player = score.leaderboardPlayerInfo; const scorePlayer = score.leaderboardPlayerInfo;
return ( return (
<div className="flex gap-2"> <div className="flex gap-2">
<Image <Image
unoptimized 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} width={48}
height={48} height={48}
alt="Song Artwork" alt="Song Artwork"
@ -21,11 +30,11 @@ export default function LeaderboardPlayer({ score }: Props) {
priority priority
/> />
<Link <Link
href={`/player/${player.id}`} href={`/player/${scorePlayer.id}`}
target="_blank" target="_blank"
className="h-fit hover:brightness-75 transition-all transform-gpu" 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> </Link>
</div> </div>
); );

@ -5,8 +5,14 @@ import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-sc
import LeaderboardPlayer from "./leaderboard-player"; import LeaderboardPlayer from "./leaderboard-player";
import LeaderboardScoreStats from "./leaderboard-score-stats"; import LeaderboardScoreStats from "./leaderboard-score-stats";
import ScoreRankInfo from "@/components/score/score-rank-info"; import ScoreRankInfo from "@/components/score/score-rank-info";
import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player";
type Props = { type Props = {
/**
* The claimed player.
*/
player: ScoreSaberPlayer;
/** /**
* The score to display. * The score to display.
*/ */
@ -18,12 +24,12 @@ type Props = {
leaderboard: ScoreSaberLeaderboardToken; leaderboard: ScoreSaberLeaderboardToken;
}; };
export default function LeaderboardScore({ score, leaderboard }: Props) { export default function LeaderboardScore({ player, score, leaderboard }: Props) {
return ( return (
<div className="pb-1 pt-1"> <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]"> <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} /> <ScoreRankInfo score={score} />
<LeaderboardPlayer score={score} /> <LeaderboardPlayer player={player} score={score} />
<LeaderboardScoreStats score={score} leaderboard={leaderboard} /> <LeaderboardScoreStats score={score} leaderboard={leaderboard} />
</div> </div>
</div> </div>

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

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

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