diff options
| author | 0-Zz-ang <s1998319@gmail.com> | 2025-08-22 13:47:37 +0900 |
|---|---|---|
| committer | 0-Zz-ang <s1998319@gmail.com> | 2025-08-22 13:47:37 +0900 |
| commit | fefca6304eefea94f41057f9f934b0e19ceb54bb (patch) | |
| tree | f4914faa83e242a68d27feac58ebf0c527302cd2 /lib/compliance/responses/compliance-responses-table.tsx | |
| parent | dbdae213e39b82ff8ee565df0774bd2f72f06140 (diff) | |
(박서영)Compliance 설문/응답 리스트 생성
Diffstat (limited to 'lib/compliance/responses/compliance-responses-table.tsx')
| -rw-r--r-- | lib/compliance/responses/compliance-responses-table.tsx | 141 |
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> + </> + ); +} |
