diff --git a/frontend/components/screen/table-options/ColumnVisibilityPanel.tsx b/frontend/components/screen/table-options/ColumnVisibilityPanel.tsx index 64acd942..67c11171 100644 --- a/frontend/components/screen/table-options/ColumnVisibilityPanel.tsx +++ b/frontend/components/screen/table-options/ColumnVisibilityPanel.tsx @@ -97,9 +97,13 @@ export const ColumnVisibilityPanel: React.FC = ({ table.onColumnOrderChange(newOrder); } - // 틀고정 컬럼 수 변경 콜백 호출 + // 틀고정 컬럼 수 변경 콜백 호출 (현재 컬럼 상태도 함께 전달) if (table?.onFrozenColumnCountChange) { - table.onFrozenColumnCountChange(frozenColumnCount); + const updatedColumns = localColumns.map((col) => ({ + columnName: col.columnName, + visible: col.visible, + })); + table.onFrozenColumnCountChange(frozenColumnCount, updatedColumns); } onClose(); diff --git a/frontend/lib/registry/components/table-list/TableListComponent.tsx b/frontend/lib/registry/components/table-list/TableListComponent.tsx index 74cea859..09422164 100644 --- a/frontend/lib/registry/components/table-list/TableListComponent.tsx +++ b/frontend/lib/registry/components/table-list/TableListComponent.tsx @@ -1039,14 +1039,16 @@ export const TableListComponent: React.FC = ({ onGroupSumChange: setGroupSumConfig, // 그룹별 합산 설정 // 틀고정 컬럼 관련 frozenColumnCount, // 현재 틀고정 컬럼 수 - onFrozenColumnCountChange: (count: number) => { + onFrozenColumnCountChange: (count: number, updatedColumns?: Array<{ columnName: string; visible: boolean }>) => { setFrozenColumnCount(count); // 체크박스 컬럼은 항상 틀고정에 포함 const checkboxColumn = (tableConfig.checkbox?.enabled ?? true) ? ["__checkbox__"] : []; // 표시 가능한 컬럼 중 처음 N개를 틀고정 컬럼으로 설정 - const visibleCols = columnsToRegister + // updatedColumns가 전달되면 그것을 사용, 아니면 columnsToRegister 사용 + const colsToUse = updatedColumns || columnsToRegister; + const visibleCols = colsToUse .filter((col) => col.visible !== false) - .map((col) => col.columnName || col.field); + .map((col) => col.columnName || (col as any).field); const newFrozenColumns = [...checkboxColumn, ...visibleCols.slice(0, count)]; setFrozenColumns(newFrozenColumns); }, @@ -4754,9 +4756,22 @@ export const TableListComponent: React.FC = ({ }); setColumnWidths(newWidths); - // 틀고정 컬럼 업데이트 - const newFrozenColumns = config.columns.filter((col) => col.frozen).map((col) => col.columnName); + // 틀고정 컬럼 업데이트 (보이는 컬럼 기준으로 처음 N개를 틀고정) + // 기존 frozen 개수를 유지하면서, 숨겨진 컬럼을 제외한 보이는 컬럼 중 처음 N개를 틀고정 + const checkboxColumn = (tableConfig.checkbox?.enabled ?? true) ? ["__checkbox__"] : []; + const visibleCols = config.columns + .filter((col) => col.visible && col.columnName !== "__checkbox__") + .map((col) => col.columnName); + + // 현재 설정된 frozen 컬럼 개수 (체크박스 제외) + const currentFrozenCount = config.columns.filter( + (col) => col.frozen && col.columnName !== "__checkbox__" + ).length; + + // 보이는 컬럼 중 처음 currentFrozenCount개를 틀고정으로 설정 + const newFrozenColumns = [...checkboxColumn, ...visibleCols.slice(0, currentFrozenCount)]; setFrozenColumns(newFrozenColumns); + setFrozenColumnCount(currentFrozenCount); // 그리드선 표시 업데이트 setShowGridLines(config.showGridLines); @@ -5819,13 +5834,18 @@ export const TableListComponent: React.FC = ({ {visibleColumns.map((column, columnIndex) => { const columnWidth = columnWidths[column.columnName]; const isFrozen = frozenColumns.includes(column.columnName); - const frozenIndex = frozenColumns.indexOf(column.columnName); - - // 틀고정된 컬럼의 left 위치 계산 + + // 틀고정된 컬럼의 left 위치 계산 (보이는 컬럼 기준으로 계산) + // 숨겨진 컬럼은 제외하고 보이는 틀고정 컬럼만 포함 + const visibleFrozenColumns = visibleColumns + .filter(col => frozenColumns.includes(col.columnName)) + .map(col => col.columnName); + const frozenIndex = visibleFrozenColumns.indexOf(column.columnName); + let leftPosition = 0; if (isFrozen && frozenIndex > 0) { for (let i = 0; i < frozenIndex; i++) { - const frozenCol = frozenColumns[i]; + const frozenCol = visibleFrozenColumns[i]; // 체크박스 컬럼은 48px 고정 const frozenColWidth = frozenCol === "__checkbox__" ? 48 : columnWidths[frozenCol] || 150; leftPosition += frozenColWidth; @@ -6131,13 +6151,17 @@ export const TableListComponent: React.FC = ({ const isNumeric = inputType === "number" || inputType === "decimal"; const isFrozen = frozenColumns.includes(column.columnName); - const frozenIndex = frozenColumns.indexOf(column.columnName); + + // 틀고정된 컬럼의 left 위치 계산 (보이는 컬럼 기준으로 계산) + const visibleFrozenColumns = visibleColumns + .filter(col => frozenColumns.includes(col.columnName)) + .map(col => col.columnName); + const frozenIndex = visibleFrozenColumns.indexOf(column.columnName); - // 틀고정된 컬럼의 left 위치 계산 let leftPosition = 0; if (isFrozen && frozenIndex > 0) { for (let i = 0; i < frozenIndex; i++) { - const frozenCol = frozenColumns[i]; + const frozenCol = visibleFrozenColumns[i]; // 체크박스 컬럼은 48px 고정 const frozenColWidth = frozenCol === "__checkbox__" ? 48 : columnWidths[frozenCol] || 150; @@ -6284,7 +6308,12 @@ export const TableListComponent: React.FC = ({ const isNumeric = inputType === "number" || inputType === "decimal"; const isFrozen = frozenColumns.includes(column.columnName); - const frozenIndex = frozenColumns.indexOf(column.columnName); + + // 틀고정된 컬럼의 left 위치 계산 (보이는 컬럼 기준으로 계산) + const visibleFrozenColumns = visibleColumns + .filter(col => frozenColumns.includes(col.columnName)) + .map(col => col.columnName); + const frozenIndex = visibleFrozenColumns.indexOf(column.columnName); // 셀 포커스 상태 const isCellFocused = focusedCell?.rowIndex === index && focusedCell?.colIndex === colIndex; @@ -6298,11 +6327,10 @@ export const TableListComponent: React.FC = ({ // 🆕 검색 하이라이트 여부 const isSearchHighlighted = searchHighlights.has(`${index}-${colIndex}`); - // 틀고정된 컬럼의 left 위치 계산 let leftPosition = 0; if (isFrozen && frozenIndex > 0) { for (let i = 0; i < frozenIndex; i++) { - const frozenCol = frozenColumns[i]; + const frozenCol = visibleFrozenColumns[i]; // 체크박스 컬럼은 48px 고정 const frozenColWidth = frozenCol === "__checkbox__" ? 48 : columnWidths[frozenCol] || 150; @@ -6462,13 +6490,17 @@ export const TableListComponent: React.FC = ({ const summary = summaryData[column.columnName]; const columnWidth = columnWidths[column.columnName]; const isFrozen = frozenColumns.includes(column.columnName); - const frozenIndex = frozenColumns.indexOf(column.columnName); + + // 틀고정된 컬럼의 left 위치 계산 (보이는 컬럼 기준으로 계산) + const visibleFrozenColumns = visibleColumns + .filter(col => frozenColumns.includes(col.columnName)) + .map(col => col.columnName); + const frozenIndex = visibleFrozenColumns.indexOf(column.columnName); - // 틀고정된 컬럼의 left 위치 계산 let leftPosition = 0; if (isFrozen && frozenIndex > 0) { for (let i = 0; i < frozenIndex; i++) { - const frozenCol = frozenColumns[i]; + const frozenCol = visibleFrozenColumns[i]; // 체크박스 컬럼은 48px 고정 const frozenColWidth = frozenCol === "__checkbox__" ? 48 : columnWidths[frozenCol] || 150; leftPosition += frozenColWidth; diff --git a/frontend/types/table-options.ts b/frontend/types/table-options.ts index bfcfccbc..6f9b2644 100644 --- a/frontend/types/table-options.ts +++ b/frontend/types/table-options.ts @@ -66,7 +66,7 @@ export interface TableRegistration { onGroupChange: (groups: string[]) => void; onColumnVisibilityChange: (columns: ColumnVisibility[]) => void; onGroupSumChange?: (config: GroupSumConfig | null) => void; // 그룹별 합산 설정 변경 - onFrozenColumnCountChange?: (count: number) => void; // 틀고정 컬럼 수 변경 + onFrozenColumnCountChange?: (count: number, updatedColumns?: Array<{ columnName: string; visible: boolean }>) => void; // 틀고정 컬럼 수 변경 // 현재 설정 값 (읽기 전용) frozenColumnCount?: number; // 현재 틀고정 컬럼 수