diff options
Diffstat (limited to 'components/bidding/manage')
3 files changed, 55 insertions, 9 deletions
diff --git a/components/bidding/manage/bidding-basic-info-editor.tsx b/components/bidding/manage/bidding-basic-info-editor.tsx index 2f55d563..e92c39a5 100644 --- a/components/bidding/manage/bidding-basic-info-editor.tsx +++ b/components/bidding/manage/bidding-basic-info-editor.tsx @@ -1090,7 +1090,7 @@ export function BiddingBasicInfoEditor({ biddingId }: BiddingBasicInfoEditorProp /> </div> - <div className="flex flex-row items-center justify-between rounded-lg border p-3"> + {/* <div className="flex flex-row items-center justify-between rounded-lg border p-3"> <div className="space-y-0.5"> <FormLabel className="text-base">연동제 적용 가능</FormLabel> <div className="text-sm text-muted-foreground"> @@ -1106,7 +1106,7 @@ export function BiddingBasicInfoEditor({ biddingId }: BiddingBasicInfoEditorProp })) }} /> - </div> + </div> */} </div> {/* 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<Map<number, BiddingCompanyContact>>(new Map()) - + + // 입찰 정보 (단수/복수 낙찰 확인용) + const [biddingInfo, setBiddingInfo] = React.useState<any>(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 <p className="text-sm text-muted-foreground mt-1"> 입찰에 참여하는 업체들을 관리합니다. 업체를 선택하면 하단에 담당자 목록이 표시됩니다. </p> + <p className="text-sm text-muted-foreground mt-1"> 단수 입찰의 경우 1개 업체만 등록 가능합니다. </p> </div> <Button onClick={() => setAddVendorDialogOpen(true)} className="flex items-center gap-2"> <Plus className="h-4 w-4" /> @@ -657,6 +687,8 @@ export function BiddingCompaniesEditor({ biddingId }: BiddingCompaniesEditorProp open={addVendorDialogOpen} onOpenChange={setAddVendorDialogOpen} onSuccess={reloadVendors} + isSingleAwardBidding={isSingleAwardBidding} + currentVendorCount={vendors.length} /> {/* 담당자 추가 다이얼로그 (직접 입력) */} diff --git a/components/bidding/manage/bidding-detail-vendor-create-dialog.tsx b/components/bidding/manage/bidding-detail-vendor-create-dialog.tsx index ed3e2be6..205224b9 100644 --- a/components/bidding/manage/bidding-detail-vendor-create-dialog.tsx +++ b/components/bidding/manage/bidding-detail-vendor-create-dialog.tsx @@ -39,6 +39,8 @@ interface BiddingDetailVendorCreateDialogProps { open: boolean onOpenChange: (open: boolean) => void onSuccess: () => void + isSingleAwardBidding?: boolean + currentVendorCount?: number } interface Vendor { @@ -57,7 +59,9 @@ export function BiddingDetailVendorCreateDialog({ biddingId, open, onOpenChange, - onSuccess + onSuccess, + isSingleAwardBidding = false, + currentVendorCount = 0 }: BiddingDetailVendorCreateDialogProps) { const { toast } = useToast() const [isPending, startTransition] = useTransition() @@ -100,6 +104,16 @@ export function BiddingDetailVendorCreateDialog({ // 벤더 추가 const handleAddVendor = (vendor: Vendor) => { + // 단수 입찰이고 이미 업체가 선택되었거나 기존 업체가 있는 경우 제한 + if (isSingleAwardBidding && (selectedVendorsWithQuestion.length > 0 || currentVendorCount > 0)) { + toast({ + title: '제한 사항', + description: '단수 입찰의 경우 1개 업체만 등록 가능합니다.', + variant: 'destructive', + }) + return + } + if (!selectedVendorsWithQuestion.find(v => v.vendor.id === vendor.id)) { setSelectedVendorsWithQuestion([ ...selectedVendorsWithQuestion, |
