diff options
Diffstat (limited to 'components')
5 files changed, 72 insertions, 17 deletions
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<typeof reAuthSchema> 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 ( - <Dialog open={isOpen} onOpenChange={() => {}}> + <Dialog open={isOpen} onOpenChange={(open) => { + if (!open && onClose) { + onClose() + } + }}> <DialogContent className="sm:max-w-[400px]"> <DialogHeader> <DialogTitle className="flex items-center gap-2"> 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 지급조건 */}
<div className="grid grid-cols-2 gap-4">
- <FormField
+ {/* <FormField
control={form.control}
name="biddingConditions.isPriceAdjustmentApplicable"
render={({ field }) => (
@@ -634,7 +634,7 @@ export function BiddingCreateDialog({ form, onSuccess }: BiddingCreateDialogProp <FormMessage />
</FormItem>
)}
- />
+ /> */}
<FormField
control={form.control}
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, |
