diff options
Diffstat (limited to 'lib/bidding/vendor/partners-bidding-pre-quote.tsx')
| -rw-r--r-- | lib/bidding/vendor/partners-bidding-pre-quote.tsx | 178 |
1 files changed, 149 insertions, 29 deletions
diff --git a/lib/bidding/vendor/partners-bidding-pre-quote.tsx b/lib/bidding/vendor/partners-bidding-pre-quote.tsx index 4ec65413..6a76ffa1 100644 --- a/lib/bidding/vendor/partners-bidding-pre-quote.tsx +++ b/lib/bidding/vendor/partners-bidding-pre-quote.tsx @@ -10,12 +10,18 @@ import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { Checkbox } from '@/components/ui/checkbox' import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select' +import { ArrowLeft, Calendar, Building2, Package, User, - DollarSign, FileText, Users, Send, @@ -35,12 +41,11 @@ import { } from '../pre-quote/service' import { getBiddingConditions } from '../service' import { getPriceAdjustmentFormByBiddingCompanyId } from '../detail/service' +import { getIncotermsForSelection, getPaymentTermsForSelection, getPlaceOfShippingForSelection, getPlaceOfDestinationForSelection } from '@/lib/procurement-select/service' import { PrItemsPricingTable } from './components/pr-items-pricing-table' import { SimpleFileUpload } from './components/simple-file-upload' import { biddingStatusLabels, - contractTypeLabels, - biddingTypeLabels } from '@/db/schema' import { useToast } from '@/hooks/use-toast' import { useTransition } from 'react' @@ -63,7 +68,8 @@ interface BiddingDetail { contractType: string biddingType: string awardCount: string - contractPeriod: string | null + contractStartDate: Date | null + contractEndDate: Date | null preQuoteDate: string | null biddingRegistrationDate: string | null submissionStartDate: string | null @@ -105,6 +111,12 @@ export function PartnersBiddingPreQuote({ biddingId, companyId }: PartnersBiddin const [biddingDetail, setBiddingDetail] = React.useState<BiddingDetail | null>(null) const [isLoading, setIsLoading] = React.useState(true) const [biddingConditions, setBiddingConditions] = React.useState<any | null>(null) + + // Procurement 데이터 상태들 + const [paymentTermsOptions, setPaymentTermsOptions] = React.useState<Array<{code: string, description: string}>>([]) + const [incotermsOptions, setIncotermsOptions] = React.useState<Array<{code: string, description: string}>>([]) + const [shippingPlaces, setShippingPlaces] = React.useState<Array<{code: string, description: string}>>([]) + const [destinationPlaces, setDestinationPlaces] = React.useState<Array<{code: string, description: string}>>([]) // 품목별 견적 관련 상태 const [prItems, setPrItems] = React.useState<any[]>([]) @@ -151,6 +163,43 @@ export function PartnersBiddingPreQuote({ biddingId, companyId }: PartnersBiddin }) const userId = session.data?.user?.id || '' + // Procurement 데이터 로드 함수들 + const loadPaymentTerms = React.useCallback(async () => { + try { + const data = await getPaymentTermsForSelection(); + setPaymentTermsOptions(data); + } catch (error) { + console.error("Failed to load payment terms:", error); + } + }, []); + + const loadIncoterms = React.useCallback(async () => { + try { + const data = await getIncotermsForSelection(); + setIncotermsOptions(data); + } catch (error) { + console.error("Failed to load incoterms:", error); + } + }, []); + + const loadShippingPlaces = React.useCallback(async () => { + try { + const data = await getPlaceOfShippingForSelection(); + setShippingPlaces(data); + } catch (error) { + console.error("Failed to load shipping places:", error); + } + }, []); + + const loadDestinationPlaces = React.useCallback(async () => { + try { + const data = await getPlaceOfDestinationForSelection(); + setDestinationPlaces(data); + } catch (error) { + console.error("Failed to load destination places:", error); + } + }, []); + // 데이터 로드 React.useEffect(() => { const loadData = async () => { @@ -229,6 +278,14 @@ export function PartnersBiddingPreQuote({ biddingId, companyId }: PartnersBiddin if (prItemsData) { setPrItems(prItemsData) } + + // Procurement 데이터 로드 + await Promise.all([ + loadPaymentTerms(), + loadIncoterms(), + loadShippingPlaces(), + loadDestinationPlaces() + ]) } catch (error) { console.error('Failed to load bidding company:', error) toast({ @@ -242,7 +299,7 @@ export function PartnersBiddingPreQuote({ biddingId, companyId }: PartnersBiddin } loadData() - }, [biddingId, companyId, toast]) + }, [biddingId, companyId, toast, loadPaymentTerms, loadIncoterms, loadShippingPlaces, loadDestinationPlaces]) // 임시저장 기능 const handleTempSave = () => { @@ -428,7 +485,7 @@ export function PartnersBiddingPreQuote({ biddingId, companyId }: PartnersBiddin { value: responseData.taxConditionsResponse, name: '응답 세금조건' }, { value: responseData.incotermsResponse, name: '응답 운송조건' }, { value: responseData.proposedShippingPort, name: '제안 선적지' }, - { value: responseData.proposedDestinationPort, name: '제안 도착지' }, + { value: responseData.proposedDestinationPort, name: '제안 하역지' }, { value: responseData.sparePartResponse, name: '스페어파트 응답' }, ] @@ -775,7 +832,7 @@ export function PartnersBiddingPreQuote({ biddingId, companyId }: PartnersBiddin </div> <div> - <Label className="text-muted-foreground">도착지</Label> + <Label className="text-muted-foreground">하역지</Label> <div className="mt-1 p-3 bg-muted rounded-md"> <p className="font-medium">{biddingConditions.destinationPort || "미설정"}</p> </div> @@ -849,12 +906,13 @@ export function PartnersBiddingPreQuote({ biddingId, companyId }: PartnersBiddin </span> </div> {participationDecision === false && ( + <> <div className="p-4 bg-muted rounded-lg"> <p className="text-muted-foreground"> 미참여로 설정되어 견적 작성 섹션이 숨겨집니다. 참여하시려면 아래 버튼을 클릭해주세요. </p> </div> - )} + <Button variant="outline" size="sm" @@ -863,6 +921,8 @@ export function PartnersBiddingPreQuote({ biddingId, companyId }: PartnersBiddin > 결정 변경하기 </Button> + </> + )} </div> )} </CardContent> @@ -961,12 +1021,27 @@ export function PartnersBiddingPreQuote({ biddingId, companyId }: PartnersBiddin <div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="space-y-2"> <Label htmlFor="paymentTermsResponse">응답 지급조건 <span className="text-red-500">*</span></Label> - <Input - id="paymentTermsResponse" + <Select value={responseData.paymentTermsResponse} - onChange={(e) => setResponseData({...responseData, paymentTermsResponse: e.target.value})} - placeholder={biddingConditions?.paymentTerms ? `참고: ${biddingConditions.paymentTerms}` : "지급조건에 대한 의견을 입력하세요"} - /> + onValueChange={(value) => setResponseData({...responseData, paymentTermsResponse: value})} + > + <SelectTrigger> + <SelectValue placeholder={biddingConditions?.paymentTerms ? `참고: ${biddingConditions.paymentTerms}` : "지급조건 선택"} /> + </SelectTrigger> + <SelectContent> + {paymentTermsOptions.length > 0 ? ( + paymentTermsOptions.map((option) => ( + <SelectItem key={option.code} value={option.code}> + {option.code} {option.description && `(${option.description})`} + </SelectItem> + )) + ) : ( + <SelectItem value="loading" disabled> + 데이터를 불러오는 중... + </SelectItem> + )} + </SelectContent> + </Select> </div> <div className="space-y-2"> @@ -983,34 +1058,79 @@ export function PartnersBiddingPreQuote({ biddingId, companyId }: PartnersBiddin <div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="space-y-2"> <Label htmlFor="incotermsResponse">응답 운송조건 <span className="text-red-500">*</span></Label> - <Input - id="incotermsResponse" + <Select value={responseData.incotermsResponse} - onChange={(e) => setResponseData({...responseData, incotermsResponse: e.target.value})} - placeholder={biddingConditions?.incoterms ? `참고: ${biddingConditions.incoterms}` : "운송조건에 대한 의견을 입력하세요"} - /> + onValueChange={(value) => setResponseData({...responseData, incotermsResponse: value})} + > + <SelectTrigger> + <SelectValue placeholder={biddingConditions?.incoterms ? `참고: ${biddingConditions.incoterms}` : "운송조건 선택"} /> + </SelectTrigger> + <SelectContent> + {incotermsOptions.length > 0 ? ( + incotermsOptions.map((option) => ( + <SelectItem key={option.code} value={option.code}> + {option.code} {option.description && `(${option.description})`} + </SelectItem> + )) + ) : ( + <SelectItem value="loading" disabled> + 데이터를 불러오는 중... + </SelectItem> + )} + </SelectContent> + </Select> </div> <div className="space-y-2"> <Label htmlFor="proposedShippingPort">제안 선적지 <span className="text-red-500">*</span></Label> - <Input - id="proposedShippingPort" + <Select value={responseData.proposedShippingPort} - onChange={(e) => setResponseData({...responseData, proposedShippingPort: e.target.value})} - placeholder={biddingConditions?.shippingPort ? `참고: ${biddingConditions.shippingPort}` : "선적지를 입력하세요"} - /> + onValueChange={(value) => setResponseData({...responseData, proposedShippingPort: value})} + > + <SelectTrigger> + <SelectValue placeholder={biddingConditions?.shippingPort ? `참고: ${biddingConditions.shippingPort}` : "선적지 선택"} /> + </SelectTrigger> + <SelectContent> + {shippingPlaces.length > 0 ? ( + shippingPlaces.map((place) => ( + <SelectItem key={place.code} value={place.code}> + {place.code} {place.description && `(${place.description})`} + </SelectItem> + )) + ) : ( + <SelectItem value="loading" disabled> + 데이터를 불러오는 중... + </SelectItem> + )} + </SelectContent> + </Select> </div> </div> <div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="space-y-2"> - <Label htmlFor="proposedDestinationPort">제안 도착지 <span className="text-red-500">*</span></Label> - <Input - id="proposedDestinationPort" + <Label htmlFor="proposedDestinationPort">제안 하역지 <span className="text-red-500">*</span></Label> + <Select value={responseData.proposedDestinationPort} - onChange={(e) => setResponseData({...responseData, proposedDestinationPort: e.target.value})} - placeholder={biddingConditions?.destinationPort ? `참고: ${biddingConditions.destinationPort}` : "도착지를 입력하세요"} - /> + onValueChange={(value) => setResponseData({...responseData, proposedDestinationPort: value})} + > + <SelectTrigger> + <SelectValue placeholder={biddingConditions?.destinationPort ? `참고: ${biddingConditions.destinationPort}` : "하역지 선택"} /> + </SelectTrigger> + <SelectContent> + {destinationPlaces.length > 0 ? ( + destinationPlaces.map((place) => ( + <SelectItem key={place.code} value={place.code}> + {place.code} {place.description && `(${place.description})`} + </SelectItem> + )) + ) : ( + <SelectItem value="loading" disabled> + 데이터를 불러오는 중... + </SelectItem> + )} + </SelectContent> + </Select> </div> <div className="space-y-2"> |
