diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-02 10:30:58 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-02 10:30:58 +0000 |
| commit | 581b415e6707d9f1d0d0b667b84c4314461bfe37 (patch) | |
| tree | 5476543a290ada5c3f29a0cba24ee86fc9c215b2 /lib/bidding/vendor/partners-bidding-detail.tsx | |
| parent | d5ddafa4276b0031538261400e431009b0734be9 (diff) | |
(최겸) 입찰 등록, 협력업체 응찰 기능 개발
Diffstat (limited to 'lib/bidding/vendor/partners-bidding-detail.tsx')
| -rw-r--r-- | lib/bidding/vendor/partners-bidding-detail.tsx | 176 |
1 files changed, 73 insertions, 103 deletions
diff --git a/lib/bidding/vendor/partners-bidding-detail.tsx b/lib/bidding/vendor/partners-bidding-detail.tsx index 4c4db37f..c6ba4926 100644 --- a/lib/bidding/vendor/partners-bidding-detail.tsx +++ b/lib/bidding/vendor/partners-bidding-detail.tsx @@ -29,7 +29,6 @@ import { submitPartnerResponse, updatePartnerAttendance } from '../detail/service' -import { PartnersBiddingAttendanceDialog } from './partners-bidding-attendance-dialog' import { biddingStatusLabels, contractTypeLabels, @@ -75,20 +74,15 @@ interface BiddingDetail { finalQuoteSubmittedAt: string isWinner: boolean isAttendingMeeting: boolean | null - offeredPaymentTerms: string - offeredTaxConditions: string - offeredIncoterms: string - offeredContractDeliveryDate: string - offeredShippingPort: string - offeredDestinationPort: string - isPriceAdjustmentApplicable: boolean - responsePaymentTerms: string - responseTaxConditions: string - responseIncoterms: string + // companyConditionResponses에서 가져온 조건들 (제시된 조건과 응답 모두) + paymentTermsResponse: string + taxConditionsResponse: string + incotermsResponse: string proposedContractDeliveryDate: string proposedShippingPort: string proposedDestinationPort: string priceAdjustmentResponse: boolean + sparePartResponse: string additionalProposals: string responseSubmittedAt: string } @@ -110,13 +104,11 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD proposedShippingPort: '', proposedDestinationPort: '', priceAdjustmentResponse: false, + sparePartResponse: '', additionalProposals: '', isAttendingMeeting: false, }) - // 사양설명회 참석 여부 다이얼로그 상태 - const [isAttendanceDialogOpen, setIsAttendanceDialogOpen] = React.useState(false) - // 데이터 로드 React.useEffect(() => { const loadData = async () => { @@ -129,15 +121,16 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD // 기존 응답 데이터로 폼 초기화 setResponseData({ finalQuoteAmount: result.finalQuoteAmount?.toString() || '', - paymentTermsResponse: result.responsePaymentTerms || '', - taxConditionsResponse: result.responseTaxConditions || '', - incotermsResponse: result.responseIncoterms || '', + paymentTermsResponse: result.paymentTermsResponse || '', + taxConditionsResponse: result.taxConditionsResponse || '', + incotermsResponse: result.incotermsResponse || '', proposedContractDeliveryDate: result.proposedContractDeliveryDate || '', proposedShippingPort: result.proposedShippingPort || '', proposedDestinationPort: result.proposedDestinationPort || '', priceAdjustmentResponse: result.priceAdjustmentResponse || false, + sparePartResponse: result.sparePartResponse || '', additionalProposals: result.additionalProposals || '', - isAttendingMeeting: false, // TODO: biddingCompanies에서 가져와야 함 + isAttendingMeeting: result.isAttendingMeeting || false, }) } } catch (error) { @@ -180,6 +173,7 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD proposedShippingPort: responseData.proposedShippingPort, proposedDestinationPort: responseData.proposedDestinationPort, priceAdjustmentResponse: responseData.priceAdjustmentResponse, + sparePartResponse: responseData.sparePartResponse, additionalProposals: responseData.additionalProposals, }, 'current-user' // TODO: 실제 사용자 ID @@ -191,15 +185,6 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD description: result.message, }) - // 사양설명회 참석 여부도 업데이트 - if (responseData.isAttendingMeeting !== undefined) { - await updatePartnerAttendance( - biddingDetail.biddingCompanyId, - responseData.isAttendingMeeting, - 'current-user' - ) - } - // 데이터 새로고침 const updatedDetail = await getBiddingDetailsForPartners(biddingId, companyId) if (updatedDetail) { @@ -272,26 +257,6 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD </div> </div> - {/* 사양설명회 참석 여부 버튼 */} - <div className="flex items-center gap-2"> - <Button - variant="outline" - onClick={() => setIsAttendanceDialogOpen(true)} - className="flex items-center gap-2" - > - <Users className="w-4 h-4" /> - 사양설명회 참석 - {biddingDetail.isAttendingMeeting !== null && ( - <div className="ml-1"> - {biddingDetail.isAttendingMeeting ? ( - <CheckCircle className="w-4 h-4 text-green-600" /> - ) : ( - <XCircle className="w-4 h-4 text-red-600" /> - )} - </div> - )} - </Button> - </div> </div> {/* 입찰 공고 섹션 */} @@ -368,48 +333,68 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD </CardContent> </Card> - {/* 제시된 조건 섹션 */} + {/* 현재 설정된 조건 섹션 */} <Card> <CardHeader> - <CardTitle>제시된 입찰 조건</CardTitle> + <CardTitle>현재 설정된 입찰 조건</CardTitle> </CardHeader> <CardContent> - <div className="space-y-4"> + <div className="grid grid-cols-2 gap-4"> <div> <Label className="text-sm font-medium">지급조건</Label> <div className="mt-1 p-3 bg-muted rounded-md"> - {biddingDetail.offeredPaymentTerms ? - JSON.parse(biddingDetail.offeredPaymentTerms).join(', ') : - '정보 없음'} + {biddingDetail.paymentTermsResponse} </div> </div> <div> <Label className="text-sm font-medium">세금조건</Label> <div className="mt-1 p-3 bg-muted rounded-md"> - {biddingDetail.offeredTaxConditions ? - JSON.parse(biddingDetail.offeredTaxConditions).join(', ') : - '정보 없음'} + {biddingDetail.taxConditionsResponse} </div> </div> <div> <Label className="text-sm font-medium">운송조건</Label> <div className="mt-1 p-3 bg-muted rounded-md"> - {biddingDetail.offeredIncoterms ? - JSON.parse(biddingDetail.offeredIncoterms).join(', ') : - '정보 없음'} + {biddingDetail.incotermsResponse} </div> </div> - {biddingDetail.offeredContractDeliveryDate && ( - <div> - <Label className="text-sm font-medium">계약납기일</Label> - <div className="mt-1 p-3 bg-muted rounded-md"> - {formatDate(biddingDetail.offeredContractDeliveryDate, 'KR')} - </div> + <div> + <Label className="text-sm font-medium">제안 계약납기일</Label> + <div className="mt-1 p-3 bg-muted rounded-md"> + {biddingDetail.proposedContractDeliveryDate ? formatDate(biddingDetail.proposedContractDeliveryDate, 'KR') : '미설정'} + </div> + </div> + + <div> + <Label className="text-sm font-medium">제안 선적지</Label> + <div className="mt-1 p-3 bg-muted rounded-md"> + {biddingDetail.proposedShippingPort} + </div> + </div> + + <div> + <Label className="text-sm font-medium">제안 도착지</Label> + <div className="mt-1 p-3 bg-muted rounded-md"> + {biddingDetail.proposedDestinationPort} + </div> + </div> + + <div> + <Label className="text-sm font-medium">스페어파트 응답</Label> + <div className="mt-1 p-3 bg-muted rounded-md"> + {biddingDetail.sparePartResponse} + </div> + </div> + + <div> + <Label className="text-sm font-medium">연동제 적용</Label> + <div className="mt-1 p-3 bg-muted rounded-md"> + {biddingDetail.priceAdjustmentResponse ? '적용' : '미적용'} </div> - )} + </div> </div> </CardContent> </Card> @@ -490,6 +475,28 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD </div> </div> + <div className="grid grid-cols-1 md:grid-cols-2 gap-6"> + <div className="space-y-2"> + <Label htmlFor="proposedDestinationPort">제안 도착지</Label> + <Input + id="proposedDestinationPort" + value={responseData.proposedDestinationPort} + onChange={(e) => setResponseData({...responseData, proposedDestinationPort: e.target.value})} + placeholder="도착지를 입력하세요" + /> + </div> + + <div className="space-y-2"> + <Label htmlFor="sparePartResponse">스페어파트 응답</Label> + <Input + id="sparePartResponse" + value={responseData.sparePartResponse} + onChange={(e) => setResponseData({...responseData, sparePartResponse: e.target.value})} + placeholder="스페어파트 관련 응답을 입력하세요" + /> + </div> + </div> + <div className="space-y-2"> <Label htmlFor="additionalProposals">추가 제안사항</Label> <Textarea @@ -512,17 +519,6 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD <Label htmlFor="priceAdjustmentResponse">연동제 적용에 동의합니다</Label> </div> - <div className="flex items-center space-x-2"> - <Checkbox - id="isAttendingMeeting" - checked={responseData.isAttendingMeeting} - onCheckedChange={(checked) => - setResponseData({...responseData, isAttendingMeeting: !!checked}) - } - /> - <Label htmlFor="isAttendingMeeting">사양설명회에 참석합니다</Label> - </div> - <div className="flex justify-end pt-4"> <Button onClick={handleSubmitResponse} disabled={isPending}> <Send className="w-4 h-4 mr-2" /> @@ -531,32 +527,6 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD </div> </CardContent> </Card> - - {/* 사양설명회 참석 여부 다이얼로그 */} - <PartnersBiddingAttendanceDialog - biddingDetail={{ - id: biddingDetail.id, - biddingNumber: biddingDetail.biddingNumber, - title: biddingDetail.title, - preQuoteDate: biddingDetail.preQuoteDate, - biddingRegistrationDate: biddingDetail.biddingRegistrationDate, - evaluationDate: biddingDetail.evaluationDate, - }} - biddingCompanyId={biddingDetail.biddingCompanyId} - isAttending={biddingDetail.isAttendingMeeting} - open={isAttendanceDialogOpen} - onOpenChange={setIsAttendanceDialogOpen} - onSuccess={() => { - // 데이터 새로고침 - const refreshData = async () => { - const updatedDetail = await getBiddingDetailsForPartners(biddingId, companyId) - if (updatedDetail) { - setBiddingDetail(updatedDetail) - } - } - refreshData() - }} - /> </div> ) } |
