summaryrefslogtreecommitdiff
path: root/lib/approval-line/table/delete-approval-line-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/approval-line/table/delete-approval-line-dialog.tsx')
-rw-r--r--lib/approval-line/table/delete-approval-line-dialog.tsx168
1 files changed, 168 insertions, 0 deletions
diff --git a/lib/approval-line/table/delete-approval-line-dialog.tsx b/lib/approval-line/table/delete-approval-line-dialog.tsx
new file mode 100644
index 00000000..aa1d8949
--- /dev/null
+++ b/lib/approval-line/table/delete-approval-line-dialog.tsx
@@ -0,0 +1,168 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/components/ui/button"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog"
+import { Badge } from "@/components/ui/badge"
+import { toast } from "sonner"
+import { Loader2, Trash2, AlertTriangle } from "lucide-react"
+import { deleteApprovalLine, getApprovalLineUsage } from "../service"
+import { type ApprovalLine } from "../service"
+
+interface DeleteApprovalLineDialogProps {
+ open: boolean
+ onOpenChange: (open: boolean) => void
+ lines: ApprovalLine[]
+ showTrigger?: boolean
+ onSuccess?: () => void
+}
+
+export function DeleteApprovalLineDialog({
+ open,
+ onOpenChange,
+ lines,
+ showTrigger = true,
+ onSuccess,
+}: DeleteApprovalLineDialogProps) {
+ const [isDeleting, setIsDeleting] = React.useState(false)
+ const [usageInfo, setUsageInfo] = React.useState<{ templateCount: number } | null>(null)
+
+ // 사용량 정보 조회
+ React.useEffect(() => {
+ if (open && lines.length === 1) {
+ getApprovalLineUsage(lines[0].id).then(setUsageInfo)
+ }
+ }, [open, lines])
+
+ const handleDelete = async () => {
+ setIsDeleting(true)
+
+ try {
+ const deletePromises = lines.map((line) => deleteApprovalLine(line.id))
+ const results = await Promise.all(deletePromises)
+
+ const successCount = results.filter((r) => r.success).length
+ const errorCount = results.length - successCount
+
+ if (successCount > 0) {
+ toast.success(`${successCount}개의 결재선이 삭제되었습니다.`)
+ onSuccess?.()
+ onOpenChange(false)
+ }
+
+ if (errorCount > 0) {
+ toast.error(`${errorCount}개의 결재선 삭제에 실패했습니다.`)
+ }
+ } catch (error) {
+ toast.error("삭제 중 오류가 발생했습니다.")
+ } finally {
+ setIsDeleting(false)
+ }
+ }
+
+ const isSingleLine = lines.length === 1
+ const line = isSingleLine ? lines[0] : null
+
+ return (
+ <Dialog open={open} onOpenChange={onOpenChange}>
+ <DialogContent>
+ <DialogHeader>
+ <DialogTitle className="flex items-center gap-2">
+ <Trash2 className="h-5 w-5 text-destructive" />
+ 결재선 삭제
+ </DialogTitle>
+ <DialogDescription>
+ {isSingleLine
+ ? `"${line?.name}" 결재선을 삭제하시겠습니까?`
+ : `${lines.length}개의 결재선을 삭제하시겠습니까?`}
+ </DialogDescription>
+ </DialogHeader>
+
+ <div className="space-y-4">
+ {/* 사용량 정보 표시 */}
+ {isSingleLine && usageInfo && (
+ <div className="p-4 bg-yellow-50 border border-yellow-200 rounded-lg">
+ <div className="flex items-center gap-2 text-yellow-700">
+ <AlertTriangle className="w-4 h-4" />
+ <span className="font-medium">사용 중인 결재선</span>
+ </div>
+ <p className="text-sm text-yellow-600 mt-1">
+ 이 결재선은 {usageInfo.templateCount}개의 템플릿에서 사용되고 있습니다.
+ </p>
+ </div>
+ )}
+
+ {/* 삭제할 결재선 목록 */}
+ <div className="space-y-2">
+ <h4 className="text-sm font-medium">삭제할 결재선:</h4>
+ <div className="space-y-2 max-h-40 overflow-y-auto">
+ {lines.map((line) => (
+ <div
+ key={line.id}
+ className="flex items-center justify-between p-3 border rounded-lg"
+ >
+ <div className="flex-1">
+ <div className="font-medium">{line.name}</div>
+ {line.description && (
+ <div className="text-sm text-gray-500">
+ {line.description}
+ </div>
+ )}
+ <div className="text-xs text-gray-400 mt-1">
+ 결재자 {(line.aplns as any[])?.length || 0}명
+ </div>
+ </div>
+ </div>
+ ))}
+ </div>
+ </div>
+
+ {/* 경고 메시지 */}
+ <div className="p-4 bg-red-50 border border-red-200 rounded-lg">
+ <div className="flex items-center gap-2 text-red-700">
+ <AlertTriangle className="w-4 h-4" />
+ <span className="font-medium">주의</span>
+ </div>
+ <p className="text-sm text-red-600 mt-1">
+ 삭제된 결재선은 복구할 수 없습니다. 이 작업은 되돌릴 수 없습니다.
+ </p>
+ </div>
+ </div>
+
+ <DialogFooter>
+ <Button
+ variant="outline"
+ onClick={() => onOpenChange(false)}
+ disabled={isDeleting}
+ >
+ 취소
+ </Button>
+ <Button
+ variant="destructive"
+ onClick={handleDelete}
+ disabled={isDeleting}
+ >
+ {isDeleting ? (
+ <>
+ <Loader2 className="w-4 h-4 mr-2 animate-spin" />
+ 삭제 중...
+ </>
+ ) : (
+ <>
+ <Trash2 className="w-4 h-4 mr-2" />
+ 삭제
+ </>
+ )}
+ </Button>
+ </DialogFooter>
+ </DialogContent>
+ </Dialog>
+ )
+} \ No newline at end of file