"use client"; /** * useTableSettings — 날코딩 페이지용 테이블 설정 훅 * * TableSettingsModal과 함께 사용하여 컬럼 표시/숨김, 순서, 너비를 관리합니다. * 설정은 localStorage에 자동 저장/복원됩니다. * * @example * const ts = useTableSettings("item-info", TABLE_NAME, GRID_COLUMNS); * * // 툴바 버튼 * * * // 테이블 헤더 — GRID_COLUMNS 대신 ts.visibleColumns 사용 * {ts.visibleColumns.map(col => {col.label})} * * // 모달 (JSX 하단) * */ import { useState, useEffect, useCallback, useMemo } from "react"; import { loadTableSettings, type TableSettings } from "@/components/common/TableSettingsModal"; export function useTableSettings( settingsId: string, tableName: string, defaultColumns: T[], ) { const [open, setOpen] = useState(false); const [visibleKeys, setVisibleKeys] = useState>( () => new Set(defaultColumns.map((c) => c.key)), ); const [columnWidths, setColumnWidths] = useState>({}); const [orderedKeys, setOrderedKeys] = useState( () => defaultColumns.map((c) => c.key), ); // 초기 filterConfig: GRID_COLUMNS에 있는 컬럼만 필터 가능 (전부 비활성) const [filterConfig, setFilterConfig] = useState( () => defaultColumns.map((c) => ({ columnName: c.key, displayName: (c as any).label || c.key, enabled: false, filterType: "text" as const, width: 25, })), ); /** TableSettingsModal onSave에 전달할 콜백 */ const applySettings = useCallback( (settings: TableSettings) => { const visible = new Set(); const widths: Record = {}; const order: string[] = []; for (const cs of settings.columns) { if (cs.visible) { visible.add(cs.columnName); widths[cs.columnName] = cs.width; order.push(cs.columnName); } } // settings에 없는 새 컬럼은 보이도록 추가 for (const col of defaultColumns) { if (!settings.columns.find((c) => c.columnName === col.key)) { visible.add(col.key); order.push(col.key); } } setVisibleKeys(visible); setColumnWidths(widths); setOrderedKeys(order); // 화면에 표시된 컬럼만 필터 가능하도록 제한 setFilterConfig( settings.filters?.filter((f) => visible.has(f.columnName)), ); }, [defaultColumns], ); // 마운트 시 저장된 설정 복원 useEffect(() => { const saved = loadTableSettings(settingsId); if (saved) applySettings(saved); }, []); // eslint-disable-line react-hooks/exhaustive-deps /** 설정이 적용된 컬럼 목록 (순서 + 표시 필터 적용) */ const visibleColumns = useMemo((): T[] => { const colMap = new Map(defaultColumns.map((c) => [c.key, c])); const result: T[] = []; // 저장된 순서대로 for (const key of orderedKeys) { if (visibleKeys.has(key)) { const col = colMap.get(key); if (col) result.push(col); } } // orderedKeys에 없는 컬럼 (새로 추가된 것) for (const col of defaultColumns) { if (!orderedKeys.includes(col.key) && visibleKeys.has(col.key)) { result.push(col); } } return result.length > 0 ? result : defaultColumns; }, [defaultColumns, orderedKeys, visibleKeys]); /** 컬럼 표시 여부 확인 */ const isVisible = useCallback((key: string) => visibleKeys.has(key), [visibleKeys]); /** 컬럼 너비 가져오기 (설정값 or undefined) */ const getWidth = useCallback( (key: string): number | undefined => columnWidths[key], [columnWidths], ); return { /** 모달 open 상태 */ open, /** 모달 open 상태 setter */ setOpen, /** web-types API 호출용 테이블명 */ tableName, /** localStorage 키 */ settingsId, /** TableSettingsModal onSave 콜백 */ applySettings, /** 설정 적용된 컬럼 배열 (순서 + 표시 필터) */ visibleColumns, /** 특정 컬럼 표시 여부 */ isVisible, /** 특정 컬럼 너비 (px) */ getWidth, /** 필터 설정 */ filterConfig, /** GRID_COLUMNS 기본 컬럼 키 목록 (TableSettingsModal defaultVisibleKeys용) */ defaultVisibleKeys: defaultColumns.map((c) => c.key), }; }