diff options
Diffstat (limited to 'lib/risk-management/table/risks-table-toolbar-actions.tsx')
| -rw-r--r-- | lib/risk-management/table/risks-table-toolbar-actions.tsx | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/lib/risk-management/table/risks-table-toolbar-actions.tsx b/lib/risk-management/table/risks-table-toolbar-actions.tsx new file mode 100644 index 00000000..2d4ba2d4 --- /dev/null +++ b/lib/risk-management/table/risks-table-toolbar-actions.tsx @@ -0,0 +1,161 @@ +'use client'; + +/* IMPORT */ +import { Button } from '@/components/ui/button'; +import { ChangeEvent, useRef } from 'react'; +import { Download, FileInput, Mail, Upload } from 'lucide-react'; +import { exportTableToExcel } from '@/lib/export'; +import { generateRiskEventsTemplate, importRiskEventsExcel } from '../service'; +import { toast } from 'sonner'; +import { type DataTableRowAction } from '@/types/table'; +import { type RisksView } from '@/db/schema'; +import { type Table } from '@tanstack/react-table'; + +// ---------------------------------------------------------------------------------------------------- + +/* TYPES */ +interface RisksTableToolbarActionsProps { + table: Table<RisksView>; + onOpenMailDialog: () => void; + onRefresh: () => void; +} + +// ---------------------------------------------------------------------------------------------------- + +/* RISKS TABLE TOOLBAR ACTIONS COMPONENT */ +function RisksTableToolbarActions(props: RisksTableToolbarActionsProps) { + const { table, onOpenMailDialog, onRefresh } = props; + const selectedRows = table.getFilteredSelectedRowModel().rows; + const hasSelection = selectedRows.length > 0; + const fileInputRef = useRef<HTMLInputElement>(null); + + // EXCEL IMPORT + function handleImport() { + fileInputRef.current?.click(); + }; + async function onFileChange(event: ChangeEvent<HTMLInputElement>) { + const file = event.target.files?.[0]; + if (!file) { + toast.error('가져올 파일을 선택해주세요.'); + return; + } + if (!file.name.endsWith('.xlsx') && !file.name.endsWith('.xls')) { + toast.error('.xlsx 또는 .xls 확장자인 Excel 파일만 업로드 가능해요.'); + return; + } + event.target.value = ''; + + try { + const { errorFile, errorMessage, successMessage } = await importRiskEventsExcel(file); + + if (errorMessage) { + toast.error(errorMessage); + + if (errorFile) { + const url = URL.createObjectURL(errorFile); + const link = document.createElement('a'); + link.href = url; + link.download = 'errors.xlsx'; + link.click(); + URL.revokeObjectURL(url); + } + } else { + toast.success(successMessage || 'Excel 파일이 성공적으로 업로드되었어요.'); + } + } catch (error) { + toast.error('Excel 파일을 업로드하는 중 오류가 발생했습니다.'); + console.error('Error in Excel File Upload: ', error); + } finally { + onRefresh(); + } + }; + + // EXCEL EXPORT + const handleExport = async () => { + try { + exportTableToExcel(table, { + filename: '협력업체_리스크_관리', + excludeColumns: ['id', 'actions'], + }); + toast.success('Excel 파일이 다운로드되었어요.'); + } catch (error) { + console.error('Error in Exporting to Excel: ', error); + toast.error('Excel 파일 내보내기 중 오류가 발생했어요.'); + } + }; + + // EXCEL TEMPLATE DOWNLOAD + const handleTemplateDownload = async () => { + try { + const buffer = await generateRiskEventsTemplate(); + const blob = new Blob([buffer], { + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = "협력업체_리스크_템플릿.xlsx"; + link.click(); + URL.revokeObjectURL(url); + toast.success('템플릿 파일이 다운로드되었어요.'); + } catch (error) { + console.error('Error in Template Download: ', error); + toast.error('템플릿 다운로드 중 오류가 발생했어요.'); + } + }; + + return ( + <div className="flex items-center gap-2"> + <Button + size="sm" + className="gap-2" + onClick={onOpenMailDialog} + disabled={!hasSelection} + > + <Mail className="size-4" aria-hidden="true" /> + <span className="hidden sm:inline"> + 메일 발송 + </span> + </Button> + <Button + variant="outline" + size="sm" + className="gap-2" + onClick={handleImport} + > + <Upload className="size-4" aria-hidden="true" /> + <span className="hidden sm:inline">Import</span> + </Button> + <input + ref={fileInputRef} + type="file" + accept=".xlsx,.xls" + className="hidden" + onChange={onFileChange} + /> + <Button + variant="outline" + size="sm" + onClick={handleExport} + className="gap-2" + > + <Download className="size-4" aria-hidden="true" /> + <span className="hidden sm:inline">Export</span> + </Button> + <Button + variant="outline" + size="sm" + onClick={handleTemplateDownload} + className="gap-2" + > + <FileInput className="size-4" aria-hidden="true" /> + <span className="hidden sm:inline">Template</span> + </Button> + </div> + ); +} + +// ---------------------------------------------------------------------------------------------------- + +/* EXPORT */ +export default RisksTableToolbarActions;
\ No newline at end of file |
