"use client" import * as React from "react" import { type ColumnDef } from "@tanstack/react-table" import { Checkbox } from "@/components/ui/checkbox" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { MoreHorizontal } from "lucide-react" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { QuotationVendor } from "@/lib/bidding/detail/service" interface GetVendorColumnsProps { onViewPriceAdjustment?: (vendor: QuotationVendor) => void onViewItemDetails?: (vendor: QuotationVendor) => void onSendBidding?: (vendor: QuotationVendor) => void onUpdateParticipation?: (vendor: QuotationVendor, participated: boolean) => void onViewQuotationHistory?: (vendor: QuotationVendor) => void biddingStatus?: string // 입찰 상태 정보 추가 biddingTargetPrice?: number | string | null // 입찰 내정가 biddingFinalBidPrice?: number | string | null // 최종 확정금액 biddingCurrency?: string // 입찰 통화 } export function getBiddingDetailVendorColumns({ onViewItemDetails, onSendBidding, onUpdateParticipation, onViewQuotationHistory, biddingStatus, biddingTargetPrice, biddingFinalBidPrice, biddingCurrency }: GetVendorColumnsProps): ColumnDef[] { return [ { id: 'select', header: ({ table }) => ( table.toggleAllPageRowsSelected(!!value)} aria-label="모두 선택" /> ), cell: ({ row }) => ( row.toggleSelected(!!value)} aria-label="행 선택" /> ), enableSorting: false, enableHiding: false, }, { accessorKey: 'vendorName', header: '업체명', cell: ({ row }) => (
{row.original.vendorName}
), }, { accessorKey: 'vendorCode', header: '업체코드', cell: ({ row }) => (
{row.original.vendorCode}
), }, { accessorKey: 'quotationAmount', header: '입찰금액', cell: ({ row }) => { const hasAmount = row.original.quotationAmount && Number(row.original.quotationAmount) > 0 return (
{hasAmount ? ( <> ) : ( - {row.original.currency} )}
) }, }, { accessorKey: 'targetPrice', header: '내정가', cell: ({ row }) => { const hasTargetPrice = biddingTargetPrice && Number(biddingTargetPrice) > 0 return (
{hasTargetPrice ? ( <> {Number(biddingTargetPrice).toLocaleString()} {row.original.currency} ) : ( - )}
) }, }, { accessorKey: 'priceRatio', header: '내정가 대비', cell: ({ row }) => { const hasAmount = row.original.quotationAmount && Number(row.original.quotationAmount) > 0 const hasTargetPrice = biddingTargetPrice && Number(biddingTargetPrice) > 0 if (!hasAmount || !hasTargetPrice) { return
-
} const quotationAmount = Number(row.original.quotationAmount) const targetPrice = Number(biddingTargetPrice) const ratio = (quotationAmount / targetPrice) * 100 // 비율에 따른 색상 결정 const getColorClass = (ratio: number) => { if (ratio < 100) return 'text-blue-600 font-bold' // 내정가보다 낮음 if (ratio === 100) return 'text-green-600 font-bold' // 내정가와 같음 if (ratio <= 110) return 'text-orange-600 font-bold' // 10% 이내 초과 return 'text-red-600 font-bold' // 10% 이상 초과 } return (
{ratio.toFixed(1)}%
) }, }, { accessorKey: 'biddingResult', header: '입찰결과', cell: ({ row }) => { const isWinner = row.original.isWinner if (isWinner === null || isWinner === undefined) { return
미정
} return ( {isWinner ? '낙찰' : '탈락'} ) }, }, { accessorKey: 'awardRatio', header: '발주비율', cell: ({ row }) => (
{row.original.awardRatio !== null ? `${row.original.awardRatio}%` : '-'}
), }, { accessorKey: 'finalBidPrice', header: '확정금액', cell: ({ row }) => { const hasFinalPrice = biddingFinalBidPrice && Number(biddingFinalBidPrice) > 0 const currency = biddingCurrency || row.original.currency return (
{hasFinalPrice ? ( <> {Number(biddingFinalBidPrice).toLocaleString()} {currency} ) : ( - )}
) }, }, { accessorKey: 'isBiddingParticipated', header: '입찰참여', cell: ({ row }) => { const participated = row.original.isBiddingParticipated if (participated === null) { return 대기 } return ( {participated ? '응찰' : '응찰포기'} ) }, }, { accessorKey: 'invitationStatus', header: '상태', cell: ({ row }) => { const invitationStatus = row.original.invitationStatus const variant = invitationStatus === 'bidding_submitted' ? 'default' : invitationStatus === 'pre_quote_submitted' ? 'secondary' : invitationStatus === 'bidding_declined' ? 'destructive' : 'outline' const label = invitationStatus === 'bidding_submitted' ? '응찰 완료' : invitationStatus === 'pre_quote_submitted' ? '사전견적 제출' : invitationStatus === 'bidding_declined' ? '응찰 거절' : invitationStatus === 'pre_quote_declined' ? '사전견적 거절' : invitationStatus === 'bidding_accepted' ? '응찰 참여' : invitationStatus === 'pre_quote_accepted' ? '사전견적 참여' : invitationStatus === 'pending' ? '대기' : invitationStatus === 'pre_quote_sent' ? '사전견적 초대' : invitationStatus === 'bidding_sent' ? '응찰 초대' : invitationStatus || '알 수 없음' return {label} }, }, { accessorKey: 'submissionDate', header: '제출일', cell: ({ row }) => (
{row.original.submissionDate ? new Date(row.original.submissionDate).toLocaleDateString('ko-KR') : '-'}
), }, { id: 'actions', header: '작업', cell: ({ row }) => { const vendor = row.original return ( 작업 {/* 입찰 히스토리 (응찰한 업체만) */} {vendor.isBiddingParticipated === true && onViewQuotationHistory && ( <> onViewQuotationHistory(vendor)}> 입찰 히스토리 )} ) }, }, ] }