109 lines
2.8 KiB
TypeScript
109 lines
2.8 KiB
TypeScript
"use client";
|
|
|
|
import { useRouter } from "next/navigation";
|
|
import { useState } from "react";
|
|
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
} from "@/components/ui/dropdown-menu";
|
|
import { Button } from "@/components/ui/button";
|
|
import { authClient } from "@/lib/auth-client";
|
|
import { MoreHorizontal, ShieldCheck, User, Ban, CircleCheck, Loader2 } from "lucide-react";
|
|
|
|
type UserRow = {
|
|
id: string;
|
|
name: string;
|
|
email: string;
|
|
role: string;
|
|
banned: boolean;
|
|
};
|
|
|
|
export function UserActions({ user }: { user: UserRow }) {
|
|
const router = useRouter();
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
async function setRole(role: "admin" | "user") {
|
|
setLoading(true);
|
|
const { error } = await authClient.admin.setRole({
|
|
userId: user.id,
|
|
role,
|
|
});
|
|
setLoading(false);
|
|
if (error) {
|
|
console.error("设置角色失败:", error.message);
|
|
return;
|
|
}
|
|
router.refresh();
|
|
}
|
|
|
|
async function toggleBan() {
|
|
setLoading(true);
|
|
if (user.banned) {
|
|
const { error } = await authClient.admin.unbanUser({ userId: user.id });
|
|
setLoading(false);
|
|
if (error) {
|
|
console.error("解封失败:", error.message);
|
|
return;
|
|
}
|
|
} else {
|
|
const { error } = await authClient.admin.banUser({
|
|
userId: user.id,
|
|
banReason: "管理员手动封禁",
|
|
});
|
|
setLoading(false);
|
|
if (error) {
|
|
console.error("封禁失败:", error.message);
|
|
return;
|
|
}
|
|
}
|
|
router.refresh();
|
|
}
|
|
|
|
return (
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger
|
|
render={
|
|
<Button variant="ghost" size="icon-sm" disabled={loading} />
|
|
}
|
|
>
|
|
{loading ? (
|
|
<Loader2 className="size-4 animate-spin" />
|
|
) : (
|
|
<MoreHorizontal className="size-4" />
|
|
)}
|
|
<span className="sr-only">操作菜单</span>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" className="w-40">
|
|
<DropdownMenuLabel>设置角色</DropdownMenuLabel>
|
|
<DropdownMenuItem onClick={() => setRole("admin")}>
|
|
<ShieldCheck className="size-4" />
|
|
管理员
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem onClick={() => setRole("user")}>
|
|
<User className="size-4" />
|
|
普通用户
|
|
</DropdownMenuItem>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem onClick={toggleBan}>
|
|
{user.banned ? (
|
|
<>
|
|
<CircleCheck className="size-4" />
|
|
解除封禁
|
|
</>
|
|
) : (
|
|
<>
|
|
<Ban className="size-4" />
|
|
封禁用户
|
|
</>
|
|
)}
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
);
|
|
}
|