diff --git a/src/components/AppLayout.tsx b/src/components/AppLayout.tsx index 24cae55..0d4af3f 100644 --- a/src/components/AppLayout.tsx +++ b/src/components/AppLayout.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react' -import { useClerk, useOrganization, useUser } from '@clerk/react' +import { useClerk, useOrganization, useOrganizationList, useUser } from '@clerk/react' import { useQuery } from '@tanstack/react-query' import { NavLink, Outlet, useLocation } from 'react-router-dom' import { LANGS, locale, setLang, t, useLang, type Key } from '../i18n' @@ -70,11 +70,57 @@ function CreditBalance() { ) } +// The Learning space card switches the active organization. AuthGate keys the pages by orgId and +// clears the query cache, so Brain, schedules, results and credits all reload for the new one. +function OrgSwitcher() { + const [open, setOpen] = useState(false) + const ref = useRef(null) + const { organization } = useOrganization() + const { setActive, userMemberships } = useOrganizationList({ userMemberships: { infinite: true } }) + + useEffect(() => { + if (!open) return + const onClick = (e: MouseEvent) => { if (!ref.current?.contains(e.target as Node)) setOpen(false) } + const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false) } + document.addEventListener('mousedown', onClick) + document.addEventListener('keydown', onKey) + return () => { document.removeEventListener('mousedown', onClick); document.removeEventListener('keydown', onKey) } + }, [open]) + + const choose = (id: string) => { + setOpen(false) + if (id !== organization?.id) void setActive?.({ organization: id }) + } + + return ( +
+ + {open && ( + + )} +
+ ) +} + export function AppLayout() { useLang() const [help, setHelp] = useState(false) const { user } = useUser() - const { organization } = useOrganization() const { signOut } = useClerk() const { pathname } = useLocation() const current = NAV.find(n => pathname.startsWith(n.to)) @@ -84,10 +130,7 @@ export function AppLayout() {