"use client" import * as React from "react" import { Upload } from "lucide-react" import { toast } from "sonner" import * as ExcelJS from 'exceljs' import { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Progress } from "@/components/ui/progress" interface ImportProcurementItemButtonProps { onImportSuccess?: () => void } export function ImportProcurementItemButton({ onImportSuccess }: ImportProcurementItemButtonProps) { const [open, setOpen] = React.useState(false) const [file, setFile] = React.useState(null) const [isUploading, setIsUploading] = React.useState(false) const [progress, setProgress] = React.useState(0) const [error, setError] = React.useState(null) const fileInputRef = React.useRef(null) // 파일 선택 처리 const handleFileChange = (e: React.ChangeEvent) => { const selectedFile = e.target.files?.[0] if (!selectedFile) return if (!selectedFile.name.endsWith('.xlsx') && !selectedFile.name.endsWith('.xls')) { setError("Excel 파일(.xlsx 또는 .xls)만 가능합니다.") return } setFile(selectedFile) setError(null) } // 데이터 가져오기 처리 const handleImport = async () => { if (!file) { setError("가져올 파일을 선택해주세요.") return } try { setIsUploading(true) setProgress(0) setError(null) // 파일을 ArrayBuffer로 변환 const arrayBuffer = await file.arrayBuffer() // ExcelJS 워크북 로드 const workbook = new ExcelJS.Workbook() await workbook.xlsx.load(arrayBuffer) // 첫 번째 워크시트 가져오기 const worksheet = workbook.worksheets[0] if (!worksheet) { throw new Error("Excel 파일에 워크시트가 없습니다.") } // 헤더 행 찾기 let headerRowIndex = 1 let headerRow: ExcelJS.Row | undefined let headerValues: (string | null)[] = [] worksheet.eachRow((row, rowNumber) => { const values = row.values as (string | null)[] if (!headerRow && values.some(v => v === "품목코드" || v === "itemCode" || v === "item_code")) { headerRowIndex = rowNumber headerRow = row headerValues = [...values] } }) if (!headerRow) { throw new Error("Excel 파일에서 헤더 행을 찾을 수 없습니다.") } // 컬럼 매핑 const columnMap: { [key: string]: number } = {} headerValues.forEach((header, index) => { if (header) { const normalizedHeader = header.toString().toLowerCase() if (normalizedHeader.includes("품목코드") || normalizedHeader.includes("itemcode") || normalizedHeader === "item_code") { columnMap.itemCode = index } else if (normalizedHeader.includes("품목명") || normalizedHeader.includes("itemname") || normalizedHeader === "item_name") { columnMap.itemName = index } else if (normalizedHeader.includes("재질") || normalizedHeader.includes("material")) { columnMap.material = index } else if (normalizedHeader.includes("규격") || normalizedHeader.includes("specification")) { columnMap.specification = index } else if (normalizedHeader.includes("단위") || normalizedHeader.includes("unit")) { columnMap.unit = index } else if (normalizedHeader.includes("활성화") || normalizedHeader.includes("isactive") || normalizedHeader === "is_active") { columnMap.isActive = index } } }) // 필수 컬럼 확인 if (!columnMap.itemCode || !columnMap.itemName) { throw new Error("필수 컬럼(품목코드, 품목명)을 찾을 수 없습니다.") } // 데이터 행 처리 const importData: any[] = [] let successCount = 0 let errorCount = 0 worksheet.eachRow((row, rowNumber) => { if (rowNumber <= headerRowIndex) return // 헤더 행 건너뜀 const values = row.values as (string | null | undefined)[] const itemData = { itemCode: values[columnMap.itemCode]?.toString().trim(), itemName: values[columnMap.itemName]?.toString().trim(), material: values[columnMap.material]?.toString().trim() || null, specification: values[columnMap.specification]?.toString().trim() || null, unit: values[columnMap.unit]?.toString().trim() || null, isActive: values[columnMap.isActive]?.toString().trim() || 'Y', } // 필수 필드 검증 if (!itemData.itemCode || !itemData.itemName) { errorCount++ return } importData.push(itemData) }) if (importData.length === 0) { throw new Error("가져올 데이터가 없습니다.") } setProgress(50) // 실제 데이터 저장 처리 (서버 액션 호출) const { importProcurementItemsFromExcel } = await import('../service') const result = await importProcurementItemsFromExcel(importData) if (!result.success) { throw new Error(result.message || '가져오기에 실패했습니다.') } setProgress(100) toast.success(`${result.importedCount}개 품목이 성공적으로 가져오기를 완료했습니다.`) // 성공 콜백 호출 onImportSuccess?.() setOpen(false) } catch (error) { console.error('가져오기 오류:', error) setError(error instanceof Error ? error.message : '알 수 없는 오류가 발생했습니다.') toast.error('가져오기에 실패했습니다.') } finally { setIsUploading(false) setProgress(0) } } return ( <> 엑셀 파일에서 품목 가져오기 템플릿을 다운로드하여 작성한 후 가져오기를 실행하세요.
{file && (

선택된 파일: {file.name}

)}
{isUploading && (

처리 중... {progress}%

)} {error && (

{error}

)}
) }