From 14f61e24947fb92dd71ec0a7196a6e815f8e66da Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Mon, 21 Jul 2025 07:54:26 +0000
Subject: (최겸)기술영업 RFQ 담당자 초대, 요구사항 반영
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../quotation-contacts-view-dialog.tsx             | 173 +++++++++++++++++++++
 1 file changed, 173 insertions(+)
 create mode 100644 lib/techsales-rfq/table/detail-table/quotation-contacts-view-dialog.tsx

(limited to 'lib/techsales-rfq/table/detail-table/quotation-contacts-view-dialog.tsx')

diff --git a/lib/techsales-rfq/table/detail-table/quotation-contacts-view-dialog.tsx b/lib/techsales-rfq/table/detail-table/quotation-contacts-view-dialog.tsx
new file mode 100644
index 00000000..3e793b62
--- /dev/null
+++ b/lib/techsales-rfq/table/detail-table/quotation-contacts-view-dialog.tsx
@@ -0,0 +1,173 @@
+"use client"
+
+import * as React from "react"
+import { useState, useEffect, useCallback } from "react"
+import {
+  Dialog,
+  DialogContent,
+  DialogDescription,
+  DialogHeader,
+  DialogTitle,
+} from "@/components/ui/dialog"
+import { Button } from "@/components/ui/button"
+import { Badge } from "@/components/ui/badge"
+import { Skeleton } from "@/components/ui/skeleton"
+import { Mail, Phone, User, Users } from "lucide-react"
+import { getQuotationContacts } from "../../service"
+
+interface QuotationContact {
+  id: number
+  contactId: number
+  contactName: string
+  contactPosition: string | null
+  contactEmail: string
+  contactPhone: string | null
+  contactCountry: string | null
+  isPrimary: boolean
+  createdAt: Date
+}
+
+interface QuotationContactsViewDialogProps {
+  open: boolean
+  onOpenChange: (open: boolean) => void
+  quotationId: number | null
+  vendorName?: string
+}
+
+export function QuotationContactsViewDialog({
+  open,
+  onOpenChange,
+  quotationId,
+  vendorName
+}: QuotationContactsViewDialogProps) {
+  const [contacts, setContacts] = useState<QuotationContact[]>([])
+  const [isLoading, setIsLoading] = useState(false)
+
+  // 담당자 정보 로드
+  const loadQuotationContacts = useCallback(async () => {
+    if (!quotationId) return
+    
+    setIsLoading(true)
+    try {
+      const result = await getQuotationContacts(quotationId)
+      if (result.success) {
+        setContacts(result.data || [])
+      } else {
+        console.error("담당자 정보 로드 실패:", result.error)
+        setContacts([])
+      }
+    } catch (error) {
+      console.error("담당자 정보 로드 오류:", error)
+      setContacts([])
+    } finally {
+      setIsLoading(false)
+    }
+  }, [quotationId])
+
+  // Dialog가 열릴 때 데이터 로드
+  useEffect(() => {
+    if (open && quotationId) {
+      loadQuotationContacts()
+    }
+  }, [open, quotationId, loadQuotationContacts])
+
+  // Dialog가 닫힐 때 상태 초기화
+  useEffect(() => {
+    if (!open) {
+      setContacts([])
+    }
+  }, [open])
+
+  return (
+    <Dialog open={open} onOpenChange={onOpenChange}>
+      <DialogContent className="max-w-2xl max-h-[70vh] overflow-hidden flex flex-col">
+        <DialogHeader>
+          <DialogTitle className="flex items-center gap-2">
+            <Users className="size-5" />
+            RFQ 발송 담당자 목록
+          </DialogTitle>
+          <DialogDescription>
+            {vendorName && (
+              <span className="font-medium">{vendorName}</span>
+            )} 에게 발송된 RFQ의 담당자 정보입니다.
+          </DialogDescription>
+        </DialogHeader>
+        
+        <div className="flex-1 overflow-y-auto">
+          {isLoading ? (
+            <div className="space-y-3">
+              {[1, 2, 3].map((i) => (
+                <Skeleton key={i} className="h-20 w-full" />
+              ))}
+            </div>
+          ) : contacts.length === 0 ? (
+            <div className="text-center py-8 text-muted-foreground">
+              <Mail className="size-12 mx-auto mb-2 opacity-50" />
+              <p>발송된 담당자 정보가 없습니다.</p>
+              <p className="text-sm">아직 RFQ가 발송되지 않았거나 담당자 정보가 기록되지 않았습니다.</p>
+            </div>
+          ) : (
+            <div className="space-y-3">
+              {contacts.map((contact) => (
+                <div
+                  key={contact.id}
+                  className="flex items-center justify-between p-4 border rounded-lg bg-gray-50"
+                >
+                  <div className="flex items-center gap-3">
+                    <User className="size-4 text-muted-foreground" />
+                    <div>
+                      <div className="flex items-center gap-2">
+                        <span className="font-medium">{contact.contactName}</span>
+                        {contact.isPrimary && (
+                          <Badge variant="secondary" className="text-xs">
+                            주담당자
+                          </Badge>
+                        )}
+                      </div>
+                      {contact.contactPosition && (
+                        <p className="text-sm text-muted-foreground">
+                          {contact.contactPosition}
+                        </p>
+                      )}
+                      {contact.contactCountry && (
+                        <p className="text-xs text-muted-foreground">
+                          {contact.contactCountry}
+                        </p>
+                      )}
+                    </div>
+                  </div>
+                  
+                  <div className="flex flex-col items-end gap-1 text-sm">
+                    <div className="flex items-center gap-1">
+                      <Mail className="size-4 text-muted-foreground" />
+                      <span>{contact.contactEmail}</span>
+                    </div>
+                    {contact.contactPhone && (
+                      <div className="flex items-center gap-1">
+                        <Phone className="size-4 text-muted-foreground" />
+                        <span>{contact.contactPhone}</span>
+                      </div>
+                    )}
+                    <div className="text-xs text-muted-foreground">
+                      발송일: {new Date(contact.createdAt).toLocaleDateString('ko-KR')}
+                    </div>
+                  </div>
+                </div>
+              ))}
+              
+              <div className="text-center pt-4 text-sm text-muted-foreground border-t">
+                총 {contacts.length}명의 담당자에게 발송됨
+              </div>
+            </div>
+          )}
+        </div>
+
+        <div className="flex justify-end pt-4">
+          <Button variant="outline" onClick={() => onOpenChange(false)}>
+            닫기
+          </Button>
+        </div>
+      </DialogContent>
+    </Dialog>
+  )
+} 
\ No newline at end of file
-- 
cgit v1.2.3

