The submodule collapse was only half applied: .gitmodules was deleted but backend/ and frontend/ were still recorded as gitlinks, so none of their files were tracked. Replace the gitlinks with the real trees. Also untrack .env (it carried placeholder secrets) in favour of a tracked .env.example, drop the committed __pycache__, and narrow the blanket *.png ignore that would have swallowed design assets.
98 lines
2.9 KiB
TypeScript
98 lines
2.9 KiB
TypeScript
import { Link as RouterLink } from "@tanstack/react-router"
|
|
import { ChevronsUpDown, LogOut, Settings } from "lucide-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 } = useSidebar()
|
|
|
|
if (!user) return null
|
|
|
|
const handleMenuClick = () => {
|
|
if (isMobile) {
|
|
setOpenMobile(false)
|
|
}
|
|
}
|
|
const handleLogout = async () => {
|
|
logout()
|
|
}
|
|
|
|
return (
|
|
<SidebarMenu>
|
|
<SidebarMenuItem>
|
|
<DropdownMenu>
|
|
<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 onClick={handleLogout}>
|
|
<LogOut />
|
|
Log Out
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</SidebarMenuItem>
|
|
</SidebarMenu>
|
|
)
|
|
}
|