ERP-node/frontend/components/admin/RoleDeleteModal.tsx

151 lines
5.4 KiB
TypeScript
Raw Normal View History

2025-10-27 16:40:59 +09:00
"use client";
import React, { useState, useCallback } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { roleAPI, RoleGroup } from "@/lib/api/role";
import { AlertTriangle } from "lucide-react";
interface RoleDeleteModalProps {
isOpen: boolean;
onClose: () => void;
onSuccess?: () => void;
role: RoleGroup | null;
}
/**
*
*
* :
* -
* - CASCADE (, )
*
* shadcn/ui
*/
export function RoleDeleteModal({ isOpen, onClose, onSuccess, role }: RoleDeleteModalProps) {
const [isLoading, setIsLoading] = useState(false);
const [showAlert, setShowAlert] = useState(false);
const [alertMessage, setAlertMessage] = useState("");
const [alertType, setAlertType] = useState<"success" | "error">("error");
// 알림 표시
const displayAlert = useCallback((message: string, type: "success" | "error") => {
setAlertMessage(message);
setAlertType(type);
setShowAlert(true);
setTimeout(() => setShowAlert(false), 3000);
}, []);
// 삭제 핸들러
const handleDelete = useCallback(async () => {
if (!role) return;
setIsLoading(true);
try {
const response = await roleAPI.delete(role.objid);
if (response.success) {
displayAlert("권한 그룹이 삭제되었습니다.", "success");
setTimeout(() => {
onClose();
onSuccess?.();
}, 1500);
} else {
displayAlert(response.message || "삭제에 실패했습니다.", "error");
}
} catch (error) {
console.error("권한 그룹 삭제 오류:", error);
displayAlert("권한 그룹 삭제 중 오류가 발생했습니다.", "error");
} finally {
setIsLoading(false);
}
}, [role, onClose, onSuccess, displayAlert]);
if (!role) return null;
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent className="max-w-[95vw] sm:max-w-[500px]">
<DialogHeader>
<DialogTitle className="text-base sm:text-lg"> </DialogTitle>
</DialogHeader>
<div className="space-y-4">
{/* 경고 메시지 */}
<div className="rounded-lg border border-orange-300 bg-orange-50 p-4">
<div className="flex items-start gap-3">
<AlertTriangle className="mt-0.5 h-5 w-5 flex-shrink-0 text-orange-600" />
<div className="space-y-2">
<p className="text-sm font-semibold text-orange-900"> ?</p>
<p className="text-xs text-orange-800">
. :
</p>
<ul className="list-inside list-disc space-y-1 text-xs text-orange-800">
<li> ({role.memberCount || 0})</li>
<li> ({role.menuCount || 0})</li>
</ul>
</div>
</div>
</div>
{/* 삭제할 권한 그룹 정보 */}
<div className="bg-muted/50 rounded-lg border p-4">
<div className="space-y-2">
<div className="flex justify-between text-sm">
<span className="text-muted-foreground"> </span>
<span className="font-medium">{role.authName}</span>
</div>
<div className="flex justify-between text-sm">
<span className="text-muted-foreground"> </span>
<span className="font-mono font-medium">{role.authCode}</span>
</div>
<div className="flex justify-between text-sm">
<span className="text-muted-foreground"></span>
<span className="font-medium">{role.companyCode}</span>
</div>
{role.memberNames && (
<div className="border-t pt-2">
<span className="text-muted-foreground text-xs">:</span>
<p className="mt-1 text-xs">{role.memberNames}</p>
</div>
)}
</div>
</div>
{/* 알림 메시지 */}
{showAlert && (
<div
className={`rounded-lg border p-3 text-sm ${
alertType === "success"
? "border-green-300 bg-green-50 text-green-800"
: "border-destructive/50 bg-destructive/10 text-destructive"
}`}
>
{alertMessage}
</div>
)}
</div>
<DialogFooter className="gap-2 sm:gap-0">
<Button
variant="outline"
onClick={onClose}
disabled={isLoading}
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
>
</Button>
<Button
variant="destructive"
onClick={handleDelete}
disabled={isLoading}
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
>
{isLoading ? "삭제중..." : "삭제"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}