"use client" import * as React from "react" import { useState, useEffect, useCallback } from "react" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Button } from "@/components/ui/button" import { Checkbox } from "@/components/ui/checkbox" import { Badge } from "@/components/ui/badge" import { Skeleton } from "@/components/ui/skeleton" import { Mail, Phone, User, Send, Loader2 } from "lucide-react" import { toast } from "sonner" interface VendorContact { id: number contactName: string contactPosition: string | null contactEmail: string contactPhone: string | null isPrimary: boolean } interface VendorWithContacts { vendor: { id: number vendorName: string vendorCode: string | null } contacts: VendorContact[] } interface SelectedContact { vendorId: number contactId: number contactEmail: string contactName: string } interface VendorContactSelectionDialogProps { open: boolean onOpenChange: (open: boolean) => void vendorIds: number[] onSendRfq: (selectedContacts: SelectedContact[]) => Promise } export function VendorContactSelectionDialog({ open, onOpenChange, vendorIds, onSendRfq }: VendorContactSelectionDialogProps) { const [vendorsWithContacts, setVendorsWithContacts] = useState>({}) const [selectedContacts, setSelectedContacts] = useState([]) const [isLoading, setIsLoading] = useState(false) const [isSending, setIsSending] = useState(false) // 벤더 contact 정보 조회 useEffect(() => { if (open && vendorIds.length > 0) { loadVendorsContacts() } }, [open, vendorIds]) // 다이얼로그 닫힐 때 상태 초기화 useEffect(() => { if (!open) { setVendorsWithContacts({}) setSelectedContacts([]) setIsLoading(false) } }, [open]) const loadVendorsContacts = useCallback(async () => { try { setIsLoading(true) const { getTechVendorsContacts } = await import("@/lib/techsales-rfq/service") const result = await getTechVendorsContacts(vendorIds) if (result.error) { toast.error(result.error) return } setVendorsWithContacts(result.data) // 기본 선택: 모든 contact 선택 const defaultSelected: SelectedContact[] = [] Object.values(result.data).forEach(vendorData => { vendorData.contacts.forEach(contact => { defaultSelected.push({ vendorId: vendorData.vendor.id, contactId: contact.id, contactEmail: contact.contactEmail, contactName: contact.contactName }) }) }) setSelectedContacts(defaultSelected) } catch (error) { console.error("벤더 contact 조회 오류:", error) toast.error("벤더 연락처를 불러오는 중 오류가 발생했습니다") } finally { setIsLoading(false) } }, [vendorIds]) // contact 선택/해제 핸들러 const handleContactToggle = (vendorId: number, contact: VendorContact) => { const isSelected = selectedContacts.some( sc => sc.vendorId === vendorId && sc.contactId === contact.id ) if (isSelected) { // 선택 해제 setSelectedContacts(prev => prev.filter(sc => !(sc.vendorId === vendorId && sc.contactId === contact.id)) ) } else { // 선택 추가 setSelectedContacts(prev => [ ...prev, { vendorId, contactId: contact.id, contactEmail: contact.contactEmail, contactName: contact.contactName } ]) } } // 벤더별 전체 선택/해제 const handleVendorToggle = (vendorId: number, vendorData: VendorWithContacts) => { const vendorContacts = vendorData.contacts const selectedVendorContacts = selectedContacts.filter(sc => sc.vendorId === vendorId) if (selectedVendorContacts.length === vendorContacts.length) { // 전체 해제 setSelectedContacts(prev => prev.filter(sc => sc.vendorId !== vendorId)) } else { // 전체 선택 const newSelected = vendorContacts.map(contact => ({ vendorId, contactId: contact.id, contactEmail: contact.contactEmail, contactName: contact.contactName })) setSelectedContacts(prev => [ ...prev.filter(sc => sc.vendorId !== vendorId), ...newSelected ]) } } // RFQ 발송 핸들러 const handleSendRfq = async () => { if (selectedContacts.length === 0) { toast.warning("발송할 연락처를 선택해주세요.") return } try { setIsSending(true) await onSendRfq(selectedContacts) onOpenChange(false) } catch (error) { console.error("RFQ 발송 오류:", error) } finally { setIsSending(false) } } // 선택된 contact가 있는지 확인 const isContactSelected = (vendorId: number, contactId: number) => { return selectedContacts.some(sc => sc.vendorId === vendorId && sc.contactId === contactId) } // 벤더별 선택 상태 확인 const getVendorSelectionState = (vendorId: number, vendorData: VendorWithContacts) => { const selectedVendorContacts = selectedContacts.filter(sc => sc.vendorId === vendorId) const totalContacts = vendorData.contacts.length if (selectedVendorContacts.length === 0) return "none" if (selectedVendorContacts.length === totalContacts) return "all" return "partial" } return ( RFQ 발송 대상 선택 각 벤더의 연락처를 선택하여 RFQ를 발송하세요. 기본적으로 모든 연락처가 선택되어 있습니다.
{isLoading ? (
{[1, 2, 3].map((i) => (
))}
) : Object.keys(vendorsWithContacts).length === 0 ? (

연락처 정보가 없습니다.

벤더의 연락처를 먼저 등록해주세요.

) : ( Object.entries(vendorsWithContacts).map(([vendorId, vendorData]) => { const selectionState = getVendorSelectionState(Number(vendorId), vendorData) return (
{ if (el) { const input = el.querySelector('input[type="checkbox"]') as HTMLInputElement if (input) { input.indeterminate = selectionState === "partial" } } }} onCheckedChange={() => handleVendorToggle(Number(vendorId), vendorData)} />

{vendorData.vendor.vendorName}

{vendorData.vendor.vendorCode && (

코드: {vendorData.vendor.vendorCode}

)}
{selectedContacts.filter(sc => sc.vendorId === Number(vendorId)).length} / {vendorData.contacts.length} 선택됨
{vendorData.contacts.map((contact) => (
handleContactToggle(Number(vendorId), contact)} />
{contact.contactName}
{contact.contactPosition && (

{contact.contactPosition}

)}
{contact.contactEmail}
{contact.contactPhone && (
{contact.contactPhone}
)}
))}
) }) )}
총 {selectedContacts.length}명의 연락처가 선택됨
) }