"use client" import { useTranslations } from "next-intl" import { Button } from "@/components/ui/button" import { Gem, Sword, User2, Loader2 } from "lucide-react" import { Input } from "@/components/ui/input" import { useState } from "react" import { useToast } from "@/components/ui/use-toast" import { ROLES, Role } from "@/lib/permissions" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" const roleIcons = { [ROLES.DUKE]: Gem, [ROLES.KNIGHT]: Sword, [ROLES.CIVILIAN]: User2, } as const type RoleWithoutEmperor = Exclude export function PromotePanel() { const t = useTranslations("profile.promote") const tCard = useTranslations("profile.card") const [searchText, setSearchText] = useState("") const [loading, setLoading] = useState(false) const [targetRole, setTargetRole] = useState(ROLES.KNIGHT) const { toast } = useToast() const roleNames = { [ROLES.DUKE]: tCard("roles.DUKE"), [ROLES.KNIGHT]: tCard("roles.KNIGHT"), [ROLES.CIVILIAN]: tCard("roles.CIVILIAN"), } as const const handleAction = async () => { if (!searchText) return setLoading(true) try { const res = await fetch("/api/roles/users", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ searchText }) }) const data = await res.json() as { user?: { id: string name?: string username?: string email: string role?: string } error?: string } if (!res.ok) throw new Error(data.error || "未知错误") if (!data.user) { toast({ title: t("noUsers"), description: t("searchPlaceholder"), variant: "destructive" }) return } if (data.user.role === targetRole) { toast({ title: t("updateSuccess"), description: t("updateSuccess"), }) return } const promoteRes = await fetch("/api/roles/promote", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ userId: data.user.id, roleName: targetRole }) }) if (!promoteRes.ok) { const error = await promoteRes.json() as { error: string } throw new Error(error.error || t("updateFailed")) } toast({ title: t("updateSuccess"), description: `${data.user.username || data.user.email} - ${roleNames[targetRole]}`, }) setSearchText("") } catch (error) { toast({ title: t("updateFailed"), description: error instanceof Error ? error.message : t("updateFailed"), variant: "destructive" }) } finally { setLoading(false) } } const Icon = roleIcons[targetRole] return (

{t("title")}

setSearchText(e.target.value)} placeholder={t("searchPlaceholder")} />
) }