summaryrefslogtreecommitdiff
path: root/lib/evaluation-target-list/table/delete-targets-dialog.tsx
blob: 5f5493c2dc2d333070e67360f8f5650f413b8593 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
"use client"

import * as React from "react"
import { Trash2, AlertTriangle } from "lucide-react"
import { toast } from "sonner"

import { Button } from "@/components/ui/button"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog"
import { Badge } from "@/components/ui/badge"
import { ScrollArea } from "@/components/ui/scroll-area"
import { EvaluationTargetWithDepartments } from "@/db/schema"
import { deleteEvaluationTargets } from "../service" 
interface DeleteTargetsDialogProps {
  open: boolean
  onOpenChange: (open: boolean) => void
  targets: EvaluationTargetWithDepartments[]
  onSuccess?: () => void
}

export function DeleteTargetsDialog({
  open,
  onOpenChange,
  targets,
  onSuccess
}: DeleteTargetsDialogProps) {
  const [isLoading, setIsLoading] = React.useState(false)

  // PENDING 상태인 타겟들만 필터링 (추가 안전장치)
  const pendingTargets = React.useMemo(() => {
    return targets.filter(target => target.status === "PENDING")
  }, [targets])


  const handleDelete = async () => {
    if (pendingTargets.length === 0) {
      toast.error("삭제할 수 있는 평가 대상이 없습니다.")
      return
    }

    setIsLoading(true)
    try {
      const targetIds = pendingTargets.map(target => target.id)
      const result = await deleteEvaluationTargets(targetIds)
      
      if (result.success) {
        toast.success(result.message || "평가 대상이 성공적으로 삭제되었습니다.", {
          description: `${result.deletedCount || pendingTargets.length}개의 항목이 삭제되었습니다.`
        })
        onSuccess?.()
        onOpenChange(false)
      } else {
        toast.error(result.error || "삭제 중 오류가 발생했습니다.")
      }
    } catch (error) {
      console.error('Error deleting targets:', error)
      toast.error("삭제 중 오류가 발생했습니다.")
    } finally {
      setIsLoading(false)
    }
  }

  const handleCancel = () => {
    if (!isLoading) {
      onOpenChange(false)
    }
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-2xl">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <Trash2 className="size-5 text-destructive" />
            평가 대상 삭제
          </DialogTitle>
          <DialogDescription>
            선택한 평가 대상을 영구적으로 삭제합니다. 이 작업은 되돌릴 수 없습니다.
          </DialogDescription>
        </DialogHeader>

        {pendingTargets.length > 0 ? (
          <div className="space-y-4">
            {/* 경고 메시지 */}
            <div className="flex items-start gap-3 p-4 bg-destructive/10 rounded-lg border border-destructive/20">
              <AlertTriangle className="size-5 text-destructive mt-0.5 flex-shrink-0" />
              <div className="space-y-1">
                <p className="font-medium text-destructive">
                  주의: 삭제된 데이터는 복구할 수 없습니다
                </p>
                <p className="text-sm text-muted-foreground">
                  PENDING 상태의 평가 대상만 삭제할 수 있습니다. 
                  확정(CONFIRMED)되거나 제외(EXCLUDED)된 대상은 삭제할 수 없습니다.
                </p>
              </div>
            </div>

            {/* 삭제 대상 목록 */}
            <div className="space-y-2">
              <div className="flex items-center justify-between">
                <h4 className="font-medium">삭제될 평가 대상 ({pendingTargets.length}개)</h4>
                <Badge variant="destructive" className="gap-1">
                  <Trash2 className="size-3" />
                  삭제 예정
                </Badge>
              </div>
              
              <ScrollArea className="h-40 w-full border rounded-md">
                <div className="p-4 space-y-2">
                  {pendingTargets.map((target) => (
                    <div 
                      key={target.id} 
                      className="flex items-center justify-between p-2 bg-muted/50 rounded text-sm"
                    >
                      <div className="space-y-1">
                        <div className="font-medium">
                          {target.vendorName || '알 수 없는 업체'}
                        </div>
                        <div className="text-xs text-muted-foreground">
                          • {target.evaluationYear}년
                        </div>
                      </div>
                      <div className="flex items-center gap-2">
                        <Badge variant="secondary" className="text-xs">
                          {target.status}
                        </Badge>
                      </div>
                    </div>
                  ))}
                </div>
              </ScrollArea>
            </div>
          </div>
        ) : (
          <div className="flex items-center justify-center py-8 text-muted-foreground">
            <div className="text-center space-y-2">
              <Trash2 className="size-8 mx-auto opacity-50" />
              <p>삭제할 수 있는 평가 대상이 없습니다.</p>
              <p className="text-xs">PENDING 상태의 대상만 삭제할 수 있습니다.</p>
            </div>
          </div>
        )}

        <DialogFooter>
          <Button
            variant="outline"
            onClick={handleCancel}
            disabled={isLoading}
          >
            취소
          </Button>
          <Button
            variant="destructive"
            onClick={handleDelete}
            disabled={isLoading || pendingTargets.length === 0}
            className="gap-2"
          >
            {isLoading ? (
              <>
                <div className="size-4 border-2 border-current border-r-transparent rounded-full animate-spin" />
                삭제 중...
              </>
            ) : (
              <>
                <Trash2 className="size-4" />
                {pendingTargets.length}개 삭제
              </>
            )}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}