feat(role): add CreateRoleDrawer component and integrate role creation functionality

This commit is contained in:
mlogclub
2026-04-23 14:05:13 +08:00
parent a769df5d44
commit e616169c41
4 changed files with 274 additions and 3 deletions
+49
View File
@@ -22,6 +22,7 @@ import {
import { CSS } from "@dnd-kit/utilities"
import {
GripVerticalIcon,
PlusIcon,
RefreshCwIcon,
ShieldCheckIcon,
ShieldIcon,
@@ -30,16 +31,19 @@ import { toast } from "sonner"
import {
assignRolePermissions,
createRole,
fetchPermissions,
fetchRoleDetail,
fetchRoles,
type AdminPermission,
type AdminRole,
type CreateAdminRolePayload,
type PageResult,
updateRoleSort,
} from "@/lib/api/admin"
import { cn } from "@/lib/utils"
import { AssignPermissionsDrawer } from "./_components/assign-permissions"
import { CreateRoleDrawer } from "./_components/create"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
@@ -148,6 +152,8 @@ function SortableRoleRow({
export default function DashboardRolesPage() {
const [loading, setLoading] = useState(true)
const [sorting, setSorting] = useState(false)
const [creatingOpen, setCreatingOpen] = useState(false)
const [savingCreate, setSavingCreate] = useState(false)
const [savingPermissions, setSavingPermissions] = useState(false)
const [assignPermissionsLoading, setAssignPermissionsLoading] = useState(false)
const [assigningRole, setAssigningRole] = useState<AdminRole | null>(null)
@@ -184,6 +190,31 @@ export default function DashboardRolesPage() {
}
}
function handleCreateDrawerOpenChange(open: boolean) {
if (savingCreate) {
return
}
setCreatingOpen(open)
}
async function handleCreateRole(payload: CreateAdminRolePayload) {
if (savingCreate) {
return
}
setSavingCreate(true)
try {
const role = await createRole(payload)
toast.success(`已创建角色 ${role.name}`)
setCreatingOpen(false)
await loadRoles()
} catch (error) {
toast.error(error instanceof Error ? error.message : "创建角色失败")
} finally {
setSavingCreate(false)
}
}
async function openAssignPermissionsDrawer(role: AdminRole) {
setActionLoadingId(role.id)
setAssigningRole(role)
@@ -279,9 +310,20 @@ export default function DashboardRolesPage() {
void loadRoles()
}, [])
const defaultSortNo =
result.results.reduce((max, item) => Math.max(max, item.sortNo), -1) + 1
return (
<div className="flex flex-1 flex-col gap-6 p-4 lg:p-6">
<div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-end">
<Button
type="button"
onClick={() => setCreatingOpen(true)}
disabled={loading || sorting}
>
<PlusIcon className="size-4" />
</Button>
<Button onClick={() => void loadRoles()} disabled={loading || sorting}>
<RefreshCwIcon className={cn((loading || sorting) && "animate-spin")} />
@@ -353,6 +395,13 @@ export default function DashboardRolesPage() {
onOpenChange={handleAssignPermissionsOpenChange}
onSubmit={handleAssignPermissions}
/>
<CreateRoleDrawer
open={creatingOpen}
saving={savingCreate}
defaultSortNo={defaultSortNo}
onOpenChange={handleCreateDrawerOpenChange}
onSubmit={handleCreateRole}
/>
</div>
)
}