diff options
Diffstat (limited to 'lib/vendor-candidates/table/import-button.tsx')
| -rw-r--r-- | lib/vendor-candidates/table/import-button.tsx | 78 |
1 files changed, 46 insertions, 32 deletions
diff --git a/lib/vendor-candidates/table/import-button.tsx b/lib/vendor-candidates/table/import-button.tsx index 1a2a4f7c..b1dd43a9 100644 --- a/lib/vendor-candidates/table/import-button.tsx +++ b/lib/vendor-candidates/table/import-button.tsx @@ -7,6 +7,7 @@ import { Button } from '@/components/ui/button' import { Upload, Loader } from 'lucide-react' import { createVendorCandidate } from '../service' import { Input } from '@/components/ui/input' +import { useSession } from "next-auth/react" // next-auth 세션 훅 추가 interface ImportExcelProps { onSuccess?: () => void @@ -15,24 +16,25 @@ interface ImportExcelProps { export function ImportVendorCandidatesButton({ onSuccess }: ImportExcelProps) { const fileInputRef = useRef<HTMLInputElement>(null) const [isImporting, setIsImporting] = React.useState(false) + const { data: session, status } = useSession() // Helper function to get cell value as string const getCellValueAsString = (cell: ExcelJS.Cell): string => { if (!cell || cell.value === undefined || cell.value === null) return ''; - + if (typeof cell.value === 'string') return cell.value.trim(); if (typeof cell.value === 'number') return cell.value.toString(); - + // Handle rich text if (typeof cell.value === 'object' && 'richText' in cell.value) { return cell.value.richText.map((rt: any) => rt.text).join(''); } - + // Handle dates if (cell.value instanceof Date) { return cell.value.toISOString().split('T')[0]; } - + // Fallback return String(cell.value); } @@ -42,55 +44,55 @@ export function ImportVendorCandidatesButton({ onSuccess }: ImportExcelProps) { if (!file) return setIsImporting(true) - + try { // Read the Excel file using ExcelJS const data = await file.arrayBuffer() const workbook = new ExcelJS.Workbook() await workbook.xlsx.load(data) - + // Get the first worksheet const worksheet = workbook.getWorksheet(1) if (!worksheet) { toast.error("No worksheet found in the spreadsheet") return } - + // Check if there's an instruction row - const hasInstructionRow = worksheet.getRow(1).getCell(1).value !== null && - worksheet.getRow(1).getCell(2).value === null; - + const hasInstructionRow = worksheet.getRow(1).getCell(1).value !== null && + worksheet.getRow(1).getCell(2).value === null; + // Get header row index (row 2 if there's an instruction row, otherwise row 1) const headerRowIndex = hasInstructionRow ? 2 : 1; - + // Get column headers and their indices const headerRow = worksheet.getRow(headerRowIndex); const headers: Record<number, string> = {}; const columnIndices: Record<string, number> = {}; - + headerRow.eachCell((cell, colNumber) => { const header = getCellValueAsString(cell); headers[colNumber] = header; columnIndices[header] = colNumber; }); - + // Process data rows const rows: any[] = []; const startRow = headerRowIndex + 1; - + for (let i = startRow; i <= worksheet.rowCount; i++) { const row = worksheet.getRow(i); - + // Skip empty rows if (row.cellCount === 0) continue; - + // Check if this is likely an example row - const isExample = i === startRow && worksheet.getRow(i+1).values?.length === 0; + const isExample = i === startRow && worksheet.getRow(i + 1).values?.length === 0; if (isExample) continue; - + const rowData: Record<string, any> = {}; let hasData = false; - + // Map the data using header indices Object.entries(columnIndices).forEach(([header, colIndex]) => { const value = getCellValueAsString(row.getCell(colIndex)); @@ -99,22 +101,22 @@ export function ImportVendorCandidatesButton({ onSuccess }: ImportExcelProps) { hasData = true; } }); - + if (hasData) { rows.push(rowData); } } - + if (rows.length === 0) { toast.error("No data found in the spreadsheet") setIsImporting(false) return } - + // Process each row let successCount = 0; let errorCount = 0; - + // Create promises for all vendor candidate creation operations const promises = rows.map(async (row) => { try { @@ -123,28 +125,40 @@ export function ImportVendorCandidatesButton({ onSuccess }: ImportExcelProps) { companyName: String(row['Company Name'] || ''), contactEmail: String(row['Contact Email'] || ''), contactPhone: String(row['Contact Phone'] || ''), + taxId: String(row['Tax ID'] || ''), + address: String(row['Address'] || ''), country: String(row['Country'] || ''), source: String(row['Source'] || ''), + items: String(row['Items'] || ''), + remark: String(row['Remark'] || row['Remarks'] || ''), // Default to COLLECTED if not specified status: (row['Status'] || 'COLLECTED') as "COLLECTED" | "INVITED" | "DISCARDED" }; - + // Validate required fields - if (!candidateData.companyName || !candidateData.contactEmail) { + if (!candidateData.companyName || !candidateData.source || + !candidateData.items) { console.error("Missing required fields", candidateData); errorCount++; return null; } - + + if (!session || !session.user || !session.user.id) { + toast.error("인증 오류. 로그인 정보를 찾을 수 없습니다.") + return + } + + const userId = session.user.id + // Create the vendor candidate - const result = await createVendorCandidate(candidateData); - + const result = await createVendorCandidate(candidateData, Number(userId)) + if (result.error) { console.error(`Failed to import row: ${result.error}`, candidateData); errorCount++; return null; } - + successCount++; return result.data; } catch (error) { @@ -153,10 +167,10 @@ export function ImportVendorCandidatesButton({ onSuccess }: ImportExcelProps) { return null; } }); - + // Wait for all operations to complete await Promise.all(promises); - + // Show results if (successCount > 0) { toast.success(`Successfully imported ${successCount} vendor candidates`); @@ -168,7 +182,7 @@ export function ImportVendorCandidatesButton({ onSuccess }: ImportExcelProps) { } else if (errorCount > 0) { toast.error(`Failed to import all ${errorCount} rows due to errors`); } - + } catch (error) { console.error("Import error:", error); toast.error("Error importing data. Please check file format."); |
