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
181
182
183
184
|
"use client"
import * as React from "react"
import { type Table } from "@tanstack/react-table"
import { Download, Plus, Trash2, Upload, FileSpreadsheet } from "lucide-react"
import { toast } from "sonner"
import { exportTableToExcel } from "@/lib/export"
import { Button } from "@/components/ui/button"
import { EsgEvaluationsView } from "@/db/schema"
import { EsgEvaluationBatchDeleteDialog } from "./esg-evaluation-delete-dialog"
import { downloadEsgTemplate } from "./excel-utils"
import { useRouter } from "next/navigation"
import { ExcelImportDialog } from "./esg-excel-import"
interface EsgEvaluationsTableToolbarActionsProps {
table: Table<EsgEvaluationsView>
onCreateNew?: () => void
onRefresh?: () => void
}
export function EsgEvaluationsTableToolbarActions({
table,
onCreateNew,
onRefresh
}: EsgEvaluationsTableToolbarActionsProps) {
const [isRefreshing, setIsRefreshing] = React.useState(false)
const [deleteDialogOpen, setDeleteDialogOpen] = React.useState(false)
const [importDialogOpen, setImportDialogOpen] = React.useState(false)
const router = useRouter()
// 선택된 행들
const selectedRows = table.getFilteredSelectedRowModel().rows
const hasSelection = selectedRows.length > 0
const selectedEvaluations = selectedRows.map(row => row.original)
// ----------------------------------------------------------------
// 새 평가표 생성
// ----------------------------------------------------------------
const handleCreateNew = () => {
if (onCreateNew) {
onCreateNew()
} else {
toast.info("새 ESG 평가표 생성 기능을 구현해주세요.")
}
}
// ----------------------------------------------------------------
// 선택된 평가표들 삭제 다이얼로그 열기
// ----------------------------------------------------------------
const handleDeleteSelected = () => {
if (!hasSelection) return
setDeleteDialogOpen(true)
}
// ----------------------------------------------------------------
// 삭제 성공 후 처리
// ----------------------------------------------------------------
const handleDeleteSuccess = async () => {
// 선택 해제
table.resetRowSelection()
router.refresh()
}
// ----------------------------------------------------------------
// Excel 템플릿 다운로드
// ----------------------------------------------------------------
const handleDownloadTemplate = async () => {
try {
await downloadEsgTemplate()
toast.success("Excel 템플릿이 다운로드되었습니다.")
} catch (error) {
console.error('Error downloading template:', error)
toast.error("템플릿 다운로드 중 오류가 발생했습니다.")
}
}
// ----------------------------------------------------------------
// Excel 내보내기
// ----------------------------------------------------------------
const handleExport = () => {
try {
exportTableToExcel(table, {
filename: "ESG_Evaluations",
excludeColumns: ["select", "actions"],
})
toast.success("Excel 파일이 다운로드되었습니다.")
} catch (error) {
console.error('Error exporting to Excel:', error)
toast.error("Excel 내보내기 중 오류가 발생했습니다.")
}
}
// ----------------------------------------------------------------
// 임포트 성공 후 처리
// ----------------------------------------------------------------
const handleImportSuccess = () => {
router.refresh()
}
return (
<>
<div className="flex items-center gap-2">
{/* 새 평가표 생성 버튼 */}
<Button
variant="default"
size="sm"
className="gap-2"
onClick={handleCreateNew}
>
<Plus className="size-4" aria-hidden="true" />
<span className="hidden sm:inline">새 평가표</span>
</Button>
{/* Excel 관련 버튼들 */}
<div className="flex items-center gap-1 border-l pl-2 ml-2">
{/* Excel 템플릿 다운로드 */}
<Button
variant="outline"
size="sm"
onClick={handleDownloadTemplate}
className="gap-2"
>
<FileSpreadsheet className="size-4" aria-hidden="true" />
<span className="hidden sm:inline">템플릿</span>
</Button>
{/* Excel 데이터 임포트 */}
<Button
variant="outline"
size="sm"
onClick={() => setImportDialogOpen(true)}
className="gap-2"
>
<Upload className="size-4" aria-hidden="true" />
<span className="hidden sm:inline">임포트</span>
</Button>
{/* Excel 데이터 내보내기 */}
<Button
variant="outline"
size="sm"
onClick={handleExport}
className="gap-2"
>
<Download className="size-4" aria-hidden="true" />
<span className="hidden sm:inline">내보내기</span>
</Button>
</div>
{/* 선택된 항목 삭제 버튼 */}
{hasSelection && (
<Button
variant="destructive"
size="sm"
className="gap-2 ml-2"
onClick={handleDeleteSelected}
>
<Trash2 className="size-4" aria-hidden="true" />
<span className="hidden sm:inline">
선택 삭제 ({selectedRows.length})
</span>
</Button>
)}
</div>
{/* 배치 삭제 다이얼로그 */}
<EsgEvaluationBatchDeleteDialog
open={deleteDialogOpen}
onOpenChange={setDeleteDialogOpen}
evaluations={selectedEvaluations}
onSuccess={handleDeleteSuccess}
useSoftDelete={false} // true로 설정하면 소프트 삭제 사용
/>
{/* Excel 임포트 다이얼로그 */}
<ExcelImportDialog
open={importDialogOpen}
onOpenChange={setImportDialogOpen}
onSuccess={handleImportSuccess}
/>
</>
)
}
|