"use client" import * as React from "react" import { useRouter } from "next/navigation" import { useTransition } from "react" import { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Plus, Send, RotateCcw, XCircle, Trophy, FileText, DollarSign, RotateCw, Link2 } from "lucide-react" import { registerBidding, markAsDisposal, cancelAwardRatio } from "@/lib/bidding/detail/service" import { sendBiddingBasicContracts, getSelectedVendorsForBidding } from "@/lib/bidding/pre-quote/service" import { increaseRoundOrRebid } from "@/lib/bidding/service" import { BiddingDetailVendorCreateDialog } from "../../../../components/bidding/manage/bidding-detail-vendor-create-dialog" import { BiddingDocumentUploadDialog } from "./bidding-document-upload-dialog" import { PriceAdjustmentDialog } from "./price-adjustment-dialog" import { Bidding } from "@/db/schema" import { useToast } from "@/hooks/use-toast" import { QuotationVendor } from "@/lib/bidding/detail/service" interface BiddingDetailVendorToolbarActionsProps { biddingId: number bidding: Bidding userId: string onOpenAwardDialog: () => void onOpenAwardRatioDialog: () => void onSuccess: () => void winnerVendor?: QuotationVendor | null // 100% 낙찰된 벤더 singleSelectedVendor?: QuotationVendor | null // single select된 벤더 readOnly?: boolean } export function BiddingDetailVendorToolbarActions({ biddingId, bidding, userId, onOpenAwardDialog, onOpenAwardRatioDialog, onSuccess, winnerVendor, singleSelectedVendor, readOnly = false }: BiddingDetailVendorToolbarActionsProps) { const router = useRouter() const { toast } = useToast() const [isPending, startTransition] = useTransition() 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([]) const [isRoundIncreaseDialogOpen, setIsRoundIncreaseDialogOpen] = React.useState(false) const [isCancelAwardDialogOpen, setIsCancelAwardDialogOpen] = React.useState(false) const [isPriceAdjustmentDialogOpen, setIsPriceAdjustmentDialogOpen] = React.useState(false) // 본입찰 초대 다이얼로그가 열릴 때 선정된 업체들 조회 React.useEffect(() => { if (isBiddingInvitationDialogOpen) { getSelectedVendors().then(vendors => { setSelectedVendors(vendors) }) } }, [isBiddingInvitationDialogOpen, biddingId]) const handleCreateVendor = () => { setIsCreateDialogOpen(true) } const handleDocumentUpload = () => { setIsDocumentDialogOpen(true) } const handleViewVendorPrices = () => { setIsPricesDialogOpen(true) } const handleRegister = () => { if (!bidding.targetPrice) { toast({ title: '오류', description: '내정가가 산정되어야 입찰 초대를 할 수 있습니다.', variant: 'destructive', }) return } // 본입찰 초대 다이얼로그 열기 setIsBiddingInvitationDialogOpen(true) } // 선정된 업체들 조회 (서버 액션 함수 사용) 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 = () => { startTransition(async () => { const result = await markAsDisposal(bidding.id, userId) if (result.success) { toast({ title: result.message, description: result.message, }) router.refresh() } else { toast({ title: result.error, description: result.error, variant: 'destructive', }) } }) } const handleCancelAward = () => { if (!winnerVendor) return startTransition(async () => { const result = await cancelAwardRatio(winnerVendor.id) if (result.success) { toast({ title: "성공", description: result.message, }) setIsCancelAwardDialogOpen(false) onSuccess() } else { toast({ title: "오류", description: result.error || "발주비율 취소 중 오류가 발생했습니다.", variant: 'destructive', }) } }) } const handleRoundIncreaseWithNavigation = () => { startTransition(async () => { const result = await increaseRoundOrRebid(bidding.id, userId, 'round_increase') if (result.success) { toast({ title: "성공", description: '차수증가가 완료되었습니다.', }) router.push(`/evcp/bid`) onSuccess() } else { toast({ title: "오류", description: result.error || "차수증가 중 오류가 발생했습니다.", variant: 'destructive', }) } }) } return ( <>
{/* 상태별 액션 버튼 - 읽기 전용이 아닐 때만 표시 */} {!readOnly && ( <> {/* 차수증가: 입찰공고 또는 입찰평가중 상태에서만 */} {(bidding.status === 'evaluation_of_bidding' || bidding.status === 'bidding_opened') && ( )} {/* 발주비율 산정: single select 시에만 활성화 */} {(bidding.status === 'evaluation_of_bidding') && ( )} {/* 연동제 적용여부: single select 시에만 활성화 */} {(bidding.status === 'evaluation_of_bidding') && ( )} {/* 유찰/낙찰: 입찰공고 또는 입찰평가중 상태에서만 */} {(bidding.status === 'bidding_opened' || bidding.status === 'evaluation_of_bidding') && ( <> )} {/* 발주비율 취소: 100% 낙찰된 벤더가 있는 경우 */} {winnerVendor && ( )} )} {/* 구분선 */} {(bidding.status === 'bidding_generated' || bidding.status === 'bidding_disposal') && (
)} {/* */}
{ onSuccess() setIsCreateDialogOpen(false) }} /> {/* 차수증가 확인 다이얼로그 */} 차수증가 확인 입찰을 차수증가 처리하시겠습니까? 차수증가 후 입찰 관리 페이지로 이동합니다. {/* 발주비율 취소 확인 다이얼로그 */} 발주비율 취소 확인 {winnerVendor && ( <> {winnerVendor.vendorName} 업체의 발주비율(100%)을 취소하시겠습니까?
취소 후 다른 업체의 발주비율을 설정할 수 있습니다. )}
{/* 연동제 적용여부 다이얼로그 */} ) }