diff options
Diffstat (limited to 'lib/techsales-rfq/vendor-response/table/vendor-quotations-table.tsx')
| -rw-r--r-- | lib/techsales-rfq/vendor-response/table/vendor-quotations-table.tsx | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/lib/techsales-rfq/vendor-response/table/vendor-quotations-table.tsx b/lib/techsales-rfq/vendor-response/table/vendor-quotations-table.tsx new file mode 100644 index 00000000..63d4674b --- /dev/null +++ b/lib/techsales-rfq/vendor-response/table/vendor-quotations-table.tsx @@ -0,0 +1,143 @@ +// lib/techsales-rfq/vendor-response/table/vendor-quotations-table.tsx +"use client" + +import * as React from "react" +import { type DataTableAdvancedFilterField, type DataTableFilterField } 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 { TechSalesVendorQuotations, TECH_SALES_QUOTATION_STATUSES, TECH_SALES_QUOTATION_STATUS_CONFIG } from "@/db/schema" +import { useRouter } from "next/navigation" +import { getColumns } from "./vendor-quotations-table-columns" + +interface QuotationWithRfqCode extends TechSalesVendorQuotations { + rfqCode?: string; + materialCode?: string; + dueDate?: Date; + rfqStatus?: string; + itemName?: string; + projNm?: string; + quotationCode?: string | null; + quotationVersion?: number | null; + rejectionReason?: string | null; + acceptedAt?: Date | null; +} + +interface VendorQuotationsTableProps { + promises: Promise<[{ data: any[], pageCount: number, total?: number }]>; +} + +export function VendorQuotationsTable({ promises }: VendorQuotationsTableProps) { + + // TODO: 안정화 이후 삭제 + console.log("렌더링 사이클 점검용 로그: VendorQuotationsTable 렌더링됨"); + + const [{ data, pageCount }] = React.use(promises); + const router = useRouter(); + + // 데이터 안정성을 위한 메모이제이션 - 핵심 속성만 비교 + const stableData = React.useMemo(() => { + return data; + }, [data.length, data.map(item => `${item.id}-${item.status}-${item.updatedAt}`).join(',')]); + + // 테이블 컬럼 정의 - router는 안정적이므로 한 번만 생성 + const columns = React.useMemo(() => getColumns({ + router, + }), [router]); + + // 필터 필드 - 중앙화된 상태 상수 사용 + const filterFields = React.useMemo<DataTableFilterField<QuotationWithRfqCode>[]>(() => [ + { + id: "status", + label: "상태", + options: Object.entries(TECH_SALES_QUOTATION_STATUSES).map(([, statusValue]) => ({ + label: TECH_SALES_QUOTATION_STATUS_CONFIG[statusValue].label, + value: statusValue, + })) + }, + { + id: "rfqCode", + label: "RFQ 번호", + placeholder: "RFQ 번호 검색...", + }, + { + id: "materialCode", + label: "자재 코드", + placeholder: "자재 코드 검색...", + } + ], []); + + // 고급 필터 필드 - 중앙화된 상태 상수 사용 + const advancedFilterFields = React.useMemo<DataTableAdvancedFilterField<QuotationWithRfqCode>[]>(() => [ + { + id: "rfqCode", + label: "RFQ 번호", + type: "text", + }, + { + id: "materialCode", + label: "자재 코드", + type: "text", + }, + { + id: "status", + label: "상태", + type: "multi-select", + options: Object.entries(TECH_SALES_QUOTATION_STATUSES).map(([, statusValue]) => ({ + label: TECH_SALES_QUOTATION_STATUS_CONFIG[statusValue].label, + value: statusValue, + })), + }, + { + id: "validUntil", + label: "유효기간", + type: "date", + }, + { + id: "submittedAt", + label: "제출일", + type: "date", + }, + ], []); + + // useDataTable 훅 사용 + const { table } = useDataTable({ + data: stableData, + columns, + pageCount, + filterFields, + enablePinning: true, + enableAdvancedFilter: true, + enableColumnResizing: true, + columnResizeMode: 'onChange', + initialState: { + sorting: [{ id: "updatedAt", desc: true }], + columnPinning: { right: ["actions"] }, + }, + getRowId: (originalRow) => String(originalRow.id), + shallow: false, + clearOnDefault: true, + defaultColumn: { + minSize: 50, + maxSize: 500, + }, + }); + + return ( + <div className="w-full"> + <div className="overflow-x-auto"> + <DataTable + table={table} + className="min-w-full" + > + <DataTableAdvancedToolbar + table={table} + filterFields={advancedFilterFields} + shallow={false} + > + </DataTableAdvancedToolbar> + </DataTable> + </div> + </div> + ); +}
\ No newline at end of file |
