diff options
Diffstat (limited to 'components/form-data/form-data-table-columns.tsx')
| -rw-r--r-- | components/form-data/form-data-table-columns.tsx | 218 |
1 files changed, 148 insertions, 70 deletions
diff --git a/components/form-data/form-data-table-columns.tsx b/components/form-data/form-data-table-columns.tsx index 3749fe02..930e113b 100644 --- a/components/form-data/form-data-table-columns.tsx +++ b/components/form-data/form-data-table-columns.tsx @@ -42,6 +42,11 @@ export interface DataTableColumnJSON { uom?: string; uomId?: string; shi?: boolean; + + /** 템플릿에서 가져온 추가 정보 */ + hidden?: boolean; // true이면 컬럼 숨김 + seq?: number; // 정렬 순서 + head?: string; // 헤더 텍스트 (우선순위 가장 높음) } /** @@ -87,79 +92,70 @@ function getStatusBadgeVariant(status: string): "default" | "secondary" | "destr } /** - * getColumns 함수 - * 1) columnsJSON 배열을 순회하면서 accessorKey / header / cell 등을 설정 - * 2) 체크박스 컬럼 추가 (showBatchSelection이 true일 때) - * 3) 마지막에 "Action" 칼럼(예: update 버튼) 추가 + * 헤더 텍스트를 결정하는 헬퍼 함수 + * displayLabel이 있으면 사용, 없으면 label 사용 */ -export function getColumns<TData extends object>({ - columnsJSON, - setRowAction, - setReportData, - tempCount, - selectedRows = {}, - onRowSelectionChange, - // editableFieldsMap 매개변수 제거됨 -}: GetColumnsProps<TData>): ColumnDef<TData>[] { - const columns: ColumnDef<TData>[] = []; +function getHeaderText(col: DataTableColumnJSON): string { + if (col.displayLabel && col.displayLabel.trim()) { + return col.displayLabel; + } + return col.label; +} - // (1) 체크박스 컬럼 (항상 표시) - const selectColumn: ColumnDef<TData> = { - id: "select", - header: ({ table }) => ( - <Checkbox - checked={ - table.getIsAllPageRowsSelected() || - (table.getIsSomePageRowsSelected() && "indeterminate") - } - onCheckedChange={(value) => { - table.toggleAllPageRowsSelected(!!value); - - // 모든 행 선택/해제 - if (onRowSelectionChange) { - const allRowsSelection: Record<string, boolean> = {}; - table.getRowModel().rows.forEach((row) => { - allRowsSelection[row.id] = !!value; - }); - onRowSelectionChange(allRowsSelection); - } - }} - aria-label="Select all" - className="translate-y-[2px]" - /> - ), - cell: ({ row }) => ( - <Checkbox - checked={row.getIsSelected()} - onCheckedChange={(value) => { - row.toggleSelected(!!value); - - // 개별 행 선택 상태 업데이트 - if (onRowSelectionChange) { - onRowSelectionChange(prev => ({ - ...prev, - [row.id]: !!value - })); - } - }} - aria-label="Select row" - className="translate-y-[2px]" - /> - ), - enableSorting: false, - enableHiding: false, - enablePinning: true, - size: 40, - }; - columns.push(selectColumn); +/** + * 컬럼들을 head 값에 따라 그룹핑하는 헬퍼 함수 + */ +function groupColumnsByHead(columns: DataTableColumnJSON[]): ColumnDef<any>[] { + const groupedColumns: ColumnDef<any>[] = []; + const groupMap = new Map<string, DataTableColumnJSON[]>(); + const ungroupedColumns: DataTableColumnJSON[] = []; + + // head 값에 따라 컬럼들을 그룹핑 + columns.forEach(col => { + if (col.head && col.head.trim()) { + const groupKey = col.head.trim(); + if (!groupMap.has(groupKey)) { + groupMap.set(groupKey, []); + } + groupMap.get(groupKey)!.push(col); + } else { + ungroupedColumns.push(col); + } + }); + + // 그룹핑된 컬럼들 처리 + groupMap.forEach((groupColumns, groupHeader) => { + if (groupColumns.length === 1) { + // 그룹에 컬럼이 하나만 있으면 일반 컬럼으로 처리 + ungroupedColumns.push(groupColumns[0]); + } else { + // 그룹 컬럼 생성 + const groupColumn: ColumnDef<any> = { + header: groupHeader, + columns: groupColumns.map(col => createColumnDef(col)) + }; + groupedColumns.push(groupColumn); + } + }); + + // 그룹핑되지 않은 컬럼들 처리 + ungroupedColumns.forEach(col => { + groupedColumns.push(createColumnDef(col)); + }); + + return groupedColumns; +} - // (2) 기본 컬럼들 - const baseColumns: ColumnDef<TData>[] = columnsJSON.map((col) => ({ +/** + * 개별 컬럼 정의를 생성하는 헬퍼 함수 + */ +function createColumnDef(col: DataTableColumnJSON): ColumnDef<any> { + return { accessorKey: col.key, header: ({ column }) => ( <ClientDataTableColumnHeaderSimple column={column} - title={col.displayLabel || col.label} + title={getHeaderText(col)} /> ), @@ -240,11 +236,93 @@ export function getColumns<TData extends object>({ ); } }, - })); + }; +} + +/** + * getColumns 함수 + * 1) columnsJSON 배열을 필터링 (hidden이 true가 아닌 것들만) + * 2) seq에 따라 정렬 + * 3) head 값에 따라 컬럼 그룹핑 + * 4) 체크박스 컬럼 추가 + * 5) 마지막에 "Action" 칼럼 추가 + */ +export function getColumns<TData extends object>({ + columnsJSON, + setRowAction, + setReportData, + tempCount, + selectedRows = {}, + onRowSelectionChange, + // editableFieldsMap 매개변수 제거됨 +}: GetColumnsProps<TData>): ColumnDef<TData>[] { + const columns: ColumnDef<TData>[] = []; + + // (0) 컬럼 필터링 및 정렬 + const visibleColumns = columnsJSON + .filter(col => col.hidden !== true) // hidden이 true가 아닌 것들만 + .sort((a, b) => { + // seq가 없는 경우 999999로 처리하여 맨 뒤로 보냄 + const seqA = a.seq !== undefined ? a.seq : 999999; + const seqB = b.seq !== undefined ? b.seq : 999999; + return seqA - seqB; + }); + + // (1) 체크박스 컬럼 (항상 표시) + const selectColumn: ColumnDef<TData> = { + id: "select", + header: ({ table }) => ( + <Checkbox + checked={ + table.getIsAllPageRowsSelected() || + (table.getIsSomePageRowsSelected() && "indeterminate") + } + onCheckedChange={(value) => { + table.toggleAllPageRowsSelected(!!value); + + // 모든 행 선택/해제 + if (onRowSelectionChange) { + const allRowsSelection: Record<string, boolean> = {}; + table.getRowModel().rows.forEach((row) => { + allRowsSelection[row.id] = !!value; + }); + onRowSelectionChange(allRowsSelection); + } + }} + aria-label="Select all" + className="translate-y-[2px]" + /> + ), + cell: ({ row }) => ( + <Checkbox + checked={row.getIsSelected()} + onCheckedChange={(value) => { + row.toggleSelected(!!value); + + // 개별 행 선택 상태 업데이트 + if (onRowSelectionChange) { + onRowSelectionChange(prev => ({ + ...prev, + [row.id]: !!value + })); + } + }} + aria-label="Select row" + className="translate-y-[2px]" + /> + ), + enableSorting: false, + enableHiding: false, + enablePinning: true, + size: 40, + }; + columns.push(selectColumn); - columns.push(...baseColumns); + // (2) 기본 컬럼들 (head에 따라 그룹핑 처리) + const groupedColumns = groupColumnsByHead(visibleColumns); + columns.push(...groupedColumns); - // (4) 액션 칼럼 - update 버튼 예시 + // (3) 액션 칼럼 - update 버튼 예시 const actionColumn: ColumnDef<TData> = { id: "update", header: "", @@ -297,6 +375,6 @@ export function getColumns<TData extends object>({ columns.push(actionColumn); - // (5) 최종 반환 + // (4) 최종 반환 return columns; }
\ No newline at end of file |
