diff --git a/src/app/(frontend)/layout.tsx b/src/app/(frontend)/layout.tsx index ffa8db2..8bce916 100644 --- a/src/app/(frontend)/layout.tsx +++ b/src/app/(frontend)/layout.tsx @@ -124,6 +124,7 @@ export default async function RootLayout(props: { children: React.ReactNode }) { hasLogistics={isLogistics} showCallsign={user.preferences?.display?.showCallsign ?? false} canImpersonate={await isSuperuser(payload, user)} + preferences={user.preferences} className="border-r" /> diff --git a/src/components/frontend/blocks/AppSidebar.tsx b/src/components/frontend/blocks/AppSidebar.tsx index 2860059..2bdc8cf 100644 --- a/src/components/frontend/blocks/AppSidebar.tsx +++ b/src/components/frontend/blocks/AppSidebar.tsx @@ -10,9 +10,13 @@ import { Search, Send, Shield, + ShoppingBag, + TrendingUp, UserCog, Users, Warehouse, + Maximize, + Minimize, } from "lucide-react"; import { NavCore } from "@/components/frontend/blocks/NavCore"; @@ -25,13 +29,15 @@ import { SidebarHeader, SidebarMenu, SidebarMenuButton, - SidebarMenuItem, + SidebarMenuItem, } from "@/components/ui/sidebar"; import Image from "next/image"; import Link from "next/link"; import XPDisplay from "@/components/frontend/blocks/XPDisplay"; import type { ResolvedLevel } from "@/utils/xp/resolveLevel"; -import { Rank } from "@/payload-types"; +import { Rank, User } from "@/payload-types"; +import { Progress } from "@/components/ui/progress"; +import { updatePreferences } from "@/app/(frontend)/account/actions"; const data = { navMain: [ @@ -45,6 +51,8 @@ const data = { url: "/roster", icon: Users, }, + ], + navHelpdesk: [ { title: "Helpdesk", url: "/helpdesk", @@ -108,22 +116,19 @@ const data = { title: "Deployed Vehicles", url: "/logistics/game-vehicles", }, - { - title: "Banking", - url: "/logistics/banking", - }, - { - title: "Market", - url: "/logistics/market", - }, ], }, ], - navSecondary: [ + navCommerce: [ { - title: "Feedback", - url: "https://onyxsimple.youtrack.cloud", - icon: Send, + title: "Banking", + url: "/logistics/banking", + icon: TrendingUp, + }, + { + title: "Market", + url: "/logistics/market", + icon: ShoppingBag, }, ], navPersonal: [ @@ -138,6 +143,13 @@ const data = { icon: UserCog, }, ], + navSecondary: [ + { + title: "Feedback", + url: "https://onyxsimple.youtrack.cloud", + icon: Send, + }, + ], }; export function AppSidebar({ @@ -148,6 +160,7 @@ export function AppSidebar({ hasLogistics = true, showCallsign = false, canImpersonate = false, + preferences, ...props }: { user: { @@ -161,7 +174,36 @@ export function AppSidebar({ hasLogistics?: boolean; showCallsign?: boolean; canImpersonate?: boolean; + preferences?: NonNullable; } & React.ComponentProps) { + const [isMiniMode, setIsMiniMode] = React.useState( + preferences?.display?.xpDisplayMini ?? false + ); + + // Re-sync when the saved preference changes (e.g. account page save + router.refresh()). + const savedXpDisplayMini = preferences?.display?.xpDisplayMini ?? false; + React.useEffect(() => { + setIsMiniMode(savedXpDisplayMini); + }, [savedXpDisplayMini]); + + const handleToggleXPMode = React.useCallback(async () => { + try { + await updatePreferences({ + mutedAll: preferences?.notifications?.mutedAll ?? false, + mutedTypes: preferences?.notifications?.mutedTypes ?? [], + showCallsign: preferences?.display?.showCallsign ?? false, + showVersionOverlay: preferences?.display?.showVersionOverlay ?? true, + leadOrActual: preferences?.display?.leadOrActual ?? "lead", + discordEnabled: preferences?.discord?.enabled ?? false, + discordMutedTypes: preferences?.discord?.mutedTypes ?? [], + xpDisplayMini: !isMiniMode, + }); + setIsMiniMode(!isMiniMode); + } catch (error) { + console.error("Failed to update XP display preference:", error); + } + }, [isMiniMode, preferences]); + return ( @@ -208,6 +250,8 @@ export function AppSidebar({ )} /> )} + + {/**/} @@ -226,9 +270,32 @@ export function AppSidebar({ } className="mt-auto" /> - +
+
+ {isMiniMode ? ( +
+
+ {xpLevel.levelName} +
+ + {xpLevel.xp.toLocaleString()} + + +
+ ) : ( + + )} + +
+