summaryrefslogtreecommitdiff
path: root/lib/tech-vendors/contacts-table/contact-table-toolbar-actions.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-10-10 07:37:26 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-10-10 07:37:26 +0000
commit00092099271ff743ac195511c03994e80f91a2e9 (patch)
treeed75474f4a8a3b0ec289c3331ece0f0d25578ec4 /lib/tech-vendors/contacts-table/contact-table-toolbar-actions.tsx
parentf14b7c3e28a6d08537e07f182f5d080d82adf60e (diff)
(최겸) 기술영업 import 수정
Diffstat (limited to 'lib/tech-vendors/contacts-table/contact-table-toolbar-actions.tsx')
-rw-r--r--lib/tech-vendors/contacts-table/contact-table-toolbar-actions.tsx124
1 files changed, 119 insertions, 5 deletions
diff --git a/lib/tech-vendors/contacts-table/contact-table-toolbar-actions.tsx b/lib/tech-vendors/contacts-table/contact-table-toolbar-actions.tsx
index 84228a54..7b81967e 100644
--- a/lib/tech-vendors/contacts-table/contact-table-toolbar-actions.tsx
+++ b/lib/tech-vendors/contacts-table/contact-table-toolbar-actions.tsx
@@ -10,10 +10,13 @@ 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
+import {
+ importTechVendorContacts,
+ generateContactImportTemplate,
+ parseContactImportFile,
+ importTechVendorDistinctContacts,
+ generateDistinctContactImportTemplate,
+ parseDistinctContactImportFile
} from "@/lib/tech-vendors/service"
interface TechVendorContactsTableToolbarActionsProps {
@@ -24,6 +27,7 @@ interface TechVendorContactsTableToolbarActionsProps {
export function TechVendorContactsTableToolbarActions({ table, vendorId }: TechVendorContactsTableToolbarActionsProps) {
// 파일 input을 숨기고, 버튼 클릭 시 참조해 클릭하는 방식
const fileInputRef = React.useRef<HTMLInputElement>(null)
+ const distinctFileInputRef = React.useRef<HTMLInputElement>(null)
// 파일이 선택되었을 때 처리
async function onFileChange(event: React.ChangeEvent<HTMLInputElement>) {
@@ -99,6 +103,11 @@ export function TechVendorContactsTableToolbarActions({ table, vendorId }: TechV
fileInputRef.current?.click()
}
+ function handleDistinctImportClick() {
+ // Distinct Import용 숨겨진 <input type="file" /> 요소를 클릭
+ distinctFileInputRef.current?.click()
+ }
+
async function handleTemplateDownload() {
try {
const templateBlob = await generateContactImportTemplate()
@@ -115,6 +124,89 @@ export function TechVendorContactsTableToolbarActions({ table, vendorId }: TechV
}
}
+ // Distinct Import 파일 처리 함수
+ async function onDistinctFileChange(event: React.ChangeEvent<HTMLInputElement>) {
+ 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 (
<div className="flex items-center gap-2">
@@ -123,7 +215,13 @@ export function TechVendorContactsTableToolbarActions({ table, vendorId }: TechV
{/** 템플릿 다운로드 버튼 */}
<Button variant="outline" size="sm" className="gap-2" onClick={handleTemplateDownload}>
<Download className="size-4" aria-hidden="true" />
- <span className="hidden sm:inline">템플릿</span>
+ <span className="hidden sm:inline">기본 템플릿</span>
+ </Button>
+
+ {/** Distinct Import 템플릿 다운로드 버튼 */}
+ <Button variant="outline" size="sm" className="gap-2" onClick={handleDistinctTemplateDownload}>
+ <Download className="size-4" aria-hidden="true" />
+ <span className="hidden sm:inline">Distinct 템플릿</span>
</Button>
{/** Import 버튼 (파일 업로드) */}
@@ -131,6 +229,13 @@ export function TechVendorContactsTableToolbarActions({ table, vendorId }: TechV
<Upload className="size-4" aria-hidden="true" />
<span className="hidden sm:inline">Import</span>
</Button>
+
+ {/** Distinct Import 버튼 (대표 이메일과 다른 담당자 추가) */}
+ <Button variant="outline" size="sm" className="gap-2" onClick={handleDistinctImportClick}>
+ <Upload className="size-4" aria-hidden="true" />
+ <span className="hidden sm:inline">Distinct Import</span>
+ </Button>
+
{/*
실제로는 숨겨진 input과 연결:
- accept=".xlsx,.xls" 등으로 Excel 파일만 업로드 허용
@@ -143,6 +248,15 @@ export function TechVendorContactsTableToolbarActions({ table, vendorId }: TechV
onChange={onFileChange}
/>
+ {/** Distinct Import용 숨겨진 input */}
+ <input
+ ref={distinctFileInputRef}
+ type="file"
+ accept=".xlsx,.xls"
+ className="hidden"
+ onChange={onDistinctFileChange}
+ />
+
{/** Export 버튼 */}
<Button
variant="outline"