返回 AiToEarn
UserSection.tsx
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
103 lines Plain Text