From b7ec3ebe0e5e8277827f78a5ef14813a90b9bbad Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 9 Sep 2024 09:24:16 +0100 Subject: [PATCH] cleanup and start work on player page --- src/app/(pages)/player/[...slug]/page.tsx | 119 ++++++++++++++++++ .../player/[id]/[sort]/[page]/page.tsx | 80 ------------ src/app/components/navbar.tsx | 2 +- .../components/{ => player}/claim-profile.tsx | 10 +- src/app/components/player/player-sub-name.tsx | 13 ++ src/app/layout.tsx | 6 +- src/middleware.ts | 2 +- tailwind.config.ts | 103 +++++++-------- 8 files changed, 195 insertions(+), 140 deletions(-) create mode 100644 src/app/(pages)/player/[...slug]/page.tsx delete mode 100644 src/app/(pages)/player/[id]/[sort]/[page]/page.tsx rename src/app/components/{ => player}/claim-profile.tsx (80%) create mode 100644 src/app/components/player/player-sub-name.tsx diff --git a/src/app/(pages)/player/[...slug]/page.tsx b/src/app/(pages)/player/[...slug]/page.tsx new file mode 100644 index 0000000..2e4606d --- /dev/null +++ b/src/app/(pages)/player/[...slug]/page.tsx @@ -0,0 +1,119 @@ +import { scoresaberLeaderboard } from "@/app/common/leaderboard/impl/scoresaber"; +import { ScoreSort } from "@/app/common/leaderboard/sort"; +import ScoreSaberPlayer from "@/app/common/leaderboard/types/scoresaber/scoresaber-player"; +import { formatNumberWithCommas } from "@/app/common/number-utils"; +import ClaimProfile from "@/app/components/player/claim-profile"; +import PlayerSubName from "@/app/components/player/player-sub-name"; +import { Avatar, AvatarFallback, AvatarImage } from "@/app/components/ui/avatar"; +import { format } from "@formkit/tempo"; +import { GlobeAmericasIcon } from "@heroicons/react/24/solid"; +import { Metadata } from "next"; + +const playerSubNames = [ + { + icon: , + render: (player: ScoreSaberPlayer) => { + return

#{formatNumberWithCommas(player.rank)}

; + }, + }, + { + icon: , + render: (player: ScoreSaberPlayer) => { + return

#{formatNumberWithCommas(player.countryRank)}

; + }, + }, + { + render: (player: ScoreSaberPlayer) => { + return

{formatNumberWithCommas(player.pp)}pp

; + }, + }, +]; + +type Props = { + params: { + slug: string[]; + }; +}; + +export async function generateMetadata({ params: { slug } }: Props): Promise { + const id = slug[0]; // The players id + const player = await scoresaberLeaderboard.lookupPlayer(id, false); + if (player === undefined) { + return { + title: `Unknown Player`, + openGraph: { + title: `Unknown Player`, + }, + }; + } + + return { + title: `${player.name}`, + openGraph: { + title: `ScoreSaber Reloaded - ${player.name}`, + description: ` + PP: ${formatNumberWithCommas(player.pp)}pp + Rank: #${formatNumberWithCommas(player.rank)} (#${formatNumberWithCommas(player.countryRank)} ${player.country}) + Joined ScoreSaber: ${format(player.firstSeen, { date: "medium", time: "short" })} + + View the scores for ${player.name}!`, + }, + }; +} + +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 = slug[2] || 1; // The page number + const player = await scoresaberLeaderboard.lookupPlayer(id, false); + + console.log("id", id); + console.log("sort", sort); + console.log("page", page); + + return ( +
+ {player === undefined && ( +
+

idek mate

+
+ )} + {player !== undefined && ( +
+
+
+ + + {player.name} + +
+

{player.name}

+
+ {playerSubNames.map((subName, index) => { + return ( + + {subName.render(player)} + + ); + })} + {/* }> +

#{formatNumberWithCommas(player.rank)}

+
+ }> +

#{formatNumberWithCommas(player.countryRank)}

+
+ +

{formatNumberWithCommas(player.pp)}pp

+
*/} +
+
+ +
+
+
+
+
+ )} +
+ ); +} diff --git a/src/app/(pages)/player/[id]/[sort]/[page]/page.tsx b/src/app/(pages)/player/[id]/[sort]/[page]/page.tsx deleted file mode 100644 index 0bbacc0..0000000 --- a/src/app/(pages)/player/[id]/[sort]/[page]/page.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { scoresaberLeaderboard } from "@/app/common/leaderboard/impl/scoresaber"; -import { ScoreSort } from "@/app/common/leaderboard/sort"; -import { formatNumberWithCommas } from "@/app/common/number-utils"; -import ClaimProfile from "@/app/components/claim-profile"; -import { Avatar, AvatarFallback, AvatarImage } from "@/app/components/ui/avatar"; -import { format } from "@formkit/tempo"; -import { Metadata } from "next"; - -type Props = { - params: { - id: string; - sort: ScoreSort; - page: number; - }; -}; - -export async function generateMetadata({ params: { id } }: Props): Promise { - const player = await scoresaberLeaderboard.lookupPlayer(id, false); - if (player === undefined) { - return { - title: `Unknown Player`, - openGraph: { - title: `Unknown Player`, - }, - }; - } - - return { - title: `${player.name}`, - openGraph: { - title: `ScoreSaber Reloaded - ${player.name}`, - description: ` - PP: ${formatNumberWithCommas(player.pp)}pp - Rank: #${formatNumberWithCommas(player.rank)} (#${formatNumberWithCommas(player.countryRank)} ${player.country}) - Joined ScoreSaber: ${format(player.firstSeen, { date: "medium", time: "short" })} - - View the scores for ${player.name}!`, - }, - }; -} - -export default async function Search({ params: { id, sort, page } }: Props) { - const player = await scoresaberLeaderboard.lookupPlayer(id, false); - console.log("id", id); - console.log("sort", sort); - console.log("page", page); - - return ( -
- {player === undefined && ( -
-

idek mate

-
- )} - {player !== undefined && ( -
-
-
- - - {player.name} - -
-

{player.name}

-
-

#{formatNumberWithCommas(player.rank)}

-

#{formatNumberWithCommas(player.countryRank)}

-

{formatNumberWithCommas(player.pp)}pp

-
-
- -
-
-
-
-
- )} -
- ); -} diff --git a/src/app/components/navbar.tsx b/src/app/components/navbar.tsx index 74b8d66..652388f 100644 --- a/src/app/components/navbar.tsx +++ b/src/app/components/navbar.tsx @@ -30,7 +30,7 @@ const renderNavbarItem = (item: NavbarItem) => ( export default function Navbar() { return ( -
+
{/* Left-aligned items */}
diff --git a/src/app/components/claim-profile.tsx b/src/app/components/player/claim-profile.tsx similarity index 80% rename from src/app/components/claim-profile.tsx rename to src/app/components/player/claim-profile.tsx index da263de..a2e9f4d 100644 --- a/src/app/components/claim-profile.tsx +++ b/src/app/components/player/claim-profile.tsx @@ -2,11 +2,11 @@ import { CheckIcon } from "@heroicons/react/24/solid"; import { useLiveQuery } from "dexie-react-hooks"; -import { setPlayerIdCookie } from "../common/website-utils"; -import useDatabase from "../hooks/use-database"; -import { useToast } from "../hooks/use-toast"; -import { Button } from "./ui/button"; -import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip"; +import { setPlayerIdCookie } from "../../common/website-utils"; +import useDatabase from "../../hooks/use-database"; +import { useToast } from "../../hooks/use-toast"; +import { Button } from "../ui/button"; +import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; type Props = { /** diff --git a/src/app/components/player/player-sub-name.tsx b/src/app/components/player/player-sub-name.tsx new file mode 100644 index 0000000..9fdc754 --- /dev/null +++ b/src/app/components/player/player-sub-name.tsx @@ -0,0 +1,13 @@ +type Props = { + icon?: React.ReactNode; + children: React.ReactNode; +}; + +export default function PlayerSubName({ icon, children }: Props) { + return ( +
+ {icon} + {children} +
+ ); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3a00c27..7eef23b 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -63,8 +63,10 @@ export default function RootLayout({ - -
{children}
+
+ + {children} +
diff --git a/src/middleware.ts b/src/middleware.ts index 42aa3fa..28b1e81 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -8,7 +8,7 @@ export function middleware(request: NextRequest) { const playerIdCookie = cookies.get("playerId"); if (pathname == "/") { if (playerIdCookie) { - return NextResponse.redirect(new URL(`/player/${playerIdCookie.value}/top/1`, request.url)); + return NextResponse.redirect(new URL(`/player/${playerIdCookie.value}`, request.url)); } else { return NextResponse.redirect(new URL("/search", request.url)); } diff --git a/tailwind.config.ts b/tailwind.config.ts index 0aecfcc..3efdbe6 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,62 +1,63 @@ import type { Config } from "tailwindcss"; const config: Config = { - darkMode: ["class"], - content: [ + darkMode: ["class"], + content: [ "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", "./src/components/**/*.{js,ts,jsx,tsx,mdx}", "./src/app/**/*.{js,ts,jsx,tsx,mdx}", ], theme: { - extend: { - colors: { - background: 'hsl(var(--background))', - foreground: 'hsl(var(--foreground))', - card: { - DEFAULT: 'hsl(var(--card))', - foreground: 'hsl(var(--card-foreground))' - }, - popover: { - DEFAULT: 'hsl(var(--popover))', - foreground: 'hsl(var(--popover-foreground))' - }, - primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))' - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))' - }, - muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))' - }, - accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))' - }, - destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))' - }, - border: 'hsl(var(--border))', - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', - chart: { - '1': 'hsl(var(--chart-1))', - '2': 'hsl(var(--chart-2))', - '3': 'hsl(var(--chart-3))', - '4': 'hsl(var(--chart-4))', - '5': 'hsl(var(--chart-5))' - } - }, - borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)' - } - } + extend: { + colors: { + pp: "text-purple-400", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + chart: { + "1": "hsl(var(--chart-1))", + "2": "hsl(var(--chart-2))", + "3": "hsl(var(--chart-3))", + "4": "hsl(var(--chart-4))", + "5": "hsl(var(--chart-5))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + }, }, plugins: [require("tailwindcss-animate")], };