From dd831478a3ab5ac7182903d41aa4b3e47f28224f Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Mon, 15 Sep 2025 10:13:11 +0000
Subject: (최겸) 구매 입찰 테스트 및 수정사항 반영
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../bidding-detail-vendor-toolbar-actions.tsx      | 88 ++++++++++++++++++++--
 1 file changed, 80 insertions(+), 8 deletions(-)

(limited to 'lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx')

diff --git a/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx b/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx
index 484b1b1e..0b707944 100644
--- a/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx
+++ b/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx
@@ -7,11 +7,14 @@ import { useTransition } from "react"
 import { Button } from "@/components/ui/button"
 import { Plus, Send, RotateCcw, XCircle, Trophy, FileText, DollarSign } from "lucide-react"
 import { QuotationVendor, registerBidding, markAsDisposal, createRebidding, awardBidding } from "@/lib/bidding/detail/service"
+import { sendBiddingBasicContracts, getSelectedVendorsForBidding } from "@/lib/bidding/pre-quote/service"
+
 import { BiddingDetailVendorCreateDialog } from "./bidding-detail-vendor-create-dialog"
 import { BiddingDocumentUploadDialog } from "./bidding-document-upload-dialog"
 import { BiddingVendorPricesDialog } from "./bidding-vendor-prices-dialog"
 import { Bidding } from "@/db/schema"
 import { useToast } from "@/hooks/use-toast"
+import { BiddingInvitationDialog } from "./bidding-invitation-dialog"
 
 interface BiddingDetailVendorToolbarActionsProps {
   table: Table<QuotationVendor>
@@ -40,6 +43,17 @@ export function BiddingDetailVendorToolbarActions({
   const [isCreateDialogOpen, setIsCreateDialogOpen] = React.useState(false)
   const [isDocumentDialogOpen, setIsDocumentDialogOpen] = React.useState(false)
   const [isPricesDialogOpen, setIsPricesDialogOpen] = React.useState(false)
+  const [isBiddingInvitationDialogOpen, setIsBiddingInvitationDialogOpen] = React.useState(false)
+  const [selectedVendors, setSelectedVendors] = React.useState<any[]>([])
+
+  // 본입찰 초대 다이얼로그가 열릴 때 선정된 업체들 조회
+  React.useEffect(() => {
+    if (isBiddingInvitationDialogOpen) {
+      getSelectedVendors().then(vendors => {
+        setSelectedVendors(vendors)
+      })
+    }
+  }, [isBiddingInvitationDialogOpen, biddingId])
 
   const handleCreateVendor = () => {
     setIsCreateDialogOpen(true)
@@ -54,23 +68,71 @@ export function BiddingDetailVendorToolbarActions({
   }
 
   const handleRegister = () => {
-    startTransition(async () => {
-      const result = await registerBidding(bidding.id, userId)
+    // 본입찰 초대 다이얼로그 열기
+    setIsBiddingInvitationDialogOpen(true)
+  }
 
-      if (result.success) {
+  const handleBiddingInvitationSend = async (data: any) => {
+    try {
+      // 1. 기본계약 발송
+      const contractResult = await sendBiddingBasicContracts(
+        biddingId,
+        data.vendors,
+        data.generatedPdfs,
+        data.message
+      )
+
+      if (!contractResult.success) {
         toast({
-          title: result.message,
-          description: result.message,
+          title: '기본계약 발송 실패',
+          description: contractResult.error,
+          variant: 'destructive',
+        })
+        return
+      }
+
+      // 2. 입찰 등록 진행
+      const registerResult = await registerBidding(bidding.id, userId)
+
+      if (registerResult.success) {
+        toast({
+          title: '본입찰 초대 완료',
+          description: '기본계약 발송 및 본입찰 초대가 완료되었습니다.',
         })
+        setIsBiddingInvitationDialogOpen(false)
         router.refresh()
+        onSuccess()
       } else {
         toast({
-          title: result.error,
-          description: result.error,
+          title: '오류',
+          description: registerResult.error,
           variant: 'destructive',
         })
       }
-    })
+    } catch (error) {
+      console.error('본입찰 초대 실패:', error)
+      toast({
+        title: '오류',
+        description: '본입찰 초대에 실패했습니다.',
+        variant: 'destructive',
+      })
+    }
+  }
+
+  // 선정된 업체들 조회 (서버 액션 함수 사용)
+  const getSelectedVendors = async () => {
+    try {
+      const result = await getSelectedVendorsForBidding(biddingId)
+      if (result.success) {
+        return result.vendors
+      } else {
+        console.error('선정된 업체 조회 실패:', result.error)
+        return []
+      }
+    } catch (error) {
+      console.error('선정된 업체 조회 실패:', error)
+      return []
+    }
   }
 
   const handleMarkAsDisposal = () => {
@@ -234,6 +296,16 @@ export function BiddingDetailVendorToolbarActions({
         targetPrice={bidding.targetPrice ? parseFloat(bidding.targetPrice.toString()) : null}
         currency={bidding.currency}
       />
+
+      <BiddingInvitationDialog
+        open={isBiddingInvitationDialogOpen}
+        onOpenChange={setIsBiddingInvitationDialogOpen}
+        vendors={selectedVendors}
+        biddingId={biddingId}
+        biddingTitle={bidding.title || ''}
+        projectName={bidding.projectName}
+        onSend={handleBiddingInvitationSend}
+      />
     </>
   )
 }
-- 
cgit v1.2.3

