forked from baron/baron-sso
개발자 권한 신청 승인/취소 및 RP 생성 흐름 개선
This commit is contained in:
@@ -30,6 +30,7 @@ import {
|
||||
import { Textarea } from "../../components/ui/textarea";
|
||||
import {
|
||||
approveDeveloperRequest,
|
||||
cancelDeveloperRequestApproval,
|
||||
fetchDeveloperRequests,
|
||||
rejectDeveloperRequest,
|
||||
requestDeveloperAccess,
|
||||
@@ -72,6 +73,16 @@ export default function DeveloperRequestPage() {
|
||||
},
|
||||
});
|
||||
|
||||
const cancelApprovalMutation = useMutation({
|
||||
mutationFn: ({ id, adminNotes }: { id: number; adminNotes: string }) =>
|
||||
cancelDeveloperRequestApproval(id, adminNotes),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["developer-requests"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["developer-request"] });
|
||||
alert(t("msg.dev.request.cancelled", "승인이 취소되었습니다."));
|
||||
},
|
||||
});
|
||||
|
||||
const handleApprove = (id: number) => {
|
||||
approveMutation.mutate({ id, adminNotes: adminNotes[id] || "" });
|
||||
};
|
||||
@@ -84,6 +95,14 @@ export default function DeveloperRequestPage() {
|
||||
rejectMutation.mutate({ id, adminNotes: adminNotes[id] });
|
||||
};
|
||||
|
||||
const handleCancelApproval = (id: number) => {
|
||||
if (!adminNotes[id]) {
|
||||
alert(t("msg.dev.request.need_cancel_notes", "승인 취소 사유를 입력해주세요."));
|
||||
return;
|
||||
}
|
||||
cancelApprovalMutation.mutate({ id, adminNotes: adminNotes[id] });
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="p-8 text-center">
|
||||
@@ -95,6 +114,10 @@ export default function DeveloperRequestPage() {
|
||||
const hasActiveRequest = requests?.some(
|
||||
(r) => r.status === "pending" || r.status === "approved",
|
||||
);
|
||||
const isActionPending =
|
||||
approveMutation.isPending ||
|
||||
rejectMutation.isPending ||
|
||||
cancelApprovalMutation.isPending;
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
@@ -211,7 +234,7 @@ export default function DeveloperRequestPage() {
|
||||
variant="outline"
|
||||
className="text-destructive hover:bg-destructive/10"
|
||||
onClick={() => handleReject(req.id)}
|
||||
disabled={rejectMutation.isPending}
|
||||
disabled={isActionPending}
|
||||
>
|
||||
<XCircle className="mr-1 h-3 w-3" />
|
||||
{t("ui.common.reject", "반려")}
|
||||
@@ -220,17 +243,44 @@ export default function DeveloperRequestPage() {
|
||||
size="sm"
|
||||
className="bg-emerald-600 hover:bg-emerald-700"
|
||||
onClick={() => handleApprove(req.id)}
|
||||
disabled={approveMutation.isPending}
|
||||
disabled={isActionPending}
|
||||
>
|
||||
<CheckCircle2 className="mr-1 h-3 w-3" />
|
||||
{t("ui.common.approve", "승인")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : req.status === "approved" ? (
|
||||
<div className="flex flex-col gap-2 min-w-[200px] items-end ml-auto">
|
||||
<Input
|
||||
placeholder={t(
|
||||
"ui.dev.request.cancel_notes_placeholder",
|
||||
"승인 취소 사유 입력...",
|
||||
)}
|
||||
className="h-8 text-xs"
|
||||
value={adminNotes[req.id] || ""}
|
||||
onChange={(e) =>
|
||||
setAdminNotes({
|
||||
...adminNotes,
|
||||
[req.id]: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
className="text-destructive hover:bg-destructive/10"
|
||||
onClick={() => handleCancelApproval(req.id)}
|
||||
disabled={isActionPending}
|
||||
>
|
||||
<XCircle className="mr-1 h-3 w-3" />
|
||||
{t("ui.dev.request.cancel_approval", "승인 취소")}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-muted-foreground text-xs italic">
|
||||
{req.status === "approved"
|
||||
? t("ui.common.completed", "처리 완료")
|
||||
{req.status === "cancelled"
|
||||
? t("ui.dev.request.status.cancelled", "승인 취소됨")
|
||||
: t("ui.common.rejected", "반려됨")}
|
||||
</span>
|
||||
)}
|
||||
@@ -282,6 +332,13 @@ function StatusBadge({ status }: { status: string }) {
|
||||
{t("ui.dev.request.status.rejected", "반려됨")}
|
||||
</Badge>
|
||||
);
|
||||
case "cancelled":
|
||||
return (
|
||||
<Badge variant="muted" className="gap-1">
|
||||
<XCircle className="h-3 w-3" />
|
||||
{t("ui.dev.request.status.cancelled", "승인 취소됨")}
|
||||
</Badge>
|
||||
);
|
||||
default:
|
||||
return <Badge variant="muted">{status}</Badge>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user