From ba8cd44a0ed2c613a5f2cee06bfc9bd0f61f21c7 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Fri, 7 Nov 2025 08:39:04 +0000
Subject: (최겸) 입찰/견적 수정사항
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/bidding/receive/biddings-receive-table.tsx | 211 +++++++++++++++++++++++++
 1 file changed, 211 insertions(+)
 create mode 100644 lib/bidding/receive/biddings-receive-table.tsx

(limited to 'lib/bidding/receive/biddings-receive-table.tsx')

diff --git a/lib/bidding/receive/biddings-receive-table.tsx b/lib/bidding/receive/biddings-receive-table.tsx
new file mode 100644
index 00000000..88fade40
--- /dev/null
+++ b/lib/bidding/receive/biddings-receive-table.tsx
@@ -0,0 +1,211 @@
+"use client"
+
+import * as React from "react"
+import { useRouter } from "next/navigation"
+import { useSession } from "next-auth/react"
+import type {
+    DataTableAdvancedFilterField,
+    DataTableFilterField,
+    DataTableRowAction,
+} from "@/types/table"
+
+import { useDataTable } from "@/hooks/use-data-table"
+import { DataTable } from "@/components/data-table/data-table"
+import { DataTableAdvancedToolbar } from "@/components/data-table/data-table-advanced-toolbar"
+import { getBiddingsReceiveColumns } from "./biddings-receive-columns"
+import { getBiddingsForReceive } from "@/lib/bidding/service"
+import {
+    biddingStatusLabels,
+    contractTypeLabels,
+} from "@/db/schema"
+import { SpecificationMeetingDialog, PrDocumentsDialog } from "../list/bidding-detail-dialogs"
+
+type BiddingReceiveItem = {
+  id: number
+  biddingNumber: string
+  originalBiddingNumber: string | null
+  title: string
+  status: string
+  contractType: string
+  prNumber: string | null
+  submissionStartDate: Date | null
+  submissionEndDate: Date | null
+  bidPicName: string | null
+  supplyPicName: string | null
+  createdBy: string | null
+  createdAt: Date | null
+  updatedAt: Date | null
+
+  // 참여 현황
+  participantExpected: number
+  participantParticipated: number
+  participantDeclined: number
+  participantPending: number
+
+  // 개찰 정보
+  openedAt: Date | null
+  openedBy: string | null
+}
+
+interface BiddingsReceiveTableProps {
+    promises: Promise<
+        [
+            Awaited<ReturnType<typeof getBiddingsForReceive>>
+        ]
+    >
+}
+
+export function BiddingsReceiveTable({ promises }: BiddingsReceiveTableProps) {
+    const [biddingsResult] = React.use(promises)
+
+    // biddingsResult에서 data와 pageCount 추출
+    const { data, pageCount } = biddingsResult
+
+    const [isCompact, setIsCompact] = React.useState<boolean>(false)
+    const [specMeetingDialogOpen, setSpecMeetingDialogOpen] = React.useState(false)
+    const [prDocumentsDialogOpen, setPrDocumentsDialogOpen] = React.useState(false)
+    const [selectedBidding, setSelectedBidding] = React.useState<BiddingReceiveItem | null>(null)
+
+    const [rowAction, setRowAction] = React.useState<DataTableRowAction<BiddingReceiveItem> | null>(null)
+
+    const router = useRouter()
+    const { data: session } = useSession()
+
+    const columns = React.useMemo(
+        () => getBiddingsReceiveColumns({ setRowAction }),
+        [setRowAction]
+    )
+
+    // rowAction 변경 감지하여 해당 다이얼로그 열기
+    React.useEffect(() => {
+        if (rowAction) {
+            setSelectedBidding(rowAction.row.original)
+
+            switch (rowAction.type) {
+                case "view":
+                    // 상세 페이지로 이동
+                    router.push(`/evcp/bid/${rowAction.row.original.id}`)
+                    break
+                case "open_bidding":
+                    // 개찰하기 (추후 구현)
+                    console.log('개찰하기:', rowAction.row.original)
+                    break
+                default:
+                    break
+            }
+        }
+    }, [rowAction])
+
+    const filterFields: DataTableFilterField<BiddingReceiveItem>[] = [
+        {
+            id: "biddingNumber",
+            label: "입찰번호",
+            type: "text",
+            placeholder: "입찰번호를 입력하세요",
+        },
+        {
+            id: "prNumber",
+            label: "P/R번호",
+            type: "text",
+            placeholder: "P/R번호를 입력하세요",
+        },
+        {
+            id: "title",
+            label: "입찰명",
+            type: "text",
+            placeholder: "입찰명을 입력하세요",
+        },
+    ]
+
+    const advancedFilterFields: DataTableAdvancedFilterField<BiddingReceiveItem>[] = [
+        { id: "title", label: "입찰명", type: "text" },
+        { id: "biddingNumber", label: "입찰번호", type: "text" },
+        { id: "bidPicName", label: "입찰담당자", type: "text" },
+        {
+            id: "status",
+            label: "진행상태",
+            type: "multi-select",
+            options: Object.entries(biddingStatusLabels).map(([value, label]) => ({
+                label,
+                value,
+            })),
+        },
+        {
+            id: "contractType",
+            label: "계약구분",
+            type: "select",
+            options: Object.entries(contractTypeLabels).map(([value, label]) => ({
+                label,
+                value,
+            })),
+        },
+        { id: "createdAt", label: "등록일", type: "date" },
+        { id: "submissionStartDate", label: "제출시작일", type: "date" },
+        { id: "submissionEndDate", label: "제출마감일", type: "date" },
+    ]
+
+    const { table } = useDataTable({
+        data,
+        columns,
+        pageCount,
+        filterFields,
+        enablePinning: true,
+        enableAdvancedFilter: true,
+        initialState: {
+            sorting: [{ id: "createdAt", desc: true }],
+            columnPinning: { right: ["actions"] },
+        },
+        getRowId: (originalRow) => String(originalRow.id),
+        shallow: false,
+        clearOnDefault: true,
+    })
+
+    const handleCompactChange = React.useCallback((compact: boolean) => {
+        setIsCompact(compact)
+    }, [])
+
+    const handleSpecMeetingDialogClose = React.useCallback(() => {
+        setSpecMeetingDialogOpen(false)
+        setRowAction(null)
+        setSelectedBidding(null)
+    }, [])
+
+    const handlePrDocumentsDialogClose = React.useCallback(() => {
+        setPrDocumentsDialogOpen(false)
+        setRowAction(null)
+        setSelectedBidding(null)
+    }, [])
+
+    return (
+        <>
+            <DataTable
+                table={table}
+                compact={isCompact}
+            >
+                <DataTableAdvancedToolbar
+                    table={table}
+                    filterFields={advancedFilterFields}
+                    shallow={false}
+                    enableCompactToggle={true}
+                    compactStorageKey="biddingsReceiveTableCompact"
+                    onCompactChange={handleCompactChange}
+                >
+                </DataTableAdvancedToolbar>
+            </DataTable>
+
+            {/* 사양설명회 다이얼로그 */}
+            <SpecificationMeetingDialog
+                open={specMeetingDialogOpen}
+                onOpenChange={handleSpecMeetingDialogClose}
+                bidding={selectedBidding}
+            />
+
+            {/* PR 문서 다이얼로그 */}
+            <PrDocumentsDialog
+                open={prDocumentsDialogOpen}
+                onOpenChange={handlePrDocumentsDialogClose}
+                bidding={selectedBidding}
+            />
+        </>
+    )
+}
-- 
cgit v1.2.3

