"use client" import { Logo } from "@ui/assets/Logo" import { UserProfileMenu } from "@/components/user-profile-menu" import { useAuth } from "@lib/auth-context" import { motion } from "motion/react" import NovaOrb from "@/components/nova/nova-orb" import { useState, useEffect, useRef } from "react" import { cn } from "@lib/utils" import { dmSansClassName } from "@/lib/fonts" import Account from "@/components/settings/account" import Integrations from "@/components/settings/integrations" import ConnectionsMCP from "@/components/settings/connections-mcp" import Support from "@/components/settings/support" import { ErrorBoundary } from "@/components/error-boundary" import { useRouter } from "next/navigation" import { useIsMobile } from "@hooks/use-mobile" import { useLocalStorageUsername } from "@hooks/use-local-storage-username" import { analytics } from "@/lib/analytics" import { Sun } from "lucide-react" const TABS = ["account", "integrations", "connections", "support"] as const type SettingsTab = (typeof TABS)[number] type NavItem = { id: SettingsTab label: string description: string icon: React.ReactNode } const NAV_ITEMS: NavItem[] = [ { id: "account", label: "Account & Billing", description: "Manage your profile, plan, usage and payments", icon: ( ), }, { id: "integrations", label: "Integrations", description: "Save, sync and search memories across tools", icon: , }, { id: "connections", label: "Connections & MCP", description: "Sync with Google Drive, Notion, OneDrive and MCP client", icon: ( ), }, { id: "support", label: "Support & Help", description: "Find answers or share feedback. We're here to help.", icon: ( ), }, ] function parseHashToTab(hash: string): SettingsTab { const cleaned = hash.replace("#", "").toLowerCase() return TABS.includes(cleaned as SettingsTab) ? (cleaned as SettingsTab) : "account" } export function UserSupermemory({ name }: { name: string }) { return ( {name.split(" ")[0]}'s supermemory ) } export default function SettingsPage() { const { user } = useAuth() const [activeTab, setActiveTab] = useState("account") const hasInitialized = useRef(false) const router = useRouter() const isMobile = useIsMobile() const localStorageUsername = useLocalStorageUsername() useEffect(() => { if (hasInitialized.current) return hasInitialized.current = true const hash = window.location.hash const tab = parseHashToTab(hash) setActiveTab(tab) analytics.settingsTabChanged({ tab }) // If no hash or invalid hash, push #account if (!hash || !TABS.includes(hash.replace("#", "") as SettingsTab)) { window.history.pushState(null, "", "#account") } }, []) useEffect(() => { const handleHashChange = () => { const tab = parseHashToTab(window.location.hash) setActiveTab(tab) analytics.settingsTabChanged({ tab }) } window.addEventListener("hashchange", handleHashChange) return () => window.removeEventListener("hashchange", handleHashChange) }, []) const headerDisplayName = user?.displayUsername || localStorageUsername || user?.name || "" const headerPossessive = headerDisplayName ? `${headerDisplayName.split(" ")[0]}'s` : "" return ( router.push("/")} className={cn( "flex items-center min-w-0 rounded-lg py-1 pr-2 -ml-1 pl-1", "hover:bg-white/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 transition-colors cursor-pointer text-left", )} > {headerDisplayName ? ( {headerPossessive} supermemory ) : ( supermemory )} / Settings {!isMobile && ( )} {NAV_ITEMS.map((item) => ( { window.location.hash = item.id setActiveTab(item.id) analytics.settingsTabChanged({ tab: item.id }) }} className={cn( "rounded-xl transition-colors flex items-start gap-3 shrink-0", isMobile ? "px-3 py-2 text-sm" : "text-left p-4", activeTab === item.id ? "bg-[#14161A] text-white shadow-[inset_2.42px_2.42px_4.263px_rgba(11,15,21,0.7)]" : "text-white/60 hover:text-white hover:bg-[#14161A] hover:shadow-[inset_2.42px_2.42px_4.263px_rgba(11,15,21,0.7)]", )} > {item.icon} {isMobile ? ( {item.label} ) : ( {item.label} {item.description} )} ))} Something went wrong loading this section.{" "} window.location.reload()} > Reload } > {activeTab === "account" && } {activeTab === "integrations" && } {activeTab === "connections" && } {activeTab === "support" && } ) }
{name.split(" ")[0]}'s
supermemory
{headerPossessive}