diff options
Diffstat (limited to 'components/bidding/manage/bidding-schedule-editor.tsx')
| -rw-r--r-- | components/bidding/manage/bidding-schedule-editor.tsx | 95 |
1 files changed, 72 insertions, 23 deletions
diff --git a/components/bidding/manage/bidding-schedule-editor.tsx b/components/bidding/manage/bidding-schedule-editor.tsx index f2978f95..f3260f04 100644 --- a/components/bidding/manage/bidding-schedule-editor.tsx +++ b/components/bidding/manage/bidding-schedule-editor.tsx @@ -19,7 +19,7 @@ import { BiddingInvitationDialog } from '@/lib/bidding/detail/table/bidding-invi import { sendBiddingBasicContracts, getSelectedVendorsForBidding } from '@/lib/bidding/pre-quote/service' import { registerBidding } from '@/lib/bidding/detail/service' import { useToast } from '@/hooks/use-toast' - +import { format } from 'date-fns' interface BiddingSchedule { submissionStartDate?: string submissionEndDate?: string @@ -112,7 +112,7 @@ export function BiddingScheduleEditor({ biddingId, readonly = false }: BiddingSc }) const [isLoading, setIsLoading] = React.useState(false) const [isSubmitting, setIsSubmitting] = React.useState(false) - const [biddingInfo, setBiddingInfo] = React.useState<{ title: string; projectName?: string; status: string } | null>(null) + const [biddingInfo, setBiddingInfo] = React.useState<{ title: string; projectName?: string; status: string; biddingNumber?: string } | null>(null) const [isBiddingInvitationDialogOpen, setIsBiddingInvitationDialogOpen] = React.useState(false) const [isApprovalDialogOpen, setIsApprovalDialogOpen] = React.useState(false) const [selectedVendors, setSelectedVendors] = React.useState<VendorContractRequirement[]>([]) @@ -120,6 +120,19 @@ export function BiddingScheduleEditor({ biddingId, readonly = false }: BiddingSc const [approvalTitle, setApprovalTitle] = React.useState('') const [invitationData, setInvitationData] = React.useState<BiddingInvitationData | null>(null) + // 차수 추출 헬퍼 함수 + const getRoundNumber = (biddingNumber: string): number => { + const match = biddingNumber.match(/-(\d+)$/) + return match ? parseInt(match[1]) : 1 + } + + // 차수 증가된 입찰인지 확인 (01이 아닌 경우) + const isRoundIncreased = (biddingNumber?: string): boolean => { + if (!biddingNumber) return false + const round = getRoundNumber(biddingNumber) + return round > 1 + } + // 데이터 로딩 React.useEffect(() => { const loadSchedule = async () => { @@ -132,25 +145,12 @@ export function BiddingScheduleEditor({ biddingId, readonly = false }: BiddingSc title: bidding.title || '', projectName: bidding.projectName || undefined, status: bidding.status || '', + biddingNumber: bidding.biddingNumber || undefined, }) - // 날짜를 문자열로 변환하는 헬퍼 - const formatDateTime = (date: unknown): string => { - if (!date) return '' - if (typeof date === 'string') { - // 이미 datetime-local 형식인 경우 - if (date.includes('T')) { - return date.slice(0, 16) - } - return date - } - if (date instanceof Date) return date.toISOString().slice(0, 16) - return '' - } - setSchedule({ - submissionStartDate: formatDateTime(bidding.submissionStartDate), - submissionEndDate: formatDateTime(bidding.submissionEndDate), + submissionStartDate: bidding.submissionStartDate ? new Date(bidding.submissionStartDate).toISOString().slice(0, 16) : '', + submissionEndDate: bidding.submissionEndDate ? new Date(bidding.submissionEndDate).toISOString().slice(0, 16) : '', remarks: bidding.remarks || '', isUrgent: bidding.isUrgent || false, hasSpecificationMeeting: bidding.hasSpecificationMeeting || false, @@ -286,6 +286,48 @@ export function BiddingScheduleEditor({ biddingId, readonly = false }: BiddingSc } } + // 차수 증가된 입찰의 직접 입찰공고 함수 (결재 생략) + const handleDirectBiddingInvitation = async (data: BiddingInvitationData, vendors: VendorContractRequirement[]) => { + try { + if (!session?.user?.id) { + toast({ + title: '오류', + description: '사용자 정보가 없습니다.', + variant: 'destructive', + }) + return + } + + // 입찰 등록 (결재 생략) + const result = await registerBidding(biddingId, session.user.id.toString()) + + if (result.success) { + toast({ + title: '입찰공고 완료', + description: '차수 증가된 입찰이 성공적으로 공고되었습니다.', + }) + + // 다이얼로그 닫기 및 페이지 새로고침 + setIsBiddingInvitationDialogOpen(false) + setInvitationData(null) + router.refresh() + } else { + toast({ + title: '오류', + description: result.error || '입찰공고 중 오류가 발생했습니다.', + variant: 'destructive', + }) + } + } catch (error) { + console.error('직접 입찰공고 중 오류 발생:', error) + toast({ + title: '오류', + description: '입찰공고 중 오류가 발생했습니다.', + variant: 'destructive', + }) + } + } + // 입찰 초대 발송 핸들러 - 결재 준비 및 결재 다이얼로그 열기 const handleBiddingInvitationSend = async (data: BiddingInvitationData) => { try { @@ -309,7 +351,14 @@ export function BiddingScheduleEditor({ biddingId, readonly = false }: BiddingSc return } - // 결재 데이터 준비 (템플릿 변수, 제목 등) + // 차수 증가된 입찰(02, 03 등)인지 확인 + if (isRoundIncreased(biddingInfo?.biddingNumber)) { + // 차수 증가된 입찰은 결재 생략하고 바로 입찰 등록 + await handleDirectBiddingInvitation(data, vendors) + return + } + + // 일반 입찰의 경우 결재 데이터 준비 (템플릿 변수, 제목 등) const approvalData = await prepareBiddingApprovalData({ biddingId, vendors, @@ -435,7 +484,7 @@ export function BiddingScheduleEditor({ biddingId, readonly = false }: BiddingSc <Input id="submission-start" type="datetime-local" - value={schedule.submissionStartDate || ''} + value={schedule.submissionStartDate} onChange={(e) => handleScheduleChange('submissionStartDate', e.target.value)} /> </div> @@ -444,7 +493,7 @@ export function BiddingScheduleEditor({ biddingId, readonly = false }: BiddingSc <Input id="submission-end" type="datetime-local" - value={schedule.submissionEndDate || ''} + value={schedule.submissionEndDate} onChange={(e) => handleScheduleChange('submissionEndDate', e.target.value)} /> </div> @@ -613,7 +662,7 @@ export function BiddingScheduleEditor({ biddingId, readonly = false }: BiddingSc <span className="font-medium">입찰서 제출 기간:</span> <span> {schedule.submissionStartDate && schedule.submissionEndDate - ? `${new Date(schedule.submissionStartDate).toLocaleString('ko-KR')} ~ ${new Date(schedule.submissionEndDate).toLocaleString('ko-KR')}` + ? `${format(new Date(schedule.submissionStartDate), "yyyy-MM-dd HH:mm")} ~ ${format(new Date(schedule.submissionEndDate), "yyyy-MM-dd HH:mm")}` : '미설정' } </span> @@ -634,7 +683,7 @@ export function BiddingScheduleEditor({ biddingId, readonly = false }: BiddingSc <div className="flex justify-between"> <span className="font-medium">사양설명회 일시:</span> <span> - {new Date(specMeetingInfo.meetingDate).toLocaleString('ko-KR')} + {format(new Date(specMeetingInfo.meetingDate), "yyyy-MM-dd HH:mm")} </span> </div> )} |
