diff options
Diffstat (limited to 'lib/esg-check-list/table/esg-evaluations-table-toolbar-actions.tsx')
| -rw-r--r-- | lib/esg-check-list/table/esg-evaluations-table-toolbar-actions.tsx | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/lib/esg-check-list/table/esg-evaluations-table-toolbar-actions.tsx b/lib/esg-check-list/table/esg-evaluations-table-toolbar-actions.tsx new file mode 100644 index 00000000..5d92d869 --- /dev/null +++ b/lib/esg-check-list/table/esg-evaluations-table-toolbar-actions.tsx @@ -0,0 +1,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} + /> + </> + ) +}
\ No newline at end of file |
