"use client" import * as React from "react" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import { useSession } from "next-auth/react" import { Button } from "@/components/ui/button" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { toast } from "@/hooks/use-toast" import { Download, Loader2, Mail, Phone, User } from "lucide-react" import { Badge } from "@/components/ui/badge" // 기술영업 벤더 관련 임포트 import { getTechVendorDetailById, modifyTechVendor } from "@/lib/tech-vendors/service" import { updateTechVendorSchema, type UpdateTechVendorSchema } from "@/lib/tech-vendors/validations" import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card" import { InformationButton } from "@/components/information/information-button" // 보안 파일 다운로드 유틸리티 import import { downloadFile, quickDownload, smartFileAction, getFileInfo, formatFileSize, getSecurityInfo } from "@/lib/file-download" // 타입 정의 interface TechVendorContact { id: number contactName: string contactPosition: string | null contactEmail: string contactPhone: string | null isPrimary: boolean } interface TechVendorAttachment { id: number fileName: string filePath: string attachmentType: string fileSize?: number createdAt: Date updatedAt: Date } export function TechVendorInfoForm() { const { data: session } = useSession() const techCompanyId = session?.user?.techCompanyId // 기술영업 벤더 데이터 상태 const [vendor, setVendor] = React.useState(null) const [contacts, setContacts] = React.useState([]) const [attachments, setAttachments] = React.useState([]) const [isLoading, setIsLoading] = React.useState(true) const [isSubmitting, setIsSubmitting] = React.useState(false) const [isDownloading, setIsDownloading] = React.useState(false) // React Hook Form (기술영업 벤더용 스키마 사용) const form = useForm({ resolver: zodResolver(updateTechVendorSchema), defaultValues: { vendorName: "", vendorCode: "", address: "", email: "", phone: "", country: "", website: "", techVendorType: "", status: "ACTIVE", }, mode: "onChange", }) const isFormValid = form.formState.isValid // 기술영업 벤더 정보 가져오기 React.useEffect(() => { async function fetchTechVendorData() { if (!techCompanyId) return try { setIsLoading(true) // 기술영업 벤더 상세 정보 가져오기 (연락처, 첨부파일 포함) const vendorData = await getTechVendorDetailById(Number(techCompanyId)) if (!vendorData) { toast({ variant: "destructive", title: "오류", description: "기술영업 벤더 정보를 찾을 수 없습니다.", }) return } setVendor(vendorData) setContacts(vendorData.contacts || []) setAttachments(vendorData.attachments || []) // 폼 기본값 설정 const formValues = { vendorName: vendorData.vendorName || "", vendorCode: vendorData.vendorCode || "", address: vendorData.address || "", email: vendorData.email || "", phone: vendorData.phone || "", country: vendorData.country || "", website: vendorData.website || "", techVendorType: vendorData.techVendorType || "", status: vendorData.status || "ACTIVE", } form.reset(formValues) } catch (error) { console.error("Error fetching tech vendor data:", error) toast({ variant: "destructive", title: "데이터 로드 오류", description: "기술영업 벤더 정보를 불러오는 중 오류가 발생했습니다.", }) } finally { setIsLoading(false) } } fetchTechVendorData() }, [techCompanyId, form]) // 보안 다운로드 유틸리티를 사용한 개별 파일 다운로드 const handleDownloadFile = async (file: TechVendorAttachment) => { try { setIsDownloading(true) // API 엔드포인트 URL 구성 const downloadUrl = `/api/tech-vendors/attachments/download?id=${file.id}&vendorId=${Number(techCompanyId)}` // 보안 다운로드 유틸리티 사용 const result = await downloadFile(downloadUrl, file.fileName, { action: 'download', showToast: false, // 우리가 직접 토스트 관리 onSuccess: (fileName, fileSize) => { const sizeText = fileSize ? ` (${formatFileSize(fileSize)})` : ''; toast({ title: "다운로드 완료", description: `파일 다운로드가 완료되었습니다: ${fileName}${sizeText}`, }); }, onError: (error) => { console.error("Download error:", error); toast({ variant: "destructive", title: "다운로드 오류", description: error || "파일 다운로드 중 오류가 발생했습니다.", }); } }); if (!result.success && result.error) { // 오류 처리는 onError 콜백에서 이미 처리됨 console.error("Download failed:", result.error); } } catch (error) { console.error("Error downloading file:", error); toast({ variant: "destructive", title: "다운로드 오류", description: "파일 다운로드 중 예상치 못한 오류가 발생했습니다.", }); } finally { setIsDownloading(false); } } // 보안 다운로드 유틸리티를 사용한 전체 파일 다운로드 const handleDownloadAllFiles = async () => { try { setIsDownloading(true) // 전체 파일 다운로드 API 엔드포인트 const downloadUrl = `/api/tech-vendors/attachments/download-all?vendorId=${Number(techCompanyId)}` const fileName = `tech-vendor-${techCompanyId}-files.zip` // 보안 다운로드 유틸리티 사용 const result = await downloadFile(downloadUrl, fileName, { action: 'download', showToast: false, // 우리가 직접 토스트 관리 onSuccess: (fileName, fileSize) => { const sizeText = fileSize ? ` (${formatFileSize(fileSize)})` : ''; toast({ title: "전체 다운로드 완료", description: `전체 파일 다운로드가 완료되었습니다: ${fileName}${sizeText}`, }); }, onError: (error) => { console.error("Download all error:", error); toast({ variant: "destructive", title: "다운로드 오류", description: error || "전체 파일 다운로드 중 오류가 발생했습니다.", }); } }); if (!result.success && result.error) { // 오류 처리는 onError 콜백에서 이미 처리됨 console.error("Download all failed:", result.error); } } catch (error) { console.error("Error downloading files:", error); toast({ variant: "destructive", title: "다운로드 오류", description: "전체 파일 다운로드 중 예상치 못한 오류가 발생했습니다.", }); } finally { setIsDownloading(false); } } async function onSubmit(values: UpdateTechVendorSchema) { if (!techCompanyId) return setIsSubmitting(true) try { const { error } = await modifyTechVendor({ ...values, id: String(techCompanyId), }) if (error) { throw new Error(error) } toast({ title: "업데이트 완료", description: "기술영업 벤더 정보가 성공적으로 업데이트되었습니다.", }) } catch (error) { console.error("Error updating tech vendor:", error) toast({ variant: "destructive", title: "업데이트 오류", description: "기술영업 벤더 정보 업데이트 중 오류가 발생했습니다.", }) } finally { setIsSubmitting(false) } } if (isLoading) { return (
기술영업 벤더 정보를 불러오는 중...
) } if (!vendor) { return (
기술영업 벤더 정보를 찾을 수 없습니다.
) } // 보안 정보 가져오기 const securityInfo = getSecurityInfo(); return (

