From d1f1768611a73541f5d63b6735f64d194466825b Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Thu, 4 Dec 2025 12:42:23 +0000
Subject: (최겸) 구매 입찰 견적 히스토리, 응찰품목조회 table 개발
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/bidding/selection/bidding-item-table.tsx | 71 ++++++++++++++++------------
 1 file changed, 42 insertions(+), 29 deletions(-)

(limited to 'lib/bidding/selection/bidding-item-table.tsx')

diff --git a/lib/bidding/selection/bidding-item-table.tsx b/lib/bidding/selection/bidding-item-table.tsx
index c101f7e7..aa2b34ec 100644
--- a/lib/bidding/selection/bidding-item-table.tsx
+++ b/lib/bidding/selection/bidding-item-table.tsx
@@ -2,10 +2,7 @@
 
 import * as React from 'react'
 import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
-import { 
-  getPRItemsForBidding, 
-  getVendorPricesForBidding 
-} from '@/lib/bidding/detail/service'
+import { getBiddingSelectionItemsAndPrices } from '@/lib/bidding/service'
 import { formatNumber } from '@/lib/utils'
 import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area'
 
@@ -21,26 +18,55 @@ export function BiddingItemTable({ biddingId }: BiddingItemTableProps) {
   const [loading, setLoading] = React.useState(true)
 
   React.useEffect(() => {
+    let isMounted = true
+
     const loadData = async () => {
       try {
         setLoading(true)
-        const [prItems, vendorPrices] = await Promise.all([
-          getPRItemsForBidding(biddingId),
-          getVendorPricesForBidding(biddingId)
-        ])
-        console.log('prItems', prItems)
-        console.log('vendorPrices', vendorPrices)
-        setData({ prItems, vendorPrices })
+        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 {
-        setLoading(false)
+        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 (
       <Card>
@@ -58,19 +84,6 @@ export function BiddingItemTable({ biddingId }: BiddingItemTableProps) {
 
   const { prItems, vendorPrices } = data
 
-  // Calculate Totals
-  const totalQuantity = prItems.reduce((sum, item) => sum + Number(item.quantity || 0), 0)
-  const totalWeight = prItems.reduce((sum, item) => sum + Number(item.totalWeight || 0), 0)
-  const totalTargetAmount = prItems.reduce((sum, item) => sum + Number(item.targetAmount || 0), 0)
-
-  // Calculate Vendor Totals
-  const vendorTotals = vendorPrices.map(vendor => {
-    const total = vendor.itemPrices.reduce((sum: number, item: any) => sum + Number(item.amount || 0), 0)
-    return {
-      companyId: vendor.companyId,
-      totalAmount: total
-    }
-  })
 
   return (
     <Card>
@@ -118,17 +131,17 @@ export function BiddingItemTable({ biddingId }: BiddingItemTableProps) {
                 {/* Summary Row */}
                 <tr className="border-b transition-colors hover:bg-muted/50 bg-muted/30 font-semibold">
                   <td className="p-4 align-middle text-center border-r" colSpan={4}>합계</td>
-                  <td className="p-4 align-middle text-right border-r">{formatNumber(totalQuantity)}</td>
+                  <td className="p-4 align-middle text-right border-r">{formatNumber(totals.quantity)}</td>
                   <td className="p-4 align-middle text-center border-r">-</td>
-                  <td className="p-4 align-middle text-right border-r">{formatNumber(totalWeight)}</td>
+                  <td className="p-4 align-middle text-right border-r">{formatNumber(totals.weight)}</td>
                   <td className="p-4 align-middle text-center border-r">-</td>
                   <td className="p-4 align-middle text-center border-r">-</td>
-                  <td className="p-4 align-middle text-right border-r">{formatNumber(totalTargetAmount)}</td>
+                  <td className="p-4 align-middle text-right border-r">{formatNumber(totals.targetAmount)}</td>
                   <td className="p-4 align-middle text-center border-r">KRW</td>
                   
                   {vendorPrices.map((vendor) => {
                      const vTotal = vendorTotals.find(t => t.companyId === vendor.companyId)?.totalAmount || 0
-                     const ratio = totalTargetAmount > 0 ? (vTotal / totalTargetAmount) * 100 : 0
+                     const ratio = totals.targetAmount > 0 ? (vTotal / totals.targetAmount) * 100 : 0
                      return (
                       <React.Fragment key={vendor.companyId}>
                         <td className="p-4 align-middle text-center border-r">-</td>
-- 
cgit v1.2.3

