-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
Expand file tree
/
Copy pathUser.tsx
More file actions
112 lines (103 loc) · 3.27 KB
/
User.tsx
File metadata and controls
112 lines (103 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { Link as RouterLink } from "@tanstack/react-router"
import { ChevronsUpDown, LogOut, Settings } from "lucide-react"
import { useState } from "react"
import { Avatar, AvatarFallback } from "@/components/ui/avatar"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
useSidebar,
} from "@/components/ui/sidebar"
import useAuth from "@/hooks/useAuth"
import { getInitials } from "@/utils"
interface UserInfoProps {
fullName?: string
email?: string
}
function UserInfo({ fullName, email }: UserInfoProps) {
return (
<div className="flex items-center gap-2.5 w-full min-w-0">
<Avatar className="size-8">
<AvatarFallback className="bg-zinc-600 text-white">
{getInitials(fullName || "User")}
</AvatarFallback>
</Avatar>
<div className="flex flex-col items-start min-w-0">
<p className="text-sm font-medium truncate w-full">{fullName}</p>
<p className="text-xs text-muted-foreground truncate w-full">{email}</p>
</div>
</div>
)
}
export function User({ user }: { user: any }) {
const { logout } = useAuth()
const { isMobile, setOpenMobile, closeMobileSidebar } = useSidebar()
const [isMenuOpen, setIsMenuOpen] = useState(false)
if (!user) return null
const handleMenuClick = () => {
setIsMenuOpen(false)
if (isMobile) {
setOpenMobile(false)
}
}
const handleLogout = () => {
setIsMenuOpen(false)
if (isMobile) {
void closeMobileSidebar().then(logout)
return
}
window.requestAnimationFrame(logout)
}
return (
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu open={isMenuOpen} onOpenChange={setIsMenuOpen}>
<DropdownMenuTrigger asChild>
<SidebarMenuButton
size="lg"
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
data-testid="user-menu"
>
<UserInfo fullName={user?.full_name} email={user?.email} />
<ChevronsUpDown className="ml-auto size-4 text-muted-foreground" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg"
side={isMobile ? "bottom" : "right"}
align="end"
sideOffset={4}
>
<DropdownMenuLabel className="p-0 font-normal">
<UserInfo fullName={user?.full_name} email={user?.email} />
</DropdownMenuLabel>
<DropdownMenuSeparator />
<RouterLink to="/settings" onClick={handleMenuClick}>
<DropdownMenuItem>
<Settings />
User Settings
</DropdownMenuItem>
</RouterLink>
<DropdownMenuItem
onSelect={(event) => {
event.preventDefault()
handleLogout()
}}
>
<LogOut />
Log Out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
)
}