summaryrefslogtreecommitdiff
path: root/lib/techsales-rfq/vendor-response/table/vendor-quotations-table.tsx
diff options
context:
space:
mode:
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.tsx143
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