From b5df1477283ef6b95c684c5fe41b90e9fbbf5225 Mon Sep 17 00:00:00 2001 From: Liam Date: Wed, 11 Sep 2024 23:10:16 +0100 Subject: [PATCH] add bsr, map and yt buttons to scores --- src/app/(pages)/player/[...slug]/page.tsx | 12 +- src/app/(pages)/search/page.tsx | 2 +- src/app/components/player/score.tsx | 45 ----- src/app/components/ui/card.tsx | 76 -------- src/app/components/ui/form.tsx | 178 ------------------ src/app/components/ui/input.tsx | 25 --- src/app/components/ui/label.tsx | 26 --- src/app/components/ui/pagination.tsx | 121 ------------ src/app/layout.tsx | 14 +- src/common/browser-utils.ts | 8 + .../data-fetcher/data-fetcher.ts} | 2 +- src/common/data-fetcher/impl/beatsaver.ts | 49 +++++ .../data-fetcher}/impl/scoresaber.ts | 6 +- .../data-fetcher}/sort.ts | 0 .../types/beatsaver/beatsaver-account.ts | 51 +++++ .../types/beatsaver/beatsaver-map-metadata.ts | 36 ++++ .../types/beatsaver/beatsaver-map-stats.ts | 31 +++ .../types/beatsaver/beatsaver-map.ts | 24 +++ .../types/scoresaber/scoresaber-badge.ts | 0 .../types/scoresaber/scoresaber-difficulty.ts | 0 .../scoresaber-leaderboard-player-info.ts | 0 .../scoresaber/scoresaber-leaderboard.ts | 0 .../types/scoresaber/scoresaber-metadata.ts | 0 .../scoresaber/scoresaber-player-score.ts | 0 .../scoresaber-player-scores-page.ts | 0 .../scoresaber/scoresaber-player-search.ts | 0 .../types/scoresaber/scoresaber-player.ts | 0 .../scoresaber/scoresaber-score-stats.ts | 0 .../types/scoresaber/scoresaber-score.ts | 0 src/{app => }/common/database/database.ts | 8 + src/common/database/types/beatsaver-map.ts | 17 ++ .../common/database/types/settings.ts | 0 src/{app => }/common/image-utils.ts | 2 +- src/{app => }/common/number-utils.ts | 0 src/common/song-utils.ts | 22 +++ src/{app => }/common/string-utils.ts | 0 src/{app => }/common/time-utils.ts | 0 src/{app => }/common/utils.ts | 0 src/{app => }/common/website-utils.ts | 0 src/{app => }/components/background-image.tsx | 2 +- src/{app => }/components/card.tsx | 0 .../components/chart/customized-axis-tick.tsx | 0 src/{app => }/components/country-flag.tsx | 0 src/{app => }/components/input/pagination.tsx | 0 .../components/input/search-player.tsx | 8 +- .../components/loaders/database-loader.tsx | 0 .../components/loaders/fullscreen-loader.tsx | 0 src/components/logos/beatsaver-logo.tsx | 24 +++ .../components/logos/scoresaber-logo.tsx | 0 src/components/logos/youtube-logo.tsx | 30 +++ .../components/navbar/navbar-button.tsx | 0 src/{app => }/components/navbar/navbar.tsx | 0 .../components/navbar/profile-button.tsx | 2 +- .../components/player/claim-profile.tsx | 0 .../components/player/player-data-point.tsx | 0 .../components/player/player-data.tsx | 8 +- .../components/player/player-header.tsx | 4 +- .../components/player/player-rank-chart.tsx | 4 +- .../components/player/player-scores.tsx | 16 +- src/components/player/score/score-button.tsx | 40 ++++ src/components/player/score/score.tsx | 106 +++++++++++ .../components/providers/query-provider.tsx | 0 .../components/providers/theme-provider.tsx | 0 src/{app => }/components/ui/avatar.tsx | 38 ++-- src/{app => }/components/ui/button.tsx | 40 ++-- src/components/ui/card.tsx | 41 ++++ src/components/ui/form.tsx | 138 ++++++++++++++ src/components/ui/input.tsx | 22 +++ src/components/ui/label.tsx | 19 ++ src/components/ui/pagination.tsx | 81 ++++++++ src/{app => }/components/ui/scroll-area.tsx | 2 +- src/{app => }/components/ui/toast.tsx | 2 +- src/{app => }/components/ui/toaster.tsx | 23 +-- src/{app => }/components/ui/tooltip.tsx | 20 +- src/{app => }/hooks/use-database.ts | 0 src/{app => }/hooks/use-toast.ts | 131 +++++++------ src/{app => }/hooks/use-window-dimensions.ts | 0 77 files changed, 899 insertions(+), 657 deletions(-) delete mode 100644 src/app/components/player/score.tsx delete mode 100644 src/app/components/ui/card.tsx delete mode 100644 src/app/components/ui/form.tsx delete mode 100644 src/app/components/ui/input.tsx delete mode 100644 src/app/components/ui/label.tsx delete mode 100644 src/app/components/ui/pagination.tsx create mode 100644 src/common/browser-utils.ts rename src/{app/common/leaderboard/leaderboard.ts => common/data-fetcher/data-fetcher.ts} (96%) create mode 100644 src/common/data-fetcher/impl/beatsaver.ts rename src/{app/common/leaderboard => common/data-fetcher}/impl/scoresaber.ts (94%) rename src/{app/common/leaderboard => common/data-fetcher}/sort.ts (100%) create mode 100644 src/common/data-fetcher/types/beatsaver/beatsaver-account.ts create mode 100644 src/common/data-fetcher/types/beatsaver/beatsaver-map-metadata.ts create mode 100644 src/common/data-fetcher/types/beatsaver/beatsaver-map-stats.ts create mode 100644 src/common/data-fetcher/types/beatsaver/beatsaver-map.ts rename src/{app/common/leaderboard => common/data-fetcher}/types/scoresaber/scoresaber-badge.ts (100%) rename src/{app/common/leaderboard => common/data-fetcher}/types/scoresaber/scoresaber-difficulty.ts (100%) rename src/{app/common/leaderboard => common/data-fetcher}/types/scoresaber/scoresaber-leaderboard-player-info.ts (100%) rename src/{app/common/leaderboard => common/data-fetcher}/types/scoresaber/scoresaber-leaderboard.ts (100%) rename src/{app/common/leaderboard => common/data-fetcher}/types/scoresaber/scoresaber-metadata.ts (100%) rename src/{app/common/leaderboard => common/data-fetcher}/types/scoresaber/scoresaber-player-score.ts (100%) rename src/{app/common/leaderboard => common/data-fetcher}/types/scoresaber/scoresaber-player-scores-page.ts (100%) rename src/{app/common/leaderboard => common/data-fetcher}/types/scoresaber/scoresaber-player-search.ts (100%) rename src/{app/common/leaderboard => common/data-fetcher}/types/scoresaber/scoresaber-player.ts (100%) rename src/{app/common/leaderboard => common/data-fetcher}/types/scoresaber/scoresaber-score-stats.ts (100%) rename src/{app/common/leaderboard => common/data-fetcher}/types/scoresaber/scoresaber-score.ts (100%) rename src/{app => }/common/database/database.ts (88%) create mode 100644 src/common/database/types/beatsaver-map.ts rename src/{app => }/common/database/types/settings.ts (100%) rename src/{app => }/common/image-utils.ts (88%) rename src/{app => }/common/number-utils.ts (100%) create mode 100644 src/common/song-utils.ts rename src/{app => }/common/string-utils.ts (100%) rename src/{app => }/common/time-utils.ts (100%) rename src/{app => }/common/utils.ts (100%) rename src/{app => }/common/website-utils.ts (100%) rename src/{app => }/components/background-image.tsx (96%) rename src/{app => }/components/card.tsx (100%) rename src/{app => }/components/chart/customized-axis-tick.tsx (100%) rename src/{app => }/components/country-flag.tsx (100%) rename src/{app => }/components/input/pagination.tsx (100%) rename src/{app => }/components/input/search-player.tsx (89%) rename src/{app => }/components/loaders/database-loader.tsx (100%) rename src/{app => }/components/loaders/fullscreen-loader.tsx (100%) create mode 100644 src/components/logos/beatsaver-logo.tsx rename src/{app => }/components/logos/scoresaber-logo.tsx (100%) create mode 100644 src/components/logos/youtube-logo.tsx rename src/{app => }/components/navbar/navbar-button.tsx (100%) rename src/{app => }/components/navbar/navbar.tsx (100%) rename src/{app => }/components/navbar/profile-button.tsx (94%) rename src/{app => }/components/player/claim-profile.tsx (100%) rename src/{app => }/components/player/player-data-point.tsx (100%) rename src/{app => }/components/player/player-data.tsx (74%) rename src/{app => }/components/player/player-header.tsx (92%) rename src/{app => }/components/player/player-rank-chart.tsx (93%) rename src/{app => }/components/player/player-scores.tsx (80%) create mode 100644 src/components/player/score/score-button.tsx create mode 100644 src/components/player/score/score.tsx rename src/{app => }/components/providers/query-provider.tsx (100%) rename src/{app => }/components/providers/theme-provider.tsx (100%) rename src/{app => }/components/ui/avatar.tsx (53%) rename src/{app => }/components/ui/button.tsx (55%) create mode 100644 src/components/ui/card.tsx create mode 100644 src/components/ui/form.tsx create mode 100644 src/components/ui/input.tsx create mode 100644 src/components/ui/label.tsx create mode 100644 src/components/ui/pagination.tsx rename src/{app => }/components/ui/scroll-area.tsx (97%) rename src/{app => }/components/ui/toast.tsx (99%) rename src/{app => }/components/ui/toaster.tsx (54%) rename src/{app => }/components/ui/tooltip.tsx (68%) rename src/{app => }/hooks/use-database.ts (100%) rename src/{app => }/hooks/use-toast.ts (57%) rename src/{app => }/hooks/use-window-dimensions.ts (100%) diff --git a/src/app/(pages)/player/[...slug]/page.tsx b/src/app/(pages)/player/[...slug]/page.tsx index 8837dbe..6cae418 100644 --- a/src/app/(pages)/player/[...slug]/page.tsx +++ b/src/app/(pages)/player/[...slug]/page.tsx @@ -1,7 +1,7 @@ -import { scoresaberLeaderboard } from "@/app/common/leaderboard/impl/scoresaber"; -import { ScoreSort } from "@/app/common/leaderboard/sort"; -import { formatNumberWithCommas } from "@/app/common/number-utils"; -import PlayerData from "@/app/components/player/player-data"; +import { scoresaberFetcher } from "@/common/data-fetcher/impl/scoresaber"; +import { ScoreSort } from "@/common/data-fetcher/sort"; +import { formatNumberWithCommas } from "@/common/number-utils"; +import PlayerData from "@/components/player/player-data"; import { format } from "@formkit/tempo"; import { Metadata } from "next"; import { redirect } from "next/navigation"; @@ -14,7 +14,7 @@ type Props = { export async function generateMetadata({ params: { slug } }: Props): Promise { const id = slug[0]; // The players id - const player = await scoresaberLeaderboard.lookupPlayer(id, false); + const player = await scoresaberFetcher.lookupPlayer(id, false); if (player === undefined) { return { title: `Unknown Player`, @@ -42,7 +42,7 @@ export default async function Search({ params: { slug } }: Props) { const id = slug[0]; // The players id const sort: ScoreSort = (slug[1] as ScoreSort) || "recent"; // The sorting method const page = parseInt(slug[2]) || 1; // The page number - const player = await scoresaberLeaderboard.lookupPlayer(id, false); + const player = await scoresaberFetcher.lookupPlayer(id, false); if (player == undefined) { // Invalid player id diff --git a/src/app/(pages)/search/page.tsx b/src/app/(pages)/search/page.tsx index 858ae71..8d3905e 100644 --- a/src/app/(pages)/search/page.tsx +++ b/src/app/(pages)/search/page.tsx @@ -1,4 +1,4 @@ -import SearchPlayer from "@/app/components/input/search-player"; +import SearchPlayer from "@/components/input/search-player"; import { Metadata } from "next"; export const metadata: Metadata = { diff --git a/src/app/components/player/score.tsx b/src/app/components/player/score.tsx deleted file mode 100644 index 97206b7..0000000 --- a/src/app/components/player/score.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import ScoreSaberPlayerScore from "@/app/common/leaderboard/types/scoresaber/scoresaber-player-score"; -import { timeAgo } from "@/app/common/time-utils"; -import { GlobeAmericasIcon } from "@heroicons/react/24/solid"; -import Image from "next/image"; - -type Props = { - /** - * The score to display. - */ - playerScore: ScoreSaberPlayerScore; -}; - -export default function Score({ playerScore }: Props) { - const { score, leaderboard } = playerScore; - - return ( -
-
-
- -

#{score.rank}

-
-

{timeAgo(new Date(score.timeSet))}

-
-
- Song Artwork -
-
-

{leaderboard.songName}

-

{leaderboard.songAuthorName}

-

{leaderboard.levelAuthorName}

-
-
-
-
stats stuff
-
- ); -} diff --git a/src/app/components/ui/card.tsx b/src/app/components/ui/card.tsx deleted file mode 100644 index 76cca06..0000000 --- a/src/app/components/ui/card.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import * as React from "react" - -import { cn } from "@/app/common/utils" - -const Card = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -Card.displayName = "Card" - -const CardHeader = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -CardHeader.displayName = "CardHeader" - -const CardTitle = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)) -CardTitle.displayName = "CardTitle" - -const CardDescription = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)) -CardDescription.displayName = "CardDescription" - -const CardContent = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)) -CardContent.displayName = "CardContent" - -const CardFooter = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -CardFooter.displayName = "CardFooter" - -export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/src/app/components/ui/form.tsx b/src/app/components/ui/form.tsx deleted file mode 100644 index 496cc79..0000000 --- a/src/app/components/ui/form.tsx +++ /dev/null @@ -1,178 +0,0 @@ -"use client" - -import * as React from "react" -import * as LabelPrimitive from "@radix-ui/react-label" -import { Slot } from "@radix-ui/react-slot" -import { - Controller, - ControllerProps, - FieldPath, - FieldValues, - FormProvider, - useFormContext, -} from "react-hook-form" - -import { cn } from "@/app/common/utils" -import { Label } from "@/app/components/ui/label" - -const Form = FormProvider - -type FormFieldContextValue< - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath -> = { - name: TName -} - -const FormFieldContext = React.createContext( - {} as FormFieldContextValue -) - -const FormField = < - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath ->({ - ...props -}: ControllerProps) => { - return ( - - - - ) -} - -const useFormField = () => { - const fieldContext = React.useContext(FormFieldContext) - const itemContext = React.useContext(FormItemContext) - const { getFieldState, formState } = useFormContext() - - const fieldState = getFieldState(fieldContext.name, formState) - - if (!fieldContext) { - throw new Error("useFormField should be used within ") - } - - const { id } = itemContext - - return { - id, - name: fieldContext.name, - formItemId: `${id}-form-item`, - formDescriptionId: `${id}-form-item-description`, - formMessageId: `${id}-form-item-message`, - ...fieldState, - } -} - -type FormItemContextValue = { - id: string -} - -const FormItemContext = React.createContext( - {} as FormItemContextValue -) - -const FormItem = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => { - const id = React.useId() - - return ( - -
- - ) -}) -FormItem.displayName = "FormItem" - -const FormLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => { - const { error, formItemId } = useFormField() - - return ( -