dify/web/app/account/(commonLayout)/avatar.tsx
Stephen Zhou a84c2d36a3
style: format with vp fmt (#38803)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-12 15:57:46 +00:00

90 lines
3.4 KiB
TypeScript

'use client'
import { Avatar } from '@langgenius/dify-ui/avatar'
import { cn } from '@langgenius/dify-ui/cn'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@langgenius/dify-ui/dropdown-menu'
import { useSuspenseQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { resetUser } from '@/app/components/base/amplitude/utils'
import PremiumBadge from '@/app/components/base/premium-badge'
import { useProviderContext } from '@/context/provider-context'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { useRouter } from '@/next/navigation'
import { useLogout } from '@/service/use-common'
export default function AppSelector() {
const router = useRouter()
const { t } = useTranslation()
// Cache is hydrated by CommonLayoutHydrationBoundary; this hits cache synchronously.
const { data: userProfileResp } = useSuspenseQuery(userProfileQueryOptions())
const userProfile = userProfileResp.profile
const { isEducationAccount } = useProviderContext()
const { mutateAsync: logout } = useLogout()
if (!userProfile) return null
const handleLogout = async () => {
await logout()
resetUser()
// Tokens are now stored in cookies and cleared by backend
router.push('/signin')
}
return (
<DropdownMenu modal={false}>
<DropdownMenuTrigger
aria-label={userProfile.name}
className={cn(
'inline-flex size-8 items-center justify-center rounded-full border-none bg-transparent p-0 text-sm text-text-primary outline-hidden',
'hover:opacity-80 focus-visible:ring-1 focus-visible:ring-components-input-border-hover active:opacity-70 data-popup-open:opacity-80',
)}
>
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} />
</DropdownMenuTrigger>
<DropdownMenuContent
placement="bottom-end"
sideOffset={4}
popupClassName="w-60 max-w-80 divide-y divide-divider-subtle bg-components-panel-bg-blur p-0"
>
<div className="p-1">
<div className="flex flex-nowrap items-center px-3 py-2">
<div className="min-w-0 grow">
<div className="system-md-medium break-all text-text-primary">
{userProfile.name}
{isEducationAccount && (
<PremiumBadge size="s" color="blue" className="ml-1 px-2!">
<span aria-hidden="true" className="mr-1 i-ri-graduation-cap-fill size-3" />
<span className="system-2xs-medium">EDU</span>
</PremiumBadge>
)}
</div>
<div className="system-xs-regular break-all text-text-tertiary">
{userProfile.email}
</div>
</div>
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} />
</div>
</div>
<div className="p-1">
<DropdownMenuItem className="h-9 justify-start px-3" onClick={handleLogout}>
<span
aria-hidden="true"
className="mr-1 i-custom-vender-line-general-log-out-01 flex size-4 text-text-tertiary"
/>
<span className="text-[14px] font-normal text-text-secondary">
{t(($) => $['userProfile.logout'], { ns: 'common' })}
</span>
</DropdownMenuItem>
</div>
</DropdownMenuContent>
</DropdownMenu>
)
}