| 1 | /** |
| 2 | * UserSection - 用户头像/登录按钮区域 |
| 3 | */ |
| 4 | |
| 5 | 'use client' |
| 6 | |
| 7 | import type { UserSectionProps } from '../types' |
| 8 | import { useTransClient } from '@/app/i18n/client' |
| 9 | import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' |
| 10 | import { Button } from '@/components/ui/button' |
| 11 | import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' |
| 12 | import { cn } from '@/utils/className' |
| 13 | import { useUserStore } from '@/store/user' |
| 14 | import { getOssUrl } from '@/utils/oss' |
| 15 | |
| 16 | /** 用户头像组件 */ |
| 17 | function UserAvatar({ |
| 18 | collapsed, |
| 19 | onOpenSettings, |
| 20 | }: { |
| 21 | collapsed: boolean |
| 22 | onOpenSettings: () => void |
| 23 | }) { |
| 24 | const userInfo = useUserStore(state => state.userInfo) |
| 25 | const { t } = useTransClient('common') |
| 26 | |
| 27 | if (!userInfo) { |
| 28 | return null |
| 29 | } |
| 30 | |
| 31 | const handleClick = () => { |
| 32 | onOpenSettings() |
| 33 | } |
| 34 | |
| 35 | return ( |
| 36 | <TooltipProvider> |
| 37 | <Tooltip> |
| 38 | <TooltipTrigger asChild> |
| 39 | <button |
| 40 | onClick={handleClick} |
| 41 | className={cn( |
| 42 | 'flex w-full cursor-pointer items-center rounded-lg border-none bg-transparent transition-colors hover:bg-accent', |
| 43 | collapsed ? 'justify-center p-1' : 'gap-2 px-2 py-1.5', |
| 44 | )} |
| 45 | > |
| 46 | <Avatar className="h-8 w-8 shrink-0 border border-border"> |
| 47 | <AvatarImage src={getOssUrl(userInfo.avatar) || ''} alt={userInfo.name || t('unknownUser')} /> |
| 48 | <AvatarFallback className="bg-muted-foreground font-semibold text-background"> |
| 49 | {userInfo.name?.charAt(0)?.toUpperCase() || 'U'} |
| 50 | </AvatarFallback> |
| 51 | </Avatar> |
| 52 | |
| 53 | {!collapsed && ( |
| 54 | <div className="flex min-w-0 flex-1 flex-col items-start"> |
| 55 | <span className="w-full truncate text-sm font-medium text-foreground text-left"> |
| 56 | {userInfo.name || t('unknownUser')} |
| 57 | </span> |
| 58 | </div> |
| 59 | )} |
| 60 | </button> |
| 61 | </TooltipTrigger> |
| 62 | {collapsed && ( |
| 63 | <TooltipContent side="right"> |
| 64 | <p>{t('profile')}</p> |
| 65 | </TooltipContent> |
| 66 | )} |
| 67 | </Tooltip> |
| 68 | </TooltipProvider> |
| 69 | ) |
| 70 | } |
| 71 | |
| 72 | export function UserSection({ collapsed, onLogin, onOpenSettings }: UserSectionProps) { |
| 73 | const token = useUserStore(state => state.token) |
| 74 | const { t } = useTransClient('common') |
| 75 | |
| 76 | if (token) { |
| 77 | return <UserAvatar collapsed={collapsed} onOpenSettings={onOpenSettings} /> |
| 78 | } |
| 79 | |
| 80 | if (collapsed) { |
| 81 | return ( |
| 82 | <TooltipProvider> |
| 83 | <Tooltip> |
| 84 | <TooltipTrigger asChild> |
| 85 | <Button onClick={onLogin} size="icon" className="h-9 w-9"> |
| 86 | <span className="text-sm font-semibold">In</span> |
| 87 | </Button> |
| 88 | </TooltipTrigger> |
| 89 | <TooltipContent side="right"> |
| 90 | <p>{t('login')}</p> |
| 91 | </TooltipContent> |
| 92 | </Tooltip> |
| 93 | </TooltipProvider> |
| 94 | ) |
| 95 | } |
| 96 | |
| 97 | return ( |
| 98 | <Button onClick={onLogin} className="mt-1 w-full"> |
| 99 | {t('login')} |
| 100 | </Button> |
| 101 | ) |
| 102 | } |
| 103 |