2026-04-10 00:36:46 +05:30

122 lines
3.6 KiB
TypeScript

import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import type { UserSummary } from "../types";
import { fetchAdminJson, getAdminErrorMessage } from "../api";
type RoleAction = "make-admin" | "revoke-admin" | "make-super-admin";
type RoleActionsProps = {
target: UserSummary;
isSelf: boolean;
isSuperAdmin: boolean;
onUpdated: () => void;
};
const actionLabels: Record<RoleAction, string> = {
"make-admin": "Grant Admin",
"revoke-admin": "Revoke Admin",
"make-super-admin": "Make Super Admin",
};
const actionDescriptions: Record<RoleAction, string> = {
"make-admin": "Are you sure you want to promote this user to ADMIN?",
"revoke-admin": "Are you sure you want to revoke admin privileges for this user?",
"make-super-admin": "Are you sure you want to promote this user to SUPER_ADMIN?",
};
const actionEndpoint: Record<RoleAction, string> = {
"make-admin": "make-admin",
"revoke-admin": "revoke-admin",
"make-super-admin": "make-super-admin",
};
export default function RoleActions({ target, isSelf, isSuperAdmin, onUpdated }: RoleActionsProps) {
const [action, setAction] = useState<RoleAction | null>(null);
const [error, setError] = useState<string | null>(null);
const [isWorking, setIsWorking] = useState(false);
if (!isSuperAdmin) {
return null;
}
const disabledDemote = isSelf && target.role === "SUPER_ADMIN";
const handleConfirm = async () => {
if (!action) {
return;
}
setIsWorking(true);
setError(null);
try {
await fetchAdminJson(
`admin/users/${target.user_id}/${actionEndpoint[action]}`,
{ method: "POST" },
);
onUpdated();
setAction(null);
} catch (err) {
const message = getAdminErrorMessage(err, "Role update failed.");
setError(message);
} finally {
setIsWorking(false);
}
};
return (
<div className="flex flex-wrap gap-2">
<Button
variant="outline"
size="sm"
disabled={target.role === "ADMIN" || target.role === "SUPER_ADMIN"}
onClick={() => setAction("make-admin")}
>
{actionLabels["make-admin"]}
</Button>
<Button
variant="outline"
size="sm"
disabled={disabledDemote || target.role === "USER"}
onClick={() => setAction("revoke-admin")}
>
{actionLabels["revoke-admin"]}
</Button>
<Button
variant="secondary"
size="sm"
disabled={target.role === "SUPER_ADMIN"}
onClick={() => setAction("make-super-admin")}
>
{actionLabels["make-super-admin"]}
</Button>
<Dialog open={!!action} onOpenChange={(open) => !open && setAction(null)}>
<DialogContent>
<DialogHeader>
<DialogTitle>{action ? actionLabels[action] : "Confirm role change"}</DialogTitle>
<DialogDescription>
{action ? actionDescriptions[action] : ""}
</DialogDescription>
</DialogHeader>
{error && <p className="text-xs text-destructive">{error}</p>}
<DialogFooter className="flex flex-col gap-2 sm:flex-row sm:justify-end">
<Button variant="outline" onClick={() => setAction(null)} disabled={isWorking}>
Cancel
</Button>
<Button onClick={handleConfirm} disabled={isWorking}>
{isWorking ? "Updating..." : "Confirm"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
);
}