'use client' import * as React from 'react' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { getBiddingSelectionItemsAndPrices } from '@/lib/bidding/service' import { formatNumber } from '@/lib/utils' import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area' interface BiddingItemTableProps { biddingId: number } export function BiddingItemTable({ biddingId }: BiddingItemTableProps) { const [data, setData] = React.useState<{ prItems: any[] vendorPrices: any[] }>({ prItems: [], vendorPrices: [] }) const [loading, setLoading] = React.useState(true) React.useEffect(() => { let isMounted = true const loadData = async () => { try { setLoading(true) const { prItems, vendorPrices } = await getBiddingSelectionItemsAndPrices(biddingId) if (isMounted) { console.log('prItems', prItems) console.log('vendorPrices', vendorPrices) setData({ prItems, vendorPrices }) } } catch (error) { console.error('Failed to load bidding items:', error) } finally { if (isMounted) { setLoading(false) } } } loadData() return () => { isMounted = false } }, [biddingId]) // Memoize calculations const totals = React.useMemo(() => { const { prItems } = data return { quantity: prItems.reduce((sum, item) => sum + Number(item.quantity || 0), 0), weight: prItems.reduce((sum, item) => sum + Number(item.totalWeight || 0), 0), targetAmount: prItems.reduce((sum, item) => sum + Number(item.targetAmount || 0), 0) } }, [data.prItems]) const vendorTotals = React.useMemo(() => { const { vendorPrices } = data return vendorPrices.map(vendor => { const total = vendor.itemPrices.reduce((sum: number, item: any) => sum + Number(item.amount || 0), 0) return { companyId: vendor.companyId, totalAmount: total } }) }, [data.vendorPrices]) if (loading) { return ( 응찰품목
로딩 중...
) } const { prItems, vendorPrices } = data return ( 응찰품목
{/* Header Row 1: Base Info + Vendor Groups */} {vendorPrices.map((vendor) => ( ))} {/* Header Row 2: Vendor Sub-columns */} {vendorPrices.map((vendor) => ( ))} {/* Summary Row */} {vendorPrices.map((vendor) => { const vTotal = vendorTotals.find(t => t.companyId === vendor.companyId)?.totalAmount || 0 const ratio = totals.targetAmount > 0 ? (vTotal / totals.targetAmount) * 100 : 0 return ( ) })} {/* Data Rows */} {prItems.map((item) => ( {vendorPrices.map((vendor) => { const bidItem = vendor.itemPrices.find((p: any) => p.prItemId === item.id) const bidAmount = bidItem ? bidItem.amount : 0 const targetAmt = Number(item.targetAmount || 0) const ratio = targetAmt > 0 && bidAmount > 0 ? (bidAmount / targetAmt) * 100 : 0 return ( ) })} ))}
자재번호 자재내역 자재내역상세 구매단위 수량 단위 총중량 중량단위 내정단가 내정액 통화 {vendor.companyName}
단가 총액 통화 내정액(%)
합계 {formatNumber(totals.quantity)} - {formatNumber(totals.weight)} - - {formatNumber(totals.targetAmount)} KRW- {formatNumber(vTotal)} {vendor.currency} {formatNumber(ratio, 0)}%
{item.materialNumber} {item.materialInfo} {item.specification} {item.purchaseUnit} {formatNumber(item.quantity)} {item.quantityUnit} {formatNumber(item.totalWeight)} {item.weightUnit} {formatNumber(item.targetUnitPrice)} {formatNumber(item.targetAmount)} {item.currency} {bidItem ? formatNumber(bidItem.unitPrice) : '-'} {bidItem ? formatNumber(bidItem.amount) : '-'} {vendor.currency} {bidItem && ratio > 0 ? `${formatNumber(ratio, 0)}%` : '-'}
) }