diff --git a/src/components/Container.tsx b/src/components/Container.tsx
index 14f4730..f4afd33 100644
--- a/src/components/Container.tsx
+++ b/src/components/Container.tsx
@@ -1,6 +1,6 @@
import Image from "next/image";
import Footer from "./Footer";
-import Navbar from "./Navbar";
+import Navbar from "./navbar/Navbar";
export default function Container({ children }: { children: React.ReactNode }) {
return (
diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx
deleted file mode 100644
index b71b166..0000000
--- a/src/components/Navbar.tsx
+++ /dev/null
@@ -1,162 +0,0 @@
-"use client";
-
-import { useSettingsStore } from "@/store/settingsStore";
-import useStore from "@/utils/useStore";
-import {
- CogIcon,
- MagnifyingGlassIcon,
- ServerIcon,
- UserIcon,
-} from "@heroicons/react/20/solid";
-import { GlobeAltIcon, TvIcon } from "@heroicons/react/24/outline";
-import Link from "next/link";
-import Avatar from "./Avatar";
-import { Button } from "./ui/button";
-import { Card } from "./ui/card";
-import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover";
-
-interface ButtonProps {
- text: string;
- icon?: JSX.Element;
- href?: string;
- ariaLabel: string;
-}
-
-function NavbarButton({ text, icon, href, ariaLabel }: ButtonProps) {
- return (
-
- <>
- {icon}
- {text}
- >
-
- );
-}
-
-function FriendsButton() {
- const settingsStore = useStore(useSettingsStore, (state) => state);
-
- return (
-
-
- }
- />
-
-
- {settingsStore?.friends.length == 0 ? (
-
-
-
No friends
-
- Add new friends by clicking below
-
-
-
-
-
-
-
- ) : (
- settingsStore?.friends.map((friend) => {
- return (
-
-
-
-
-
#{friend.rank}
-
{friend.name}
-
-
-
- );
- })
- )}
-
-
- );
-}
-
-export default function Navbar() {
- const settingsStore = useStore(useSettingsStore, (state) => state);
-
- return (
- <>
-
- {settingsStore !== undefined && settingsStore.player && (
-
- }
- href={`/player/${settingsStore.player.id}/top/1`}
- />
- )}
-
-
- {/* TODO: fix hydration error? */}
- {/*
-
-
-
- Click to view your friends
- */}
-
- }
- href="/ranking/global/1"
- />
- }
- href="/overlay/builder"
- />
- }
- href="/analytics"
- />
-
-
-
- }
- href="/search"
- />
- }
- href="/settings"
- />
-
- >
- );
-}
diff --git a/src/components/navbar/FriendsButton.tsx b/src/components/navbar/FriendsButton.tsx
new file mode 100644
index 0000000..dc43b48
--- /dev/null
+++ b/src/components/navbar/FriendsButton.tsx
@@ -0,0 +1,66 @@
+"use client";
+
+import { useSettingsStore } from "@/store/settingsStore";
+import useStore from "@/utils/useStore";
+import { UserIcon } from "@heroicons/react/20/solid";
+import Link from "next/link";
+import Avatar from "../Avatar";
+import { Button } from "../ui/button";
+import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
+import NavbarButton from "./NavbarButton";
+
+export default function FriendsButton() {
+ const settingsStore = useStore(useSettingsStore, (state) => state);
+
+ return (
+
+
+ }
+ />
+
+
+ {settingsStore?.friends.length == 0 ? (
+
+
+
No friends
+
+ Add new friends by clicking below
+
+
+
+
+
+
+
+ ) : (
+ settingsStore?.friends.map((friend) => {
+ return (
+
+
+
+
+
#{friend.rank}
+
{friend.name}
+
+
+
+ );
+ })
+ )}
+
+
+ );
+}
diff --git a/src/components/navbar/Navbar.tsx b/src/components/navbar/Navbar.tsx
new file mode 100644
index 0000000..3de7fb1
--- /dev/null
+++ b/src/components/navbar/Navbar.tsx
@@ -0,0 +1,56 @@
+import {
+ CogIcon,
+ MagnifyingGlassIcon,
+ ServerIcon,
+} from "@heroicons/react/20/solid";
+import { GlobeAltIcon, TvIcon } from "@heroicons/react/24/outline";
+import { Card } from "../ui/card";
+import FriendsButton from "./FriendsButton";
+import NavbarButton from "./NavbarButton";
+import YouButton from "./YouButton";
+
+export default function Navbar() {
+ return (
+ <>
+
+
+
+
+
+ }
+ href="/ranking/global/1"
+ />
+ }
+ href="/overlay/builder"
+ />
+ }
+ href="/analytics"
+ />
+
+
+
+ }
+ href="/search"
+ />
+ }
+ href="/settings"
+ />
+
+ >
+ );
+}
diff --git a/src/components/navbar/NavbarButton.tsx b/src/components/navbar/NavbarButton.tsx
new file mode 100644
index 0000000..c896a2c
--- /dev/null
+++ b/src/components/navbar/NavbarButton.tsx
@@ -0,0 +1,26 @@
+interface ButtonProps {
+ text: string;
+ icon?: JSX.Element;
+ href?: string;
+ ariaLabel: string;
+}
+
+export default function NavbarButton({
+ text,
+ icon,
+ href,
+ ariaLabel,
+}: ButtonProps) {
+ return (
+
+ <>
+ {icon}
+ {text}
+ >
+
+ );
+}
diff --git a/src/components/navbar/YouButton.tsx b/src/components/navbar/YouButton.tsx
new file mode 100644
index 0000000..a3110f7
--- /dev/null
+++ b/src/components/navbar/YouButton.tsx
@@ -0,0 +1,29 @@
+"use client";
+
+import { useSettingsStore } from "@/store/settingsStore";
+import { useStore } from "zustand";
+import Avatar from "../Avatar";
+import NavbarButton from "./NavbarButton";
+
+export default function YouButton() {
+ const settingsStore = useStore(useSettingsStore, (state) => state);
+
+ if (!settingsStore || !settingsStore.player) {
+ return null;
+ }
+
+ return (
+
+ }
+ href={`/player/${settingsStore.player.id}/top/1`}
+ />
+ );
+}
diff --git a/src/components/player/PlayerInfo.tsx b/src/components/player/PlayerInfo.tsx
index 32cfa69..4d54755 100644
--- a/src/components/player/PlayerInfo.tsx
+++ b/src/components/player/PlayerInfo.tsx
@@ -1,120 +1,19 @@
-"use client";
-
import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
-import { useScoresaberScoresStore } from "@/store/scoresaberScoresStore";
-import { useSettingsStore } from "@/store/settingsStore";
import { formatNumber } from "@/utils/numberUtils";
-import { getAveragePp, getHighestPpPlay } from "@/utils/scoresaber/scores";
import { normalizedRegionName } from "@/utils/utils";
-import {
- GlobeAsiaAustraliaIcon,
- HomeIcon,
- UserIcon,
- XMarkIcon,
-} from "@heroicons/react/20/solid";
-import dynamic from "next/dynamic";
-import { useEffect, useRef, useState } from "react";
-import { toast } from "react-toastify";
-import { useStore } from "zustand";
+import { GlobeAsiaAustraliaIcon } from "@heroicons/react/20/solid";
import Avatar from "../Avatar";
-import Button from "../Button";
import Card from "../Card";
import CountyFlag from "../CountryFlag";
import Label from "../Label";
-
-const PPGainLabel = dynamic(() => import("./PPGainLabel"));
+import PlayerInfoExtraLabels from "./PlayerInfoExtraLabels";
+import PlayerSettingsButtons from "./PlayerSettingsButtons";
type PlayerInfoProps = {
playerData: ScoresaberPlayer;
};
export default function PlayerInfo({ playerData }: PlayerInfoProps) {
- const [mounted, setMounted] = useState(false);
- const playerId = playerData.id;
- const settingsStore = useStore(useSettingsStore, (store) => store);
- const playerScoreStore = useStore(useScoresaberScoresStore, (store) => store);
-
- // Whether we have scores for this player in the local database
- const hasLocalScores = playerScoreStore?.exists(playerId);
-
- const toastId: any = useRef(null);
-
- useEffect(() => {
- setMounted(true);
- }, []);
-
- async function claimProfile() {
- settingsStore?.setProfile(playerData);
- addProfile(false);
- }
-
- async function addFriend() {
- const friend = await settingsStore?.addFriend(playerData.id);
- if (!friend) {
- toast.error(`Failed to add ${playerData.name} as a friend`);
- return;
- }
- addProfile(true);
- }
-
- async function removeFriend() {
- settingsStore?.removeFriend(playerData.id);
-
- toast.success(`Successfully removed ${playerData.name} as a friend`);
- }
-
- async function addProfile(isFriend: boolean) {
- if (!useScoresaberScoresStore.getState().exists(playerId)) {
- if (!isFriend) {
- toast.success(`Successfully set ${playerData.name} as your profile`);
- } else {
- toast.success(`Successfully added ${playerData.name} as a friend`);
- }
-
- const reponse = await playerScoreStore?.addOrUpdatePlayer(
- playerId,
- (page, totalPages) => {
- const autoClose = page == totalPages ? 5000 : false;
-
- if (page == 1) {
- toastId.current = toast.info(
- `Fetching scores for ${playerData.name} page ${page}/${totalPages}`,
- {
- autoClose: autoClose,
- progress: page / totalPages,
- },
- );
- } else {
- if (page != totalPages) {
- toast.update(toastId.current, {
- progress: page / totalPages,
- render: `Fetching scores for ${playerData.name} page ${page}/${totalPages}`,
- autoClose: autoClose,
- });
- } else {
- toast.update(toastId.current, {
- progress: 0,
- render: `Successfully fetched scores for ${playerData.name}`,
- autoClose: autoClose,
- type: "success",
- });
- }
- }
-
- console.log(
- `Fetching scores for ${playerId} (${page}/${totalPages})`,
- );
- },
- );
- if (reponse?.error) {
- toast.error("Failed to fetch scores");
- console.log(reponse.message);
- return;
- }
- }
- }
-
- const isOwnProfile = settingsStore.player?.id == playerId;
const scoreStats = playerData.scoreStats;
return (
@@ -129,42 +28,7 @@ export default function PlayerInfo({ playerData }: PlayerInfoProps) {
{/* Settings Buttons */}
- {mounted && (
- <>
- {!isOwnProfile && (
-
@@ -261,30 +125,7 @@ export default function PlayerInfo({ playerData }: PlayerInfoProps) {
value={formatNumber(scoreStats.replaysWatched)}
/>
- {hasLocalScores && (
- <>
-