summaryrefslogtreecommitdiff
path: root/lib/compliance/responses/compliance-responses-table.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compliance/responses/compliance-responses-table.tsx')
-rw-r--r--lib/compliance/responses/compliance-responses-table.tsx141
1 files changed, 141 insertions, 0 deletions
diff --git a/lib/compliance/responses/compliance-responses-table.tsx b/lib/compliance/responses/compliance-responses-table.tsx
new file mode 100644
index 00000000..e4292719
--- /dev/null
+++ b/lib/compliance/responses/compliance-responses-table.tsx
@@ -0,0 +1,141 @@
+"use client";
+
+import * as React from "react";
+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 type {
+ DataTableAdvancedFilterField,
+ DataTableRowAction,
+ DataTableFilterField,
+} from "@/types/table"
+import { getComplianceResponsesWithPagination } from "../services";
+import { getResponseColumns } from "./compliance-responses-columns";
+import { ComplianceResponsesToolbarActions } from "./compliance-responses-toolbar";
+
+interface ComplianceResponsesTableProps {
+ templateId: number;
+ promises?: Promise<[{ data: any[]; pageCount: number }]>;
+}
+
+export function ComplianceResponsesTable({ templateId, promises }: ComplianceResponsesTableProps) {
+ // 페이지네이션 모드 데이터
+ const paginationData = promises ? React.use(promises) : null;
+ const [{ data: initialData = [], pageCount = 0 }] = paginationData || [{ data: [], pageCount: 0 }];
+
+ const [rowAction, setRowAction] = React.useState<DataTableRowAction<any> | null>(null);
+ const [data, setData] = React.useState(initialData);
+ const [currentSorting, setCurrentSorting] = React.useState<{ id: string; desc: boolean }[]>([]);
+
+ // 초기 데이터가 변경되면 data 상태 업데이트
+ React.useEffect(() => {
+ setData(initialData);
+ }, [initialData]);
+
+ // 컬럼 설정 - 외부 파일에서 가져옴
+ const columns = React.useMemo(
+ () => getResponseColumns({ setRowAction }),
+ [setRowAction]
+ )
+
+ // 기본 필터 필드 설정
+ const filterFields: DataTableFilterField<any>[] = [
+ {
+ id: "status",
+ label: "상태",
+ options: [
+ { label: "진행중", value: "IN_PROGRESS" },
+ { label: "완료", value: "COMPLETED" },
+ { label: "검토완료", value: "REVIEWED" },
+ ],
+ },
+ ];
+
+ // 고급 필터 필드 설정
+ const advancedFilterFields: DataTableAdvancedFilterField<any>[] = [
+ { id: "vendorId", label: "Vendor ID", type: "text" },
+ { id: "vendorName", label: "업체명", type: "text" },
+ { id: "contractName", label: "계약서명", type: "text" },
+ {
+ id: "status", label: "상태", type: "select", options: [
+ { label: "진행중", value: "IN_PROGRESS" },
+ { label: "완료", value: "COMPLETED" },
+ { label: "검토완료", value: "REVIEWED" },
+ ]
+ },
+ { id: "answersCount", label: "답변 수", type: "text" },
+ { id: "createdAt", label: "생성일", type: "date" },
+ { id: "completedAt", label: "완료일", type: "date" },
+ ];
+
+ const { table } = useDataTable({
+ data,
+ columns,
+ pageCount,
+ filterFields,
+ enablePinning: true,
+ enableAdvancedFilter: true,
+ enableRowSelection: true,
+ initialState: {
+ sorting: [{ id: "createdAt", desc: true }],
+ columnPinning: { right: ["actions"] },
+ },
+ getRowId: (originalRow) => String(originalRow.id),
+ shallow: false,
+ clearOnDefault: true,
+ })
+
+ // 정렬 상태 변경 감지
+ React.useEffect(() => {
+ const newSorting = table.getState().sorting;
+ if (JSON.stringify(newSorting) !== JSON.stringify(currentSorting)) {
+ setCurrentSorting(newSorting);
+ }
+ }, [table.getState().sorting, currentSorting]);
+
+ // 정렬이 변경될 때 데이터 다시 로드 (응답 데이터는 클라이언트 사이드 정렬)
+ React.useEffect(() => {
+ if (currentSorting && currentSorting.length > 0) {
+ const sortedData = [...initialData].sort((a, b) => {
+ for (const sort of currentSorting) {
+ const aValue = a[sort.id];
+ const bValue = b[sort.id];
+
+ if (aValue === bValue) continue;
+
+ if (aValue === null || aValue === undefined) return 1;
+ if (bValue === null || bValue === undefined) return -1;
+
+ if (typeof aValue === 'string' && typeof bValue === 'string') {
+ return sort.desc ? bValue.localeCompare(aValue) : aValue.localeCompare(bValue);
+ }
+
+ if (aValue instanceof Date && bValue instanceof Date) {
+ return sort.desc ? bValue.getTime() - aValue.getTime() : aValue.getTime() - bValue.getTime();
+ }
+
+ return sort.desc ? (bValue > aValue ? 1 : -1) : (aValue > bValue ? 1 : -1);
+ }
+ return 0;
+ });
+
+ setData(sortedData);
+ } else {
+ setData(initialData);
+ }
+ }, [currentSorting, initialData]);
+
+ return (
+ <>
+ <DataTable table={table}>
+ <DataTableAdvancedToolbar
+ table={table}
+ filterFields={advancedFilterFields}
+ shallow={false}
+ >
+ <ComplianceResponsesToolbarActions table={table} />
+ </DataTableAdvancedToolbar>
+ </DataTable>
+ </>
+ );
+}