/** * 顶栏用户菜单:接 `auth.me` / `auth.logout`,未登录显示登录/注册入口。 */ import type { Locale } from "@app/i18n"; import { t } from "@app/i18n"; import { Avatar, AvatarFallback, AvatarImage, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, toast, } from "@app/ui"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { createTRPCReactClient, trpc } from "../lib/trpc"; const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false } }, }); const trpcClient = createTRPCReactClient(); export interface UserMenuProps { locale?: Locale | undefined; name?: string | undefined; email?: string | undefined; avatarUrl?: string | undefined; } function home(locale: Locale): string { return locale === "zh-CN" ? "/zh-CN" : "/en"; } export default function UserMenu({ locale = "zh-CN", avatarUrl }: UserMenuProps) { return ( ); } function UserMenuInner({ locale, avatarUrl }: { locale: Locale; avatarUrl?: string | undefined }) { const me = trpc.auth.me.useQuery(); const logout = trpc.auth.logout.useMutation({ onSuccess: () => { toast.success(t(locale, "auth.msg.logoutOk")); queryClient.clear(); window.location.reload(); }, onError: (err) => toast.error(err.message || t(locale, "auth.err.generic")), }); const base = home(locale); const user = me.data?.user ?? null; if (me.isPending) { return …; } if (!user) { return ( {t(locale, "auth.menu.login")} {t(locale, "auth.menu.register")} ); } const name = user.name; const initials = name.slice(0, 1); return (
{name} {user.email}
{t(locale, "auth.menu.dashboard")} {t(locale, "auth.menu.settings")} { e.preventDefault(); logout.mutate(); }} disabled={logout.isPending} > {t(locale, "auth.menu.logout")}
); }