add hover transition to the footer
All checks were successful
Deploy SSR / deploy (push) Successful in 1m43s
All checks were successful
Deploy SSR / deploy (push) Successful in 1m43s
This commit is contained in:
@ -32,7 +32,7 @@ export default function Footer() {
|
||||
return (
|
||||
<Link
|
||||
key={index}
|
||||
className="px-2 text-pp hover:brightness-75"
|
||||
className="px-2 text-pp hover:brightness-75 transition-all transform-gpu"
|
||||
href={item.link}
|
||||
>
|
||||
{item.name}
|
||||
|
@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { scoresaberService } from "@/common/service/impl/scoresaber";
|
||||
import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player";
|
||||
import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token";
|
||||
import { formatNumberWithCommas } from "@/common/number-utils";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import Link from "next/link";
|
||||
@ -25,7 +25,7 @@ export default function SearchPlayer() {
|
||||
username: "",
|
||||
},
|
||||
});
|
||||
const [results, setResults] = useState<ScoreSaberPlayer[] | undefined>();
|
||||
const [results, setResults] = useState<ScoreSaberPlayerToken[] | undefined>();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
async function onSubmit({ username }: z.infer<typeof formSchema>) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import ScoreSaberScore from "@/common/service/types/scoresaber/scoresaber-score";
|
||||
import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
type Props = {
|
||||
score: ScoreSaberScore;
|
||||
score: ScoreSaberScoreToken;
|
||||
};
|
||||
|
||||
export default function LeaderboardPlayer({ score }: Props) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import ScoreSaberLeaderboard from "@/common/service/types/scoresaber/scoresaber-leaderboard";
|
||||
import ScoreSaberScore from "@/common/service/types/scoresaber/scoresaber-score";
|
||||
import ScoreSaberLeaderboardToken from "@/common/model/token/scoresaber/score-saber-leaderboard-token";
|
||||
import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token";
|
||||
import { formatNumberWithCommas } from "@/common/number-utils";
|
||||
import StatValue from "@/components/stat-value";
|
||||
import { XMarkIcon } from "@heroicons/react/24/solid";
|
||||
@ -8,15 +8,15 @@ import clsx from "clsx";
|
||||
type Badge = {
|
||||
name: string;
|
||||
create: (
|
||||
score: ScoreSaberScore,
|
||||
leaderboard: ScoreSaberLeaderboard,
|
||||
score: ScoreSaberScoreToken,
|
||||
leaderboard: ScoreSaberLeaderboardToken,
|
||||
) => string | React.ReactNode | undefined;
|
||||
};
|
||||
|
||||
const badges: Badge[] = [
|
||||
{
|
||||
name: "PP",
|
||||
create: (score: ScoreSaberScore) => {
|
||||
create: (score: ScoreSaberScoreToken) => {
|
||||
const pp = score.pp;
|
||||
if (pp === 0) {
|
||||
return undefined;
|
||||
@ -26,14 +26,17 @@ const badges: Badge[] = [
|
||||
},
|
||||
{
|
||||
name: "Accuracy",
|
||||
create: (score: ScoreSaberScore, leaderboard: ScoreSaberLeaderboard) => {
|
||||
create: (
|
||||
score: ScoreSaberScoreToken,
|
||||
leaderboard: ScoreSaberLeaderboardToken,
|
||||
) => {
|
||||
const acc = (score.baseScore / leaderboard.maxScore) * 100;
|
||||
return `${acc.toFixed(2)}%`;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Full Combo",
|
||||
create: (score: ScoreSaberScore) => {
|
||||
create: (score: ScoreSaberScoreToken) => {
|
||||
const fullCombo = score.missedNotes === 0;
|
||||
|
||||
return (
|
||||
@ -55,8 +58,8 @@ const badges: Badge[] = [
|
||||
];
|
||||
|
||||
type Props = {
|
||||
score: ScoreSaberScore;
|
||||
leaderboard: ScoreSaberLeaderboard;
|
||||
score: ScoreSaberScoreToken;
|
||||
leaderboard: ScoreSaberLeaderboardToken;
|
||||
};
|
||||
|
||||
export default function LeaderboardScoreStats({ score, leaderboard }: Props) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import ScoreSaberLeaderboard from "@/common/service/types/scoresaber/scoresaber-leaderboard";
|
||||
import ScoreSaberScore from "@/common/service/types/scoresaber/scoresaber-score";
|
||||
import ScoreSaberLeaderboardToken from "@/common/model/token/scoresaber/score-saber-leaderboard-token";
|
||||
import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token";
|
||||
import LeaderboardPlayer from "./leaderboard-player";
|
||||
import LeaderboardScoreStats from "./leaderboard-score-stats";
|
||||
import ScoreRankInfo from "@/components/score/score-rank-info";
|
||||
@ -10,12 +10,12 @@ type Props = {
|
||||
/**
|
||||
* The score to display.
|
||||
*/
|
||||
score: ScoreSaberScore;
|
||||
score: ScoreSaberScoreToken;
|
||||
|
||||
/**
|
||||
* The leaderboard to display.
|
||||
*/
|
||||
leaderboard: ScoreSaberLeaderboard;
|
||||
leaderboard: ScoreSaberLeaderboardToken;
|
||||
};
|
||||
|
||||
export default function LeaderboardScore({ score, leaderboard }: Props) {
|
||||
|
@ -1,8 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { scoresaberService } from "@/common/service/impl/scoresaber";
|
||||
import ScoreSaberLeaderboard from "@/common/service/types/scoresaber/scoresaber-leaderboard";
|
||||
import ScoreSaberLeaderboardScoresPage from "@/common/service/types/scoresaber/scoresaber-leaderboard-scores-page";
|
||||
import ScoreSaberLeaderboardToken from "@/common/model/token/scoresaber/score-saber-leaderboard-token";
|
||||
import ScoreSaberLeaderboardScoresPageToken from "@/common/model/token/scoresaber/score-saber-leaderboard-scores-page-token";
|
||||
import useWindowDimensions from "@/hooks/use-window-dimensions";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { motion } from "framer-motion";
|
||||
@ -12,7 +12,7 @@ import Pagination from "../input/pagination";
|
||||
import LeaderboardScore from "./leaderboard-score";
|
||||
|
||||
type Props = {
|
||||
leaderboard: ScoreSaberLeaderboard;
|
||||
leaderboard: ScoreSaberLeaderboardToken;
|
||||
};
|
||||
|
||||
export default function LeaderboardScores({ leaderboard }: Props) {
|
||||
@ -20,7 +20,7 @@ export default function LeaderboardScores({ leaderboard }: Props) {
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [currentScores, setCurrentScores] = useState<
|
||||
ScoreSaberLeaderboardScoresPage | undefined
|
||||
ScoreSaberLeaderboardScoresPageToken | undefined
|
||||
>();
|
||||
|
||||
const {
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
import { scoresaberService } from "@/common/service/impl/scoresaber";
|
||||
import { ScoreSort } from "@/common/service/score-sort";
|
||||
import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player";
|
||||
import ScoreSaberPlayerScoresPage from "@/common/service/types/scoresaber/scoresaber-player-scores-page";
|
||||
import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token";
|
||||
import ScoreSaberPlayerScoresPageToken from "@/common/model/token/scoresaber/score-saber-player-scores-page-token";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import PlayerHeader from "./player-header";
|
||||
import PlayerRankChart from "./player-rank-chart";
|
||||
@ -12,8 +12,8 @@ import PlayerScores from "./player-scores";
|
||||
const REFRESH_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
type Props = {
|
||||
initialPlayerData: ScoreSaberPlayer;
|
||||
initialScoreData?: ScoreSaberPlayerScoresPage;
|
||||
initialPlayerData: ScoreSaberPlayerToken;
|
||||
initialScoreData?: ScoreSaberPlayerScoresPageToken;
|
||||
sort: ScoreSort;
|
||||
page: number;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player";
|
||||
import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token";
|
||||
import { formatNumberWithCommas } from "@/common/number-utils";
|
||||
import { GlobeAmericasIcon } from "@heroicons/react/24/solid";
|
||||
import Card from "../card";
|
||||
@ -13,29 +13,29 @@ const playerData = [
|
||||
icon: () => {
|
||||
return <GlobeAmericasIcon className="h-5 w-5" />;
|
||||
},
|
||||
render: (player: ScoreSaberPlayer) => {
|
||||
render: (player: ScoreSaberPlayerToken) => {
|
||||
return <p>#{formatNumberWithCommas(player.rank)}</p>;
|
||||
},
|
||||
},
|
||||
{
|
||||
showWhenInactiveOrBanned: false,
|
||||
icon: (player: ScoreSaberPlayer) => {
|
||||
icon: (player: ScoreSaberPlayerToken) => {
|
||||
return <CountryFlag country={player.country.toLowerCase()} size={15} />;
|
||||
},
|
||||
render: (player: ScoreSaberPlayer) => {
|
||||
render: (player: ScoreSaberPlayerToken) => {
|
||||
return <p>#{formatNumberWithCommas(player.countryRank)}</p>;
|
||||
},
|
||||
},
|
||||
{
|
||||
showWhenInactiveOrBanned: true,
|
||||
render: (player: ScoreSaberPlayer) => {
|
||||
render: (player: ScoreSaberPlayerToken) => {
|
||||
return <p className="text-pp">{formatNumberWithCommas(player.pp)}pp</p>;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
type Props = {
|
||||
player: ScoreSaberPlayer;
|
||||
player: ScoreSaberPlayerToken;
|
||||
};
|
||||
|
||||
export default function PlayerHeader({ player }: Props) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
"use client";
|
||||
|
||||
import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player";
|
||||
import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token";
|
||||
import { formatNumberWithCommas } from "@/common/number-utils";
|
||||
import {
|
||||
CategoryScale,
|
||||
@ -86,7 +86,7 @@ export const options: any = {
|
||||
};
|
||||
|
||||
type Props = {
|
||||
player: ScoreSaberPlayer;
|
||||
player: ScoreSaberPlayerToken;
|
||||
};
|
||||
|
||||
export default function PlayerRankChart({ player }: Props) {
|
||||
|
@ -11,13 +11,13 @@ import Pagination from "../input/pagination";
|
||||
import { Button } from "../ui/button";
|
||||
import { leaderboards } from "@/common/leaderboards";
|
||||
import { ScoreSort } from "@/common/service/score-sort";
|
||||
import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player";
|
||||
import ScoreSaberPlayerScoresPage from "@/common/service/types/scoresaber/scoresaber-player-scores-page";
|
||||
import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token";
|
||||
import ScoreSaberPlayerScoresPageToken from "@/common/model/token/scoresaber/score-saber-player-scores-page-token";
|
||||
import Score from "@/components/score/score";
|
||||
|
||||
type Props = {
|
||||
initialScoreData?: ScoreSaberPlayerScoresPage;
|
||||
player: ScoreSaberPlayer;
|
||||
initialScoreData?: ScoreSaberPlayerScoresPageToken;
|
||||
player: ScoreSaberPlayerToken;
|
||||
sort: ScoreSort;
|
||||
page: number;
|
||||
};
|
||||
@ -88,7 +88,7 @@ export default function PlayerScores({
|
||||
});
|
||||
const [previousPage, setPreviousPage] = useState(page);
|
||||
const [currentScores, setCurrentScores] = useState<
|
||||
ScoreSaberPlayerScoresPage | undefined
|
||||
ScoreSaberPlayerScoresPageToken | undefined
|
||||
>(initialScoreData);
|
||||
|
||||
const {
|
||||
|
@ -1,57 +1,59 @@
|
||||
import { formatNumberWithCommas } from "@/common/number-utils";
|
||||
import StatValue from "@/components/stat-value";
|
||||
import ScoreSaberPlayer from "@/common/service/types/scoresaber/scoresaber-player";
|
||||
import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token";
|
||||
|
||||
type Badge = {
|
||||
name: string;
|
||||
color?: string;
|
||||
create: (player: ScoreSaberPlayer) => string | React.ReactNode | undefined;
|
||||
create: (
|
||||
player: ScoreSaberPlayerToken,
|
||||
) => string | React.ReactNode | undefined;
|
||||
};
|
||||
|
||||
const badges: Badge[] = [
|
||||
{
|
||||
name: "Ranked Play Count",
|
||||
color: "bg-pp",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
create: (player: ScoreSaberPlayerToken) => {
|
||||
return formatNumberWithCommas(player.scoreStats.rankedPlayCount);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Total Ranked Score",
|
||||
color: "bg-pp",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
create: (player: ScoreSaberPlayerToken) => {
|
||||
return formatNumberWithCommas(player.scoreStats.totalRankedScore);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Average Ranked Accuracy",
|
||||
color: "bg-pp",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
create: (player: ScoreSaberPlayerToken) => {
|
||||
return player.scoreStats.averageRankedAccuracy.toFixed(2) + "%";
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Total Play Count",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
create: (player: ScoreSaberPlayerToken) => {
|
||||
return formatNumberWithCommas(player.scoreStats.totalPlayCount);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Total Score",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
create: (player: ScoreSaberPlayerToken) => {
|
||||
return formatNumberWithCommas(player.scoreStats.totalScore);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Total Replays Watched",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
create: (player: ScoreSaberPlayerToken) => {
|
||||
return formatNumberWithCommas(player.scoreStats.replaysWatched);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
type Props = {
|
||||
player: ScoreSaberPlayer;
|
||||
player: ScoreSaberPlayerToken;
|
||||
};
|
||||
|
||||
export default function PlayerStats({ player }: Props) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { copyToClipboard } from "@/common/browser-utils";
|
||||
import ScoreSaberPlayerScore from "@/common/service/types/scoresaber/scoresaber-player-score";
|
||||
import ScoreSaberPlayerScoreToken from "@/common/model/token/scoresaber/score-saber-player-score-token";
|
||||
import BeatSaverMap from "@/common/database/types/beatsaver-map";
|
||||
import { songNameToYouTubeLink } from "@/common/youtube-utils";
|
||||
import BeatSaverLogo from "@/components/logos/beatsaver-logo";
|
||||
@ -12,7 +12,7 @@ import LeaderboardButton from "./leaderboard-button";
|
||||
import ScoreButton from "./score-button";
|
||||
|
||||
type Props = {
|
||||
playerScore: ScoreSaberPlayerScore;
|
||||
playerScore: ScoreSaberPlayerScoreToken;
|
||||
beatSaverMap?: BeatSaverMap;
|
||||
isLeaderboardExpanded: boolean;
|
||||
setIsLeaderboardExpanded: Dispatch<SetStateAction<boolean>>;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import ScoreSaberLeaderboard from "@/common/service/types/scoresaber/scoresaber-leaderboard";
|
||||
import ScoreSaberLeaderboardToken from "@/common/model/token/scoresaber/score-saber-leaderboard-token";
|
||||
import BeatSaverMap from "@/common/database/types/beatsaver-map";
|
||||
import { getDifficultyFromScoreSaberDifficulty } from "@/common/scoresaber-utils";
|
||||
import { songDifficultyToColor } from "@/common/song-utils";
|
||||
@ -9,7 +9,7 @@ import clsx from "clsx";
|
||||
import Image from "next/image";
|
||||
|
||||
type Props = {
|
||||
leaderboard: ScoreSaberLeaderboard;
|
||||
leaderboard: ScoreSaberLeaderboardToken;
|
||||
beatSaverMap?: BeatSaverMap;
|
||||
};
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import ScoreSaberScore from "@/common/service/types/scoresaber/scoresaber-score";
|
||||
import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token";
|
||||
import { formatNumberWithCommas } from "@/common/number-utils";
|
||||
import { timeAgo } from "@/common/time-utils";
|
||||
import { GlobeAmericasIcon } from "@heroicons/react/24/solid";
|
||||
|
||||
type Props = {
|
||||
score: ScoreSaberScore;
|
||||
score: ScoreSaberScoreToken;
|
||||
};
|
||||
|
||||
export default function ScoreRankInfo({ score }: Props) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import ScoreSaberLeaderboard from "@/common/service/types/scoresaber/scoresaber-leaderboard";
|
||||
import ScoreSaberScore from "@/common/service/types/scoresaber/scoresaber-score";
|
||||
import ScoreSaberLeaderboardToken from "@/common/model/token/scoresaber/score-saber-leaderboard-token";
|
||||
import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token";
|
||||
import { formatNumberWithCommas } from "@/common/number-utils";
|
||||
import StatValue from "@/components/stat-value";
|
||||
import { XMarkIcon } from "@heroicons/react/24/solid";
|
||||
@ -9,12 +9,12 @@ import { accuracyToColor } from "@/common/song-utils";
|
||||
type Badge = {
|
||||
name: string;
|
||||
color?: (
|
||||
score: ScoreSaberScore,
|
||||
leaderboard: ScoreSaberLeaderboard,
|
||||
score: ScoreSaberScoreToken,
|
||||
leaderboard: ScoreSaberLeaderboardToken,
|
||||
) => string | undefined;
|
||||
create: (
|
||||
score: ScoreSaberScore,
|
||||
leaderboard: ScoreSaberLeaderboard,
|
||||
score: ScoreSaberScoreToken,
|
||||
leaderboard: ScoreSaberLeaderboardToken,
|
||||
) => string | React.ReactNode | undefined;
|
||||
};
|
||||
|
||||
@ -24,7 +24,7 @@ const badges: Badge[] = [
|
||||
color: () => {
|
||||
return "bg-pp";
|
||||
},
|
||||
create: (score: ScoreSaberScore) => {
|
||||
create: (score: ScoreSaberScoreToken) => {
|
||||
const pp = score.pp;
|
||||
if (pp === 0) {
|
||||
return undefined;
|
||||
@ -34,18 +34,24 @@ const badges: Badge[] = [
|
||||
},
|
||||
{
|
||||
name: "Accuracy",
|
||||
color: (score: ScoreSaberScore, leaderboard: ScoreSaberLeaderboard) => {
|
||||
color: (
|
||||
score: ScoreSaberScoreToken,
|
||||
leaderboard: ScoreSaberLeaderboardToken,
|
||||
) => {
|
||||
const acc = (score.baseScore / leaderboard.maxScore) * 100;
|
||||
return accuracyToColor(acc);
|
||||
},
|
||||
create: (score: ScoreSaberScore, leaderboard: ScoreSaberLeaderboard) => {
|
||||
create: (
|
||||
score: ScoreSaberScoreToken,
|
||||
leaderboard: ScoreSaberLeaderboardToken,
|
||||
) => {
|
||||
const acc = (score.baseScore / leaderboard.maxScore) * 100;
|
||||
return `${acc.toFixed(2)}%`;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Score",
|
||||
create: (score: ScoreSaberScore) => {
|
||||
create: (score: ScoreSaberScoreToken) => {
|
||||
return `${formatNumberWithCommas(score.baseScore)}`;
|
||||
},
|
||||
},
|
||||
@ -59,7 +65,7 @@ const badges: Badge[] = [
|
||||
},
|
||||
{
|
||||
name: "Full Combo",
|
||||
create: (score: ScoreSaberScore) => {
|
||||
create: (score: ScoreSaberScoreToken) => {
|
||||
const fullCombo = score.missedNotes === 0;
|
||||
|
||||
return (
|
||||
@ -81,8 +87,8 @@ const badges: Badge[] = [
|
||||
];
|
||||
|
||||
type Props = {
|
||||
score: ScoreSaberScore;
|
||||
leaderboard: ScoreSaberLeaderboard;
|
||||
score: ScoreSaberScoreToken;
|
||||
leaderboard: ScoreSaberLeaderboardToken;
|
||||
};
|
||||
|
||||
export default function ScoreStats({ score, leaderboard }: Props) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { beatsaverService } from "@/common/service/impl/beatsaver";
|
||||
import ScoreSaberPlayerScore from "@/common/service/types/scoresaber/scoresaber-player-score";
|
||||
import ScoreSaberPlayerScoreToken from "@/common/model/token/scoresaber/score-saber-player-score-token";
|
||||
import BeatSaverMap from "@/common/database/types/beatsaver-map";
|
||||
import LeaderboardScores from "@/components/leaderboard/leaderboard-scores";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
@ -14,7 +14,7 @@ type Props = {
|
||||
/**
|
||||
* The score to display.
|
||||
*/
|
||||
playerScore: ScoreSaberPlayerScore;
|
||||
playerScore: ScoreSaberPlayerScoreToken;
|
||||
};
|
||||
|
||||
export default function Score({ playerScore }: Props) {
|
||||
|
Reference in New Issue
Block a user