add beatleader score fetching and add icons to FC
Some checks failed
deploy / deploy (push) Failing after 2s

This commit is contained in:
Lee
2023-10-22 13:47:56 +01:00
parent 2e93a1b27f
commit 80e6c0da43
33 changed files with 979 additions and 124 deletions

View File

@ -0,0 +1,24 @@
"use client";
import { useBeatLeaderScoresStore } from "@/store/beatLeaderScoresStore";
import { useScoresaberScoresStore } from "@/store/scoresaberScoresStore";
type AppProviderProps = {
children: React.ReactNode;
};
export function AppProvider({ children }: AppProviderProps) {
return <>{children}</>;
}
const UPDATE_INTERVAL = 1000 * 60 * 15; // 15 minutes
useBeatLeaderScoresStore.getState().updatePlayerScores();
setInterval(() => {
useBeatLeaderScoresStore.getState().updatePlayerScores();
}, UPDATE_INTERVAL);
useScoresaberScoresStore.getState().updatePlayerScores();
setInterval(() => {
useScoresaberScoresStore.getState().updatePlayerScores();
}, UPDATE_INTERVAL);

View File

@ -1,5 +1,6 @@
import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
import { usePlayerScoresStore } from "@/store/playerScoresStore";
import { useBeatLeaderScoresStore } from "@/store/beatLeaderScoresStore";
import { useScoresaberScoresStore } from "@/store/scoresaberScoresStore";
import { useSettingsStore } from "@/store/settingsStore";
import { formatNumber } from "@/utils/number";
import {
@ -28,7 +29,7 @@ type PlayerInfoProps = {
export default function PlayerInfo({ playerData }: PlayerInfoProps) {
const playerId = playerData.id;
const settingsStore = useStore(useSettingsStore, (store) => store);
const playerScoreStore = useStore(usePlayerScoresStore, (store) => store);
const playerScoreStore = useStore(useScoresaberScoresStore, (store) => store);
// Whether we have scores for this player in the local database
const hasLocalScores = playerScoreStore?.exists(playerId);
@ -50,39 +51,80 @@ export default function PlayerInfo({ playerData }: PlayerInfoProps) {
}
async function addProfile(isFriend: boolean) {
if (!usePlayerScoresStore.getState().exists(playerId)) {
const reponse = await playerScoreStore?.addPlayer(
playerId,
(page, totalPages) => {
const autoClose = page == totalPages ? 5000 : false;
const setupScoresaber = async () => {
if (!useScoresaberScoresStore.getState().exists(playerId)) {
const reponse = await playerScoreStore?.addPlayer(
playerId,
(page, totalPages) => {
const autoClose = page == totalPages ? 5000 : false;
if (page == 1) {
toastId.current = toast.info(
`Fetching scores ${page}/${totalPages}`,
{
autoClose: autoClose,
if (page == 1) {
toastId.current = toast.info(
`Fetching ScoreSaber scores ${page}/${totalPages}`,
{
autoClose: autoClose,
progress: page / totalPages,
},
);
} else {
toast.update(toastId.current, {
progress: page / totalPages,
},
);
} else {
toast.update(toastId.current, {
progress: page / totalPages,
render: `Fetching scores ${page}/${totalPages}`,
autoClose: autoClose,
});
}
render: `Fetching ScoreSaber scores ${page}/${totalPages}`,
autoClose: autoClose,
});
}
console.log(
`Fetching scores for ${playerId} (${page}/${totalPages})`,
);
},
);
if (reponse?.error) {
toast.error("Failed to fetch scores");
console.log(reponse.message);
return;
console.log(
`Fetching ScoreSaber scores for ${playerId} (${page}/${totalPages})`,
);
},
);
if (reponse?.error) {
toast.error("Failed to fetch scores");
console.log(reponse.message);
return;
}
}
}
};
const setupBeatleader = async () => {
if (!useBeatLeaderScoresStore.getState().exists(playerId)) {
const reponse = await playerScoreStore?.addPlayer(
playerId,
(page, totalPages) => {
const autoClose = page == totalPages ? 5000 : false;
if (page == 1) {
toastId.current = toast.info(
`Fetching BeatLeader scores ${page}/${totalPages}`,
{
autoClose: autoClose,
progress: page / totalPages,
},
);
} else {
toast.update(toastId.current, {
progress: page / totalPages,
render: `Fetching BeatLeader scores ${page}/${totalPages}`,
autoClose: autoClose,
});
}
console.log(
`Fetching BeatLeader scores for ${playerId} (${page}/${totalPages})`,
);
},
);
if (reponse?.error) {
toast.error("Failed to fetch scores");
console.log(reponse.message);
return;
}
}
};
await setupScoresaber();
await setupBeatleader();
if (!isFriend) {
toast.success(`Successfully set ${playerData.name} as your profile`);

View File

@ -1,7 +1,13 @@
import { ScoresaberLeaderboardInfo } from "@/schemas/scoresaber/leaderboard";
import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
import { ScoresaberScore } from "@/schemas/scoresaber/score";
import { useBeatLeaderScoresStore } from "@/store/beatLeaderScoresStore";
import { formatNumber } from "@/utils/number";
import { GlobeAsiaAustraliaIcon } from "@heroicons/react/20/solid";
import {
CheckIcon,
GlobeAsiaAustraliaIcon,
XMarkIcon,
} from "@heroicons/react/20/solid";
import clsx from "clsx";
import moment from "moment";
import Image from "next/image";
@ -9,11 +15,17 @@ import ScoreStatLabel from "./ScoreStatLabel";
type ScoreProps = {
score: ScoresaberScore;
player: ScoresaberPlayer;
leaderboard: ScoresaberLeaderboardInfo;
};
export default function Score({ score, leaderboard }: ScoreProps) {
export default function Score({ score, player, leaderboard }: ScoreProps) {
const isFullCombo = score.missedNotes + score.badCuts === 0;
const beatleaderScoreData = useBeatLeaderScoresStore
.getState()
.getScore(player.id, leaderboard.songHash);
console.log(beatleaderScoreData);
return (
<div className="grid grid-cols-1 pb-2 pt-2 first:pt-0 last:pb-0 md:grid-cols-[1.1fr_6fr_3fr] xl:md:grid-cols-[.95fr_6fr_3fr]">
@ -90,7 +102,13 @@ export default function Score({ score, leaderboard }: ScoreProps) {
"min-w-[2rem]",
isFullCombo ? "bg-green-500" : "bg-red-500",
)}
title={`${score.missedNotes} missed notes. ${score.badCuts} bad cuts.`}
icon={
isFullCombo ? (
<CheckIcon width={20} height={20} />
) : (
<XMarkIcon width={20} height={20} />
)
}
value={
isFullCombo
? "FC"

View File

@ -2,7 +2,7 @@ import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
import { ScoresaberPlayerScore } from "@/schemas/scoresaber/playerScore";
import { useSettingsStore } from "@/store/settingsStore";
import { SortType, SortTypes } from "@/types/SortTypes";
import { fetchScores } from "@/utils/scoresaber/api";
import { ScoreSaberAPI } from "@/utils/scoresaber/api";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import Card from "../Card";
@ -43,38 +43,40 @@ export default function Scores({ playerData, page, sortType }: ScoresProps) {
const updateScoresPage = useCallback(
(sortType: SortType, page: any) => {
console.log(`Switching page to ${page} with sort ${sortType.value}`);
fetchScores(playerId, page, sortType.value, 10).then((scoresResponse) => {
if (!scoresResponse) {
setError(true);
setErrorMessage("No Scores");
setScores({ ...scores, loading: false });
return;
}
setScores({
...scores,
scores: scoresResponse.scores,
totalPages: scoresResponse.pageInfo.totalPages,
loading: false,
page: page,
sortType: sortType,
});
useSettingsStore.setState({
lastUsedSortType: sortType,
});
if (page > 1) {
router.push(
`/player/${playerId}?page=${page}&sort=${sortType.value}`,
{
scroll: false,
},
);
} else {
router.push(`/player/${playerId}?sort=${sortType.value}`, {
scroll: false,
ScoreSaberAPI.fetchScores(playerId, page, sortType.value, 10).then(
(scoresResponse) => {
if (!scoresResponse) {
setError(true);
setErrorMessage("No Scores");
setScores({ ...scores, loading: false });
return;
}
setScores({
...scores,
scores: scoresResponse.scores,
totalPages: scoresResponse.pageInfo.totalPages,
loading: false,
page: page,
sortType: sortType,
});
}
});
useSettingsStore.setState({
lastUsedSortType: sortType,
});
if (page > 1) {
router.push(
`/player/${playerId}?page=${page}&sort=${sortType.value}`,
{
scroll: false,
},
);
} else {
router.push(`/player/${playerId}?sort=${sortType.value}`, {
scroll: false,
});
}
},
);
},
[playerId, router, scores],
);
@ -125,7 +127,12 @@ export default function Scores({ playerData, page, sortType }: ScoresProps) {
const { score, leaderboard } = scoreData;
return (
<Score key={id} score={score} leaderboard={leaderboard} />
<Score
key={id}
player={playerData}
score={score}
leaderboard={leaderboard}
/>
);
})
)}

View File

@ -2,7 +2,7 @@
import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
import { formatNumber } from "@/utils/number";
import { getPlayerInfo, searchByName } from "@/utils/scoresaber/api";
import { ScoreSaberAPI } from "@/utils/scoresaber/api";
import { MagnifyingGlassIcon } from "@heroicons/react/20/solid";
import clsx from "clsx";
import { useEffect, useState } from "react";
@ -27,14 +27,14 @@ export default function SearchPlayer() {
const id = search.split("/").pop();
if (id == undefined) return;
const player = await getPlayerInfo(id);
const player = await ScoreSaberAPI.getPlayerInfo(id);
if (player == undefined) return;
setPlayers([player]);
}
// Search by name
const players = await searchByName(search);
const players = await ScoreSaberAPI.searchByName(search);
if (players == undefined) return;
setPlayers(players);