summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/bidding/manage/bidding-schedule-editor.tsx95
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>
)}