From 213b995271edfbe7604d07ba4b71fcc20038a894 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 17 Nov 2025 10:00:07 +0000 Subject: (최겸) 구매 입찰 수정 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/auth/simple-reauth-modal.tsx | 21 ++++++++--- .../bidding/create/bidding-create-dialog.tsx | 4 +- .../bidding/manage/bidding-basic-info-editor.tsx | 4 +- .../bidding/manage/bidding-companies-editor.tsx | 44 +++++++++++++++++++--- .../manage/bidding-detail-vendor-create-dialog.tsx | 16 +++++++- 5 files changed, 72 insertions(+), 17 deletions(-) (limited to 'components') diff --git a/components/auth/simple-reauth-modal.tsx b/components/auth/simple-reauth-modal.tsx index f00674e3..80f03ad9 100644 --- a/components/auth/simple-reauth-modal.tsx +++ b/components/auth/simple-reauth-modal.tsx @@ -36,13 +36,15 @@ type ReAuthFormValues = z.infer interface SimpleReAuthModalProps { isOpen: boolean onSuccess: () => void + onClose?: () => void userEmail: string } -export function SimpleReAuthModal({ - isOpen, - onSuccess, - userEmail +export function SimpleReAuthModal({ + isOpen, + onSuccess, + onClose, + userEmail }: SimpleReAuthModalProps) { const [isLoading, setIsLoading] = React.useState(false) const [attemptCount, setAttemptCount] = React.useState(0) @@ -114,11 +116,18 @@ export function SimpleReAuthModal({ if (!isOpen) { form.reset() setAttemptCount(0) + if (onClose) { + // 모달이 닫힐 때 정리 작업 + } } - }, [isOpen, form]) + }, [isOpen, form, onClose]) return ( - {}}> + { + if (!open && onClose) { + onClose() + } + }}> diff --git a/components/bidding/create/bidding-create-dialog.tsx b/components/bidding/create/bidding-create-dialog.tsx index 30550ca4..bdb00a01 100644 --- a/components/bidding/create/bidding-create-dialog.tsx +++ b/components/bidding/create/bidding-create-dialog.tsx @@ -609,7 +609,7 @@ export function BiddingCreateDialog({ form, onSuccess }: BiddingCreateDialogProp {/* 4행: 하도급법적용여부, SHI 지급조건 */}
- ( @@ -634,7 +634,7 @@ export function BiddingCreateDialog({ form, onSuccess }: BiddingCreateDialogProp )} - /> + /> */}
-
+ {/*
연동제 적용 가능
@@ -1106,7 +1106,7 @@ export function BiddingBasicInfoEditor({ biddingId }: BiddingBasicInfoEditorProp })) }} /> -
+
*/}
{/* 5행: 스페어파트 옵션 */} diff --git a/components/bidding/manage/bidding-companies-editor.tsx b/components/bidding/manage/bidding-companies-editor.tsx index 1ce8b014..4992c2ab 100644 --- a/components/bidding/manage/bidding-companies-editor.tsx +++ b/components/bidding/manage/bidding-companies-editor.tsx @@ -5,13 +5,14 @@ import { Building, User, Plus, Trash2 } from 'lucide-react' import { toast } from 'sonner' import { Button } from '@/components/ui/button' -import { - getBiddingVendors, +import { + getBiddingVendors, getBiddingCompanyContacts, createBiddingCompanyContact, deleteBiddingCompanyContact, getVendorContactsByVendorId, - updateBiddingCompanyPriceAdjustmentQuestion + updateBiddingCompanyPriceAdjustmentQuestion, + getBiddingById } from '@/lib/bidding/service' import { deleteBiddingCompany } from '@/lib/bidding/pre-quote/service' import { BiddingDetailVendorCreateDialog } from './bidding-detail-vendor-create-dialog' @@ -87,7 +88,11 @@ export function BiddingCompaniesEditor({ biddingId }: BiddingCompaniesEditorProp const [isLoadingContacts, setIsLoadingContacts] = React.useState(false) // 각 업체별 첫 번째 담당자 정보 저장 (vendorId -> 첫 번째 담당자) const [vendorFirstContacts, setVendorFirstContacts] = React.useState>(new Map()) - + + // 입찰 정보 (단수/복수 낙찰 확인용) + const [biddingInfo, setBiddingInfo] = React.useState(null) + const [isLoadingBiddingInfo, setIsLoadingBiddingInfo] = React.useState(false) + // 담당자 추가 다이얼로그 const [addContactDialogOpen, setAddContactDialogOpen] = React.useState(false) const [newContact, setNewContact] = React.useState({ @@ -141,6 +146,29 @@ export function BiddingCompaniesEditor({ biddingId }: BiddingCompaniesEditorProp } }, [biddingId]) + // 입찰 정보 로딩 + const loadBiddingInfo = React.useCallback(async () => { + setIsLoadingBiddingInfo(true) + try { + const result = await getBiddingById(biddingId) + if (result) { + setBiddingInfo(result) + } else { + console.error('Failed to load bidding info') + setBiddingInfo(null) + } + } catch (error) { + console.error('Failed to load bidding info:', error) + setBiddingInfo(null) + } finally { + setIsLoadingBiddingInfo(false) + } + }, [biddingId]) + + // 단수 입찰 여부 확인 및 업체 추가 제한 + const isSingleAwardBidding = biddingInfo?.awardCount === 'single' + const canAddVendor = !isSingleAwardBidding || vendors.length === 0 + // 데이터 로딩 React.useEffect(() => { const loadVendors = async () => { @@ -177,7 +205,7 @@ export function BiddingCompaniesEditor({ biddingId }: BiddingCompaniesEditorProp console.error(`Failed to load contact for vendor ${vendor.companyId}:`, error) } }) - + await Promise.all(contactPromises) setVendorFirstContacts(firstContactsMap) } else { @@ -194,7 +222,8 @@ export function BiddingCompaniesEditor({ biddingId }: BiddingCompaniesEditorProp } loadVendors() - }, [biddingId]) + loadBiddingInfo() + }, [biddingId, loadBiddingInfo]) // 업체 선택 핸들러 (단일 선택) const handleVendorSelect = async (vendor: QuotationVendor) => { @@ -482,6 +511,7 @@ export function BiddingCompaniesEditor({ biddingId }: BiddingCompaniesEditorProp

입찰에 참여하는 업체들을 관리합니다. 업체를 선택하면 하단에 담당자 목록이 표시됩니다.

+

단수 입찰의 경우 1개 업체만 등록 가능합니다.