"use client" import * as React from "react" import { type Table } from "@tanstack/react-table" import { Download, Upload } from "lucide-react" import { toast } from "sonner" import ExcelJS from "exceljs" import { exportTableToExcel } from "@/lib/export" import { Button } from "@/components/ui/button" import { TechVendorContact } from "@/db/schema/techVendors" import { AddContactDialog } from "./add-contact-dialog" import { importTechVendorContacts, generateContactImportTemplate, parseContactImportFile, importTechVendorDistinctContacts, generateDistinctContactImportTemplate, parseDistinctContactImportFile } from "@/lib/tech-vendors/service" interface TechVendorContactsTableToolbarActionsProps { table: Table vendorId: number } export function TechVendorContactsTableToolbarActions({ table, vendorId }: TechVendorContactsTableToolbarActionsProps) { // 파일 input을 숨기고, 버튼 클릭 시 참조해 클릭하는 방식 const fileInputRef = React.useRef(null) const distinctFileInputRef = React.useRef(null) // 파일이 선택되었을 때 처리 async function onFileChange(event: React.ChangeEvent) { const file = event.target.files?.[0] if (!file) return // 파일 초기화 (동일 파일 재업로드 시에도 onChange가 트리거되도록) event.target.value = "" try { // Excel 파일 파싱 const contactData = await parseContactImportFile(file) if (contactData.length === 0) { toast.error("유효한 데이터가 없습니다. 템플릿 형식을 확인해주세요.") return } // 서버로 데이터 전송 const result = await importTechVendorContacts(contactData) if (result.successCount > 0) { toast.success(`${result.successCount}개 연락처가 성공적으로 추가되었습니다.`) } if (result.failedRows.length > 0) { toast.error(`${result.failedRows.length}개 행에서 오류가 발생했습니다.`) // 에러 데이터를 Excel로 다운로드 const errorWorkbook = new ExcelJS.Workbook() const errorWorksheet = errorWorkbook.addWorksheet("오류내역") // 헤더 추가 errorWorksheet.columns = [ { header: "행번호", key: "row", width: 10 }, { header: "벤더이메일", key: "vendorEmail", width: 25 }, { header: "담당자명", key: "contactName", width: 20 }, { header: "담당자이메일", key: "contactEmail", width: 25 }, { header: "오류내용", key: "error", width: 80, style: { alignment: { wrapText: true } , font: { color: { argb: "FFFF0000" } } } }, ] // 오류 데이터 추가 result.failedRows.forEach(failedRow => { errorWorksheet.addRow({ row: failedRow.row, error: failedRow.error, vendorEmail: failedRow.vendorEmail, contactName: failedRow.contactName, contactEmail: failedRow.contactEmail, }) }) const buffer = await errorWorkbook.xlsx.writeBuffer() 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 = "contact-import-errors.xlsx" link.click() URL.revokeObjectURL(url) } } catch (error) { toast.error("파일 업로드 중 오류가 발생했습니다.") console.error("Import error:", error) } } function handleImportClick() { // 숨겨진 요소를 클릭 fileInputRef.current?.click() } function handleDistinctImportClick() { // Distinct Import용 숨겨진 요소를 클릭 distinctFileInputRef.current?.click() } async function handleTemplateDownload() { try { const templateBlob = await generateContactImportTemplate() const url = URL.createObjectURL(templateBlob) const link = document.createElement("a") link.href = url link.download = "tech-vendor-contacts-template.xlsx" link.click() URL.revokeObjectURL(url) toast.success("템플릿이 다운로드되었습니다.") } catch (error) { toast.error("템플릿 다운로드 중 오류가 발생했습니다.") console.error("Template download error:", error) } } // Distinct Import 파일 처리 함수 async function onDistinctFileChange(event: React.ChangeEvent) { const file = event.target.files?.[0] if (!file) return // 파일 초기화 (동일 파일 재업로드 시에도 onChange가 트리거되도록) event.target.value = "" try { // Excel 파일 파싱 (새로운 함수 사용) const distinctContactData = await parseDistinctContactImportFile(file) if (distinctContactData.length === 0) { toast.error("유효한 데이터가 없습니다. 템플릿 형식을 확인해주세요.") return } // 서버로 데이터 전송 (새로운 함수 사용) const result = await importTechVendorDistinctContacts(distinctContactData) if (result.successCount > 0) { toast.success(`${result.successCount}개 담당자가 성공적으로 추가되었습니다.`) } if (result.failedRows.length > 0) { toast.error(`${result.failedRows.length}개 행에서 오류가 발생했습니다.`) // 에러 데이터를 Excel로 다운로드 const errorWorkbook = new ExcelJS.Workbook() const errorWorksheet = errorWorkbook.addWorksheet("오류내역") // 헤더 추가 errorWorksheet.columns = [ { header: "행번호", key: "row", width: 10 }, { header: "벤더이름", key: "vendorName", width: 20 }, { header: "이메일", key: "email", width: 25 }, { header: "오류내용", key: "error", width: 80, style: { alignment: { wrapText: true }, font: { color: { argb: "FFFF0000" } } } }, ] // 오류 데이터 추가 result.failedRows.forEach(failedRow => { errorWorksheet.addRow({ row: failedRow.row, error: failedRow.error, vendorName: failedRow.vendorName, email: failedRow.email, }) }) const buffer = await errorWorkbook.xlsx.writeBuffer() 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 = "distinct-contact-import-errors.xlsx" link.click() URL.revokeObjectURL(url) } } catch (error) { toast.error("파일 업로드 중 오류가 발생했습니다.") console.error("Distinct Import error:", error) } } async function handleDistinctTemplateDownload() { try { const templateBlob = await generateDistinctContactImportTemplate() const url = URL.createObjectURL(templateBlob) const link = document.createElement("a") link.href = url link.download = "tech-vendor-distinct-contacts-template.xlsx" link.click() URL.revokeObjectURL(url) toast.success("Distinct Import 템플릿이 다운로드되었습니다.") } catch (error) { toast.error("템플릿 다운로드 중 오류가 발생했습니다.") console.error("Distinct Template download error:", error) } } return (
{/** 템플릿 다운로드 버튼 */} {/** Distinct Import 템플릿 다운로드 버튼 */} {/** Import 버튼 (파일 업로드) */} {/** Distinct Import 버튼 (대표 이메일과 다른 담당자 추가) */} {/* 실제로는 숨겨진 input과 연결: - accept=".xlsx,.xls" 등으로 Excel 파일만 업로드 허용 */} {/** Distinct Import용 숨겨진 input */} {/** Export 버튼 */}
) }