"use client" import * as React from "react" import type { Table } from "@tanstack/react-table" import { Plus, Trash2, Upload, Download, Users } from "lucide-react" import { toast } from "sonner" import { Button } from "@/components/ui/button" import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip" import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog" import type { TechVendorPossibleItem } from "../validations" import { deleteTechVendorPossibleItemsNew, parsePossibleItemsImportFile, importPossibleItemsFromExcel, generatePossibleItemsImportTemplate, generatePossibleItemsErrorExcel, type PossibleItemImportData, type PossibleItemErrorData, // Contact Possible Import 관련 함수들 parseContactPossibleItemsImportFile, importContactPossibleItemsFromExcel, generateContactPossibleItemsImportTemplate, generateContactPossibleItemsErrorExcel, type ContactPossibleItemImportData, type ContactPossibleItemErrorData } from "../service" interface PossibleItemsTableToolbarActionsProps { table: Table vendorId: number onAdd: () => void // 주석처리 onRefresh?: () => void // 데이터 새로고침 콜백 } export function PossibleItemsTableToolbarActions({ table, vendorId, onAdd, // 주석처리 onRefresh, }: PossibleItemsTableToolbarActionsProps) { const [showDeleteAlert, setShowDeleteAlert] = React.useState(false) const [isDeleting, setIsDeleting] = React.useState(false) const [isImporting, setIsImporting] = React.useState(false) const [isContactImporting, setIsContactImporting] = React.useState(false) const fileInputRef = React.useRef(null) const contactFileInputRef = React.useRef(null) const selectedRows = table.getFilteredSelectedRowModel().rows async function handleDelete() { setIsDeleting(true) try { const ids = selectedRows.map((row) => row.original.id) const { error } = await deleteTechVendorPossibleItemsNew(ids, vendorId) if (error) { throw new Error(error) } toast.success(`${ids.length}개의 아이템이 삭제되었습니다`) table.resetRowSelection() setShowDeleteAlert(false) onRefresh?.() // 데이터 새로고침 } catch { toast.error("아이템 삭제 중 오류가 발생했습니다") } finally { setIsDeleting(false) } } // 템플릿 다운로드 핸들러 async function handleTemplateDownload() { try { const templateBlob = await generatePossibleItemsImportTemplate() const url = window.URL.createObjectURL(templateBlob) const link = document.createElement("a") link.href = url link.download = "벤더_possible_items_템플릿.xlsx" document.body.appendChild(link) link.click() document.body.removeChild(link) window.URL.revokeObjectURL(url) toast.success("템플릿 파일이 다운로드되었습니다") } catch (error) { toast.error("템플릿 다운로드 중 오류가 발생했습니다") } } // 파일 선택 핸들러 function handleFileSelect() { fileInputRef.current?.click() } // Excel 파일 import 핸들러 async function handleFileImport(event: React.ChangeEvent) { const file = event.target.files?.[0] if (!file) return // 파일 타입 검증 if (!file.name.endsWith('.xlsx') && !file.name.endsWith('.xls')) { toast.error("Excel 파일(.xlsx 또는 .xls)만 업로드 가능합니다") return } setIsImporting(true) try { // Excel 파일 파싱 const importData: PossibleItemImportData[] = await parsePossibleItemsImportFile(file) if (importData.length === 0) { toast.error("업로드할 데이터가 없습니다") return } // 데이터 import 실행 const result = await importPossibleItemsFromExcel(importData) // 결과 메시지 생성 const successMessage = `${result.successCount}개의 아이템이 성공적으로 등록되었습니다` const failMessage = result.failedRows.length > 0 ? `, ${result.failedRows.length}개의 아이템 등록 실패` : "" toast.success(successMessage + failMessage) // 실패한 행이 있는 경우 에러 파일 다운로드 if (result.failedRows.length > 0) { const errorData: PossibleItemErrorData[] = result.failedRows.map(failedRow => ({ vendorEmail: failedRow.vendorEmail, itemCode: failedRow.itemCode, itemType: failedRow.itemType, error: failedRow.error, })) const errorBlob = await generatePossibleItemsErrorExcel(errorData) const url = window.URL.createObjectURL(errorBlob) const link = document.createElement("a") link.href = url link.download = "possible_items_import_에러.xlsx" document.body.appendChild(link) link.click() document.body.removeChild(link) window.URL.revokeObjectURL(url) toast.error("에러 내역 파일이 다운로드되었습니다") } // 파일 입력 초기화 if (fileInputRef.current) { fileInputRef.current.value = "" } // 데이터 새로고침 onRefresh?.() } catch (error) { console.error("Import error:", error) toast.error(error instanceof Error ? error.message : "데이터 등록 중 오류가 발생했습니다") } finally { setIsImporting(false) } } // Contact Possible Import용 템플릿 다운로드 핸들러 async function handleContactTemplateDownload() { try { const templateBlob = await generateContactPossibleItemsImportTemplate() const url = window.URL.createObjectURL(templateBlob) const link = document.createElement("a") link.href = url link.download = "담당자별_아이템매핑_템플릿.xlsx" document.body.appendChild(link) link.click() document.body.removeChild(link) window.URL.revokeObjectURL(url) toast.success("템플릿 파일이 다운로드되었습니다") } catch (error) { toast.error("템플릿 다운로드 중 오류가 발생했습니다") } } // Contact Possible Import용 파일 선택 핸들러 function handleContactFileSelect() { contactFileInputRef.current?.click() } // Contact Possible Import 핸들러 async function handleContactFileImport(event: React.ChangeEvent) { const file = event.target.files?.[0] if (!file) return // 파일 타입 검증 if (!file.name.endsWith('.xlsx') && !file.name.endsWith('.xls')) { toast.error("Excel 파일(.xlsx 또는 .xls)만 업로드 가능합니다") return } setIsContactImporting(true) try { // Excel 파일 파싱 (새로운 함수 사용) const importData: ContactPossibleItemImportData[] = await parseContactPossibleItemsImportFile(file) if (importData.length === 0) { toast.error("업로드할 데이터가 없습니다") return } // 데이터 import 실행 (새로운 함수 사용) const result = await importContactPossibleItemsFromExcel(importData) console.log(result) // 결과 메시지 생성 const successMessage = `${result.successCount}개의 아이템 매핑이 성공적으로 등록되었습니다` const failMessage = result.failedRows.length > 0 ? `, ${result.failedRows.length}개의 매핑 등록 실패` : "" toast.success(successMessage + failMessage) // 실패한 행이 있는 경우 에러 파일 다운로드 if (result.failedRows.length > 0) { const errorData: ContactPossibleItemErrorData[] = result.failedRows.map(failedRow => ({ contactEmail: failedRow.contactEmail, itemCode: Array.isArray(failedRow.itemCode) ? failedRow.itemCode.join(', ') : failedRow.itemCode, error: failedRow.error, })) const errorBlob = await generateContactPossibleItemsErrorExcel(errorData) const url = window.URL.createObjectURL(errorBlob) const link = document.createElement("a") link.href = url link.download = "contact_possible_items_import_에러.xlsx" document.body.appendChild(link) link.click() document.body.removeChild(link) window.URL.revokeObjectURL(url) toast.error("에러 내역 파일이 다운로드되었습니다") } // 파일 입력 초기화 if (contactFileInputRef.current) { contactFileInputRef.current.value = "" } // 데이터 새로고침 onRefresh?.() } catch (error) { console.error("Contact Possible Import error:", error) toast.error(error instanceof Error ? error.message : "데이터 등록 중 오류가 발생했습니다") } finally { setIsContactImporting(false) } } return ( <>
{/* 템플릿 다운로드 버튼 */} Excel 템플릿 파일 다운로드 {/* Excel Import 버튼 */} Excel 파일로 아이템 일괄 등록 {/* Contact Possible Import 템플릿 버튼 */} 담당자별 아이템 매핑 템플릿 다운로드 {/* Contact Possible Import 버튼 */} 담당자별 아이템 매핑 등록 {/* 숨겨진 파일 입력들 */} {/* Contact Possible Import용 숨겨진 파일 입력 */} {/* 아이템 추가 버튼 주석처리 */} {selectedRows.length > 0 && ( <> 선택된 {selectedRows.length}개 아이템을 삭제합니다 )}
아이템 삭제 선택된 {selectedRows.length}개의 아이템을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다. 취소 {isDeleting ? "삭제 중..." : "삭제"} ) }