diff options
| author | joonhoekim <26rote@gmail.com> | 2025-11-27 17:53:34 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-11-27 17:53:34 +0900 |
| commit | 5870b73785715d1585531e655c06d8c068eb64ac (patch) | |
| tree | 1d19e1482f5210cc56e778158b51e810f9717c46 /components/client-data-table | |
| parent | 95984e67b8d57fbe1431fcfedf3bb682f28416b3 (diff) | |
(김준회) Revert "(대표님) EDP 작업사항"
태그 가져오기 실패 등 에러로 인한 Revert 처리
Diffstat (limited to 'components/client-data-table')
| -rw-r--r-- | components/client-data-table/data-table.tsx | 300 |
1 files changed, 146 insertions, 154 deletions
diff --git a/components/client-data-table/data-table.tsx b/components/client-data-table/data-table.tsx index 371a1dab..3e009302 100644 --- a/components/client-data-table/data-table.tsx +++ b/components/client-data-table/data-table.tsx @@ -49,9 +49,8 @@ interface DataTableProps<TData, TValue> { children?: React.ReactNode /** 선택 상태 초기화 트리거 */ clearSelection?: boolean - initialColumnPinning?: ColumnPinningState - /** Table 인스턴스를 상위 컴포넌트에 전달하는 콜백 */ - onTableReady?: (table: Table<TData>) => void + initialColumnPinning?: ColumnPinningState // 추가 + } export function ClientDataTable<TData, TValue>({ @@ -64,8 +63,7 @@ export function ClientDataTable<TData, TValue>({ maxHeight, onSelectedRowsChange, clearSelection, - initialColumnPinning, - onTableReady + initialColumnPinning }: DataTableProps<TData, TValue>) { // (1) React Table 상태 @@ -120,13 +118,6 @@ export function ClientDataTable<TData, TValue>({ useAutoSizeColumns(table, autoSizeColumns) - // 🆕 Table 인스턴스를 상위 컴포넌트에 전달 - React.useEffect(() => { - if (onTableReady) { - onTableReady(table) - } - }, [table, onTableReady]) - React.useEffect(() => { if (!onSelectedRowsChange) return const selectedRows = table @@ -173,7 +164,6 @@ export function ClientDataTable<TData, TValue>({ }), } } - // 🎯 테이블 총 너비 계산 const getTableWidth = React.useCallback(() => { const totalSize = table.getCenterTotalSize() + table.getLeftTotalSize() + table.getRightTotalSize() @@ -216,172 +206,174 @@ export function ClientDataTable<TData, TValue>({ {children} </ClientDataTableAdvancedToolbar> - <div - className="max-w-[100vw] overflow-auto" - style={{ maxHeight: maxHeight || '34rem' }} - onScroll={handleScroll} // 🎯 스크롤 이벤트 핸들러 추가 - > - <UiTable + + <div + className="max-w-[100vw] overflow-auto" + style={{ maxHeight: maxHeight || '34rem' }} + onScroll={handleScroll} // 🎯 스크롤 이벤트 핸들러 추가 + > + <UiTable className={cn( "[&>thead]:sticky [&>thead]:top-0 [&>thead]:z-10", !hasNestedHeader && "table-fixed" // nested header가 없으면 table-fixed 적용 )} style={{ minWidth: hasNestedHeader ? getTableWidth() : undefined }}> - {/* nested header가 있으면 table-fixed 제거, 없으면 적용 */} - <TableHeader> - {table.getHeaderGroups().map((headerGroup) => ( - <TableRow key={headerGroup.id} className={compactStyles.headerRow}> - {headerGroup.headers.map((header) => { - // 만약 이 컬럼이 현재 "그룹핑" 상태라면 헤더도 표시하지 않음 - if (header.column.getIsGrouped()) { - return null - } + {/* nested header가 있으면 table-fixed 제거, 없으면 적용 */} + <TableHeader> + {table.getHeaderGroups().map((headerGroup) => ( + <TableRow key={headerGroup.id} className={compactStyles.headerRow}> + {headerGroup.headers.map((header) => { + // 만약 이 컬럼이 현재 "그룹핑" 상태라면 헤더도 표시하지 않음 + if (header.column.getIsGrouped()) { + return null + } - return ( - <TableHead - key={header.id} - colSpan={header.colSpan} - data-column-id={header.column.id} - className={compactStyles.header} - style={{ - ...getPinnedStyle(header.column, true), // 🎯 헤더임을 명시 - // 부모 그룹 헤더는 colSpan으로 너비가 결정되므로 width 설정하지 않음 - // 자식 헤더만 개별 width 설정 - ...(!('columns' in header.column.columnDef) && { width: header.getSize() }), - }} - > - <div style={{ position: "relative" }}> - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.header, - header.getContext() + return ( + <TableHead + key={header.id} + colSpan={header.colSpan} + data-column-id={header.column.id} + className={compactStyles.header} + style={{ + ...getPinnedStyle(header.column, true), // 🎯 헤더임을 명시 + // 부모 그룹 헤더는 colSpan으로 너비가 결정되므로 width 설정하지 않음 + // 자식 헤더만 개별 width 설정 + ...(!('columns' in header.column.columnDef) && { width: header.getSize() }), + }} + > + <div style={{ position: "relative" }}> + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + {/* 부모 그룹 헤더는 리사이즈 불가, 자식 헤더만 리사이즈 가능 */} + {header.column.getCanResize() && !('columns' in header.column.columnDef) && ( + <DataTableResizer header={header} /> )} - - {/* 부모 그룹 헤더는 리사이즈 불가, 자식 헤더만 리사이즈 가능 */} - {header.column.getCanResize() && !('columns' in header.column.columnDef) && ( - <DataTableResizer header={header} /> - )} - </div> - </TableHead> - ) - })} - </TableRow> - ))} - </TableHeader> - <TableBody> - {table.getRowModel().rows?.length ? ( - table.getRowModel().rows.map((row) => { - // --------------------------------------------------- - // 1) "그룹핑 헤더" Row인지 확인 - // --------------------------------------------------- - if (row.getIsGrouped()) { - // row.groupingColumnId로 어떤 컬럼을 기준으로 그룹화 되었는지 알 수 있음 - const groupingColumnId = row.groupingColumnId ?? "" - const groupingColumn = table.getColumn(groupingColumnId) // 해당 column 객체 + </div> + </TableHead> + ) + })} + </TableRow> + ))} + </TableHeader> + <TableBody> + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => { + // --------------------------------------------------- + // 1) "그룹핑 헤더" Row인지 확인 + // --------------------------------------------------- + if (row.getIsGrouped()) { + // row.groupingColumnId로 어떤 컬럼을 기준으로 그룹화 되었는지 알 수 있음 + const groupingColumnId = row.groupingColumnId ?? "" + const groupingColumn = table.getColumn(groupingColumnId) // 해당 column 객체 - // 컬럼 라벨 가져오기 - let columnLabel = groupingColumnId - if (groupingColumn) { - const headerDef = groupingColumn.columnDef.meta?.excelHeader - if (typeof headerDef === "string") { - columnLabel = headerDef + // 컬럼 라벨 가져오기 + let columnLabel = groupingColumnId + if (groupingColumn) { + const headerDef = groupingColumn.columnDef.meta?.excelHeader + if (typeof headerDef === "string") { + columnLabel = headerDef + } } + + return ( + <TableRow + key={row.id} + className={compactStyles.groupRow} + data-state={row.getIsExpanded() && "expanded"} + > + {/* 그룹 헤더는 한 줄에 합쳐서 보여주고, 토글 버튼 + 그룹 라벨 + 값 표기 */} + <TableCell + colSpan={table.getVisibleFlatColumns().length} + className={compact ? "py-1 px-2" : ""} + > + {/* 확장/축소 버튼 (아이콘 중앙 정렬 + Indent) */} + {row.getCanExpand() && ( + <button + onClick={row.getToggleExpandedHandler()} + className="inline-flex items-center justify-center mr-2 w-5 h-5" + style={{ + // row.depth: 0이면 top-level, 1이면 그 하위 등 + marginLeft: `${row.depth * 1.5}rem`, + }} + > + {row.getIsExpanded() ? ( + <ChevronUp size={compact ? 14 : 16} /> + ) : ( + <ChevronRight size={compact ? 14 : 16} /> + )} + </button> + )} + + {/* Group Label + 값 */} + <span className="font-semibold"> + {columnLabel}: {row.getValue(groupingColumnId)} + </span> + <span className="ml-2 text-xs text-muted-foreground"> + ({row.subRows.length} rows) + </span> + </TableCell> + </TableRow> + ) } + // --------------------------------------------------- + // 2) 일반 Row + // → "그룹핑된 컬럼"은 숨긴다 + // --------------------------------------------------- return ( <TableRow key={row.id} - className={compactStyles.groupRow} - data-state={row.getIsExpanded() && "expanded"} + className={compactStyles.row} + data-state={row.getIsSelected() && "selected"} > - {/* 그룹 헤더는 한 줄에 합쳐서 보여주고, 토글 버튼 + 그룹 라벨 + 값 표기 */} - <TableCell - colSpan={table.getVisibleFlatColumns().length} - className={compact ? "py-1 px-2" : ""} - > - {/* 확장/축소 버튼 (아이콘 중앙 정렬 + Indent) */} - {row.getCanExpand() && ( - <button - onClick={row.getToggleExpandedHandler()} - className="inline-flex items-center justify-center mr-2 w-5 h-5" + {row.getVisibleCells().map((cell) => { + // 이 셀의 컬럼이 grouped라면 숨긴다 + if (cell.column.getIsGrouped()) { + return null + } + + return ( + <TableCell + key={cell.id} + data-column-id={cell.column.id} + className={compactStyles.cell} style={{ - // row.depth: 0이면 top-level, 1이면 그 하위 등 - marginLeft: `${row.depth * 1.5}rem`, + ...getPinnedStyle(cell.column, false), // 🎯 바디 셀임을 명시 + width: cell.column.getSize() // 🎯 width 별도 설정 }} > - {row.getIsExpanded() ? ( - <ChevronUp size={compact ? 14 : 16} /> - ) : ( - <ChevronRight size={compact ? 14 : 16} /> + {flexRender( + cell.column.columnDef.cell, + cell.getContext() )} - </button> - )} - - {/* Group Label + 값 */} - <span className="font-semibold"> - {columnLabel}: {row.getValue(groupingColumnId)} - </span> - <span className="ml-2 text-xs text-muted-foreground"> - ({row.subRows.length} rows) - </span> - </TableCell> + </TableCell> + ) + })} </TableRow> ) - } - + }) + ) : ( // --------------------------------------------------- - // 2) 일반 Row - // → "그룹핑된 컬럼"은 숨긴다 + // 3) 데이터가 없을 때 // --------------------------------------------------- - return ( - <TableRow - key={row.id} - className={compactStyles.row} - data-state={row.getIsSelected() && "selected"} + <TableRow> + <TableCell + colSpan={table.getAllColumns().length} + className={compactStyles.emptyRow + " text-center"} > - {row.getVisibleCells().map((cell) => { - // 이 셀의 컬럼이 grouped라면 숨긴다 - if (cell.column.getIsGrouped()) { - return null - } + No results. + </TableCell> + </TableRow> + )} + </TableBody> + </UiTable> + </div> - return ( - <TableCell - key={cell.id} - data-column-id={cell.column.id} - className={compactStyles.cell} - style={{ - ...getPinnedStyle(cell.column, false), // 🎯 바디 셀임을 명시 - width: cell.column.getSize() // 🎯 width 별도 설정 - }} - > - {flexRender( - cell.column.columnDef.cell, - cell.getContext() - )} - </TableCell> - ) - })} - </TableRow> - ) - }) - ) : ( - // --------------------------------------------------- - // 3) 데이터가 없을 때 - // --------------------------------------------------- - <TableRow> - <TableCell - colSpan={table.getAllColumns().length} - className={compactStyles.emptyRow + " text-center"} - > - No results. - </TableCell> - </TableRow> - )} - </TableBody> - </UiTable> - </div> <ClientDataTablePagination table={table} /> </div> |
