Files
cstb-next/src/components/auth/AuthButton.tsx

143 lines
4.1 KiB
TypeScript
Raw Normal View History

2025-11-05 11:21:13 +08:00
"use client"
import { Button, Dropdown, DropdownTrigger, DropdownMenu, DropdownItem, Avatar, Spinner } from "@heroui/react"
import { User, Logout, Login, AddUser } from "@icon-park/react"
import { useAuthStore } from "@/store/auth"
import { openLoginPage, openSignupPage } from "@/utils/auth"
import { useDisclosure } from "@heroui/react"
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from "@heroui/react"
export function AuthButton() {
const { state, signOut } = useAuthStore()
const { isOpen, onOpen, onOpenChange } = useDisclosure()
const handleLogin = async () => {
await openLoginPage()
}
const handleSignup = async () => {
await openSignupPage()
}
const handleSignOut = async () => {
await signOut()
onOpenChange()
}
if (state.isLoading) {
return (
<Button
isIconOnly
variant="light"
size="sm"
className="px-2 py-0 rounded transition duration-150 hover:bg-black/10 dark:hover:bg-zinc-100/10 active:scale-95"
>
<Spinner size="sm" />
</Button>
)
}
if (state.isAuthenticated && state.user) {
return (
<>
<Dropdown placement="bottom-end">
<DropdownTrigger>
<Button
isIconOnly
variant="light"
size="sm"
className="px-2 py-0 rounded transition duration-150 hover:bg-black/10 dark:hover:bg-zinc-100/10 active:scale-95"
>
<Avatar
src={state.user.user_metadata?.avatar_url}
name={state.user.email || state.user.id}
size="sm"
className="w-6 h-6"
/>
</Button>
</DropdownTrigger>
<DropdownMenu aria-label="用户菜单">
<DropdownItem
key="profile"
startContent={<User size={16} />}
textValue="用户信息"
>
<div className="flex flex-col">
<span className="text-sm font-medium">{state.user.email}</span>
{state.user.user_metadata?.name && (
<span className="text-xs text-zinc-500">{state.user.user_metadata.name}</span>
)}
</div>
</DropdownItem>
<DropdownItem
key="logout"
startContent={<Logout size={16} />}
color="danger"
onPress={onOpen}
>
退
</DropdownItem>
</DropdownMenu>
</Dropdown>
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
<ModalContent>
{(onClose) => (
<>
<ModalHeader className="flex flex-col gap-1">退</ModalHeader>
<ModalBody>
<p>退</p>
</ModalBody>
<ModalFooter>
<Button color="default" variant="light" onPress={onClose}>
</Button>
<Button
color="danger"
onPress={() => {
handleSignOut()
}}
>
退
</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
</>
)
}
return (
<Dropdown placement="bottom-end">
<DropdownTrigger>
<Button
isIconOnly
variant="light"
size="sm"
className="px-2 py-0 rounded transition duration-150 hover:bg-black/10 dark:hover:bg-zinc-100/10 active:scale-95"
>
<User size={16} />
</Button>
</DropdownTrigger>
<DropdownMenu aria-label="登录菜单">
<DropdownItem
key="login"
startContent={<Login size={16} />}
onPress={handleLogin}
>
</DropdownItem>
<DropdownItem
key="signup"
startContent={<AddUser size={16} />}
onPress={handleSignup}
>
</DropdownItem>
</DropdownMenu>
</Dropdown>
)
}