기술영업 벤더 정보

기술영업 벤더 정보를 확인하고 업데이트할 수 있습니다.

{/* 보안 정보 표시 */}

📁 허용 파일 크기: {securityInfo.maxFileSizeFormatted} | 남은 다운로드: {securityInfo.remainingDownloads}/분

{attachments.length > 0 && ( )}
기본 정보
( 벤더명 )} /> ( 벤더 코드 )} />
{/* 사업자등록번호 */} {vendor.taxId && (

{vendor.taxId}

)} {/* 공급품목 */} {vendor.items && (

{vendor.items}

)}
( 이메일 )} /> ( 전화번호 )} />
( 주소 )} />
( 국가 )} /> ( 웹사이트 )} />
{/* 연락처 정보 */} {contacts.length > 0 && ( 연락처 정보 등록된 연락처 정보입니다.
{contacts.map((contact) => (

{contact.contactName}

{contact.isPrimary && ( 주 담당자 )}
{contact.contactPosition && (

{contact.contactPosition}

)}
{contact.contactEmail && ( )} {contact.contactPhone && ( )}
))}
)} {/* 첨부파일 정보 - 보안 강화된 버전 */} {attachments.length > 0 && ( 첨부파일 업로드된 파일들을 확인하고 다운로드할 수 있습니다.
{attachments.map((file) => { const fileInfo = getFileInfo(file.fileName); return (
{fileInfo.icon}

{file.fileName}

{file.attachmentType} {new Date(file.createdAt).toLocaleDateString()} {file.fileSize && ( <> {formatFileSize(file.fileSize)} )}
); })}
)}
) }