summaryrefslogtreecommitdiff
path: root/lib/procurement-items/table/procurement-items-table-toolbar-actions.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/procurement-items/table/procurement-items-table-toolbar-actions.tsx')
-rw-r--r--lib/procurement-items/table/procurement-items-table-toolbar-actions.tsx182
1 files changed, 182 insertions, 0 deletions
diff --git a/lib/procurement-items/table/procurement-items-table-toolbar-actions.tsx b/lib/procurement-items/table/procurement-items-table-toolbar-actions.tsx
new file mode 100644
index 00000000..f9bc8805
--- /dev/null
+++ b/lib/procurement-items/table/procurement-items-table-toolbar-actions.tsx
@@ -0,0 +1,182 @@
+"use client"
+
+import * as React from "react"
+import { useRouter } from "next/navigation"
+import { type Table } from "@tanstack/react-table"
+import { Download, FileDown, Plus } from "lucide-react"
+import * as ExcelJS from 'exceljs'
+import { saveAs } from "file-saver"
+import { toast } from "sonner"
+
+import { Button } from "@/components/ui/button"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+
+import { ProcurementItem } from "@/db/schema/items"
+import { DeleteProcurementItemsDialog } from "./delete-procurement-items-dialog"
+import { AddProcurementItemDialog } from "./add-procurement-items-dialog"
+import { exportProcurementItemTemplate } from "./procurement-items-excel-template"
+import { ImportProcurementItemButton } from "./import-procurement-items-excel-button"
+
+interface ProcurementItemsTableToolbarActionsProps {
+ table: Table<ProcurementItem>
+}
+
+export function ProcurementItemsTableToolbarActions({
+ table
+}: ProcurementItemsTableToolbarActionsProps) {
+ const [isAddDialogOpen, setIsAddDialogOpen] = React.useState(false)
+ const router = useRouter()
+
+ // 가져오기 성공 후 테이블 갱신
+ const handleImportSuccess = () => {
+ router.refresh()
+ }
+
+ // Excel 내보내기 함수
+ const exportTableToExcel = async (
+ table: Table<ProcurementItem>,
+ options: {
+ filename: string;
+ excludeColumns?: string[];
+ sheetName?: string;
+ }
+ ) => {
+ const { filename, excludeColumns = [], sheetName = "품목 목록" } = options;
+
+ // 워크북 생성
+ const workbook = new ExcelJS.Workbook();
+ workbook.creator = 'Procurement Item Management System';
+ workbook.created = new Date();
+
+ // 워크시트 생성
+ const worksheet = workbook.addWorksheet(sheetName);
+
+ // 테이블 데이터 가져오기
+ const data = table.getFilteredRowModel().rows.map(row => row.original);
+
+ // 테이블 헤더 가져오기
+ const headers = table.getAllColumns()
+ .filter(column => !excludeColumns.includes(column.id))
+ .map(column => ({
+ key: column.id,
+ header: column.columnDef.meta?.excelHeader || column.id,
+ }));
+
+ // 헤더 행 추가
+ worksheet.addRow(headers.map(h => h.header));
+
+ // 데이터 행 추가
+ data.forEach((item) => {
+ const rowData = headers.map(header => {
+ const value = item[header.key];
+
+ // 날짜 처리
+ if (header.key === 'createdAt' || header.key === 'updatedAt') {
+ return value instanceof Date ? value.toLocaleDateString('ko-KR') : value;
+ }
+
+ // 활성화 여부 처리
+ if (header.key === 'isActive') {
+ return value === 'Y' ? '활성' : '비활성';
+ }
+
+ return value || '';
+ });
+ worksheet.addRow(rowData);
+ });
+
+ // 컬럼 너비 설정
+ worksheet.columns = headers.map(header => ({
+ key: header.key,
+ width: header.key === 'itemName' || header.key === 'specification' ? 30 : 15
+ }));
+
+ // 파일 저장
+ const buffer = await workbook.xlsx.writeBuffer();
+ const blob = new Blob([buffer], {
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ });
+ saveAs(blob, `${filename}_${new Date().toISOString().split('T')[0]}.xlsx`);
+ };
+
+ // 테이블 내보내기
+ const handleExportToExcel = () => {
+ exportTableToExcel(table, {
+ filename: 'procurement_items',
+ excludeColumns: ['select', 'actions'],
+ sheetName: '품목 목록'
+ });
+ toast.success('엑셀 파일이 다운로드되었습니다.');
+ };
+
+ // 템플릿 다운로드
+ const handleDownloadTemplate = () => {
+ exportProcurementItemTemplate();
+ toast.success('엑셀 템플릿이 다운로드되었습니다.');
+ };
+
+ return (
+ <>
+ <div className="flex items-center gap-2">
+ {/* 추가 버튼 */}
+ <Button
+ variant="default"
+ size="sm"
+ onClick={() => setIsAddDialogOpen(true)}
+ >
+ <Plus className="mr-2 h-4 w-4" />
+ 품목 추가
+ </Button>
+
+ {/* 엑셀 내보내기 메뉴 */}
+ <DropdownMenu>
+ <DropdownMenuTrigger asChild>
+ <Button variant="outline" size="sm">
+ <Download className="mr-2 h-4 w-4" />
+ 내보내기
+ </Button>
+ </DropdownMenuTrigger>
+ <DropdownMenuContent align="end">
+ <DropdownMenuItem onClick={handleExportToExcel}>
+ <FileDown className="mr-2 h-4 w-4" />
+ 현재 목록 내보내기
+ </DropdownMenuItem>
+ <DropdownMenuItem onClick={handleDownloadTemplate}>
+ <FileDown className="mr-2 h-4 w-4" />
+ 템플릿 다운로드
+ </DropdownMenuItem>
+ </DropdownMenuContent>
+ </DropdownMenu>
+
+ {/* 엑셀 가져오기 버튼 */}
+ <ImportProcurementItemButton onImportSuccess={handleImportSuccess} />
+
+ {/* 선택된 항목들 삭제 버튼 */}
+ {table.getFilteredSelectedRowModel().rows.length > 0 && (
+ <DeleteProcurementItemsDialog
+ procurementItems={table.getFilteredSelectedRowModel().rows.map(row => row.original)}
+ showTrigger={true}
+ onSuccess={() => {
+ table.toggleAllRowsSelected(false)
+ router.refresh()
+ }}
+ />
+ )}
+ </div>
+
+ <AddProcurementItemDialog
+ open={isAddDialogOpen}
+ onOpenChange={setIsAddDialogOpen}
+ onSuccess={() => {
+ setIsAddDialogOpen(false)
+ router.refresh()
+ }}
+ />
+ </>
+ )
+}