From bee8b12e66811fa957cd8909fd741db7e97b693b Mon Sep 17 00:00:00 2001 From: MaheshtheDev <38828053+MaheshtheDev@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:36:52 +0000 Subject: [PATCH] feat: allow api orgs to nova app (#728) --- apps/web/components/new/settings/account.tsx | 105 +++++++++++++++++-- packages/lib/auth-context.tsx | 32 ++---- 2 files changed, 106 insertions(+), 31 deletions(-) diff --git a/apps/web/components/new/settings/account.tsx b/apps/web/components/new/settings/account.tsx index 3be01f9fb..35194a162 100644 --- a/apps/web/components/new/settings/account.tsx +++ b/apps/web/components/new/settings/account.tsx @@ -11,8 +11,18 @@ import { DialogTrigger, DialogClose, } from "@ui/components/dialog" +import { authClient } from "@lib/auth" +import { Popover, PopoverContent, PopoverTrigger } from "@ui/components/popover" import { useCustomer } from "autumn-js/react" -import { Check, X, Trash2, LoaderIcon, Settings } from "lucide-react" +import { + Check, + X, + Trash2, + LoaderIcon, + Settings, + ChevronDown, + Building2, +} from "lucide-react" import { useState } from "react" function SectionTitle({ children }: { children: React.ReactNode }) { @@ -76,11 +86,25 @@ function PlanFeatureRow({ } export default function Account() { - const { user, org } = useAuth() + const { user, org, setActiveOrg } = useAuth() const autumn = useCustomer() const [isUpgrading, setIsUpgrading] = useState(false) const [deleteConfirmText, setDeleteConfirmText] = useState("") const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false) + const [switchingOrgId, setSwitchingOrgId] = useState(null) + const { data: allOrgs } = authClient.useListOrganizations() + + const handleOrgSwitch = async (orgSlug: string, orgId: string) => { + if (orgId === org?.id) return + setSwitchingOrgId(orgId) + try { + await setActiveOrg(orgSlug) + window.location.reload() + } catch (error) { + console.error("Failed to switch organization:", error) + setSwitchingOrgId(null) + } + } const { memoriesUsed, @@ -163,7 +187,6 @@ export default function Account() { - {/* Organization + Member since */}

Organization

-

+ + + {org?.name ?? "Personal"} + + + + {allOrgs && allOrgs.length > 1 && ( + + {allOrgs.map((organization) => { + const isCurrent = organization.id === org?.id + const isSwitching = switchingOrgId === organization.id + const isConsumer = + organization.metadata?.isConsumer === true + return ( + + ) + })} + )} - > - {org?.name ?? "Personal"} -

+

) => { @@ -52,28 +53,17 @@ export function AuthProvider({ children }: { children: ReactNode }) { // biome-ignore lint/correctness/useExhaustiveDependencies: ignoring the setActiveOrg dependency useEffect(() => { - if (session?.session.activeOrganizationId) { - authClient.organization - .getFullOrganization() - .then((org) => { - if (org.metadata?.isConsumer === true) { - console.log("Consumer organization:", org) - setOrg(org) - } else { - console.log("ALl orgs:", orgs) - const consumerOrg = orgs?.find( - (o) => o.metadata?.isConsumer === true, - ) - if (consumerOrg) { - setActiveOrg(consumerOrg.slug) - } - } - }) - .catch((error) => { - // Silently handle organization fetch failures to prevent unhandled rejections - console.error("Failed to fetch organization:", error) - }) + if (!session?.session.activeOrganizationId || !orgs) return + + const savedSlug = localStorage.getItem("supermemory-consumer-last-org-slug") + + if (savedSlug && orgs.find((o) => o.slug === savedSlug)) { + setActiveOrg(savedSlug) + return } + + if (savedSlug) localStorage.removeItem("supermemory-consumer-last-org-slug") + authClient.organization.getFullOrganization().then(setOrg) }, [session?.session.activeOrganizationId, orgs]) // When a session exists and there is a pending login method recorded,