feat: TableListComponent에 FlowWidget과 동일한 필터 설정 UI 구현

- 전체 선택/해제 기능 추가
- 선택된 컬럼 개수 표시 추가
- 필터 설정 localStorage 저장/로드 기능
- 체크된 항목만 실제 검색 필터로 표시
- 저장 시 Toast 알림 추가
- FlowWidget과 완전히 동일한 UI/UX 적용
This commit is contained in:
kjs
2025-11-03 13:59:12 +09:00
parent e0e7bc387e
commit 297870a24c
2 changed files with 153 additions and 33 deletions

View File

@@ -38,10 +38,12 @@ import {
Folder,
FolderOpen,
Grid,
Filter,
} from "lucide-react";
import { tableTypeApi } from "@/lib/api/screen";
import { commonCodeApi } from "@/lib/api/commonCode";
import { getCurrentUser, UserInfo } from "@/lib/api/client";
import { useAuth } from "@/hooks/useAuth";
import { DataTableComponent, DataTableColumn, DataTableFilter } from "@/types/screen-legacy-backup";
import { cn } from "@/lib/utils";
import { downloadFile, getLinkedFiles, getFilePreviewUrl, getDirectFileUrl } from "@/lib/api/file";
@@ -99,6 +101,7 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
onRefresh,
}) => {
const { isPreviewMode } = useScreenPreview(); // 프리뷰 모드 확인
const { user } = useAuth(); // 사용자 정보 가져오기
const [data, setData] = useState<Record<string, any>[]>([]);
const [loading, setLoading] = useState(false);
const [searchValues, setSearchValues] = useState<Record<string, any>>({});
@@ -134,6 +137,13 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
// 공통코드 관리 상태
const [codeOptions, setCodeOptions] = useState<Record<string, Array<{ value: string; label: string }>>>({});
// 🆕 검색 필터 관련 상태 (FlowWidget과 동일)
const [searchFilterColumns, setSearchFilterColumns] = useState<Set<string>>(new Set()); // 검색 필터로 사용할 컬럼
const [isFilterSettingOpen, setIsFilterSettingOpen] = useState(false); // 필터 설정 다이얼로그
const [allAvailableColumns, setAllAvailableColumns] = useState<string[]>([]); // 전체 컬럼 목록
const [filteredData, setFilteredData] = useState<any[]>([]); // 필터링된 데이터
const [columnLabels, setColumnLabels] = useState<Record<string, string>>({}); // 컬럼명 -> 라벨 매핑
// 공통코드 옵션 가져오기
const loadCodeOptions = useCallback(
async (categoryCode: string) => {
@@ -633,6 +643,31 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
try {
const columns = await tableTypeApi.getColumns(component.tableName);
setTableColumns(columns);
// 🆕 전체 컬럼 목록 설정
const columnNames = columns.map(col => col.columnName);
setAllAvailableColumns(columnNames);
// 🆕 컬럼명 -> 라벨 매핑 생성
const labels: Record<string, string> = {};
columns.forEach(col => {
labels[col.columnName] = col.displayName || col.columnName;
});
setColumnLabels(labels);
// 🆕 localStorage에서 필터 설정 복원
if (user?.userId && component.componentId) {
const storageKey = `table-search-filter-${user.userId}-${component.componentId}`;
const savedFilter = localStorage.getItem(storageKey);
if (savedFilter) {
try {
const parsed = JSON.parse(savedFilter);
setSearchFilterColumns(new Set(parsed));
} catch (e) {
console.error("필터 설정 복원 실패:", e);
}
}
}
} catch (error) {
// console.error("테이블 컬럼 정보 로드 실패:", error);
}
@@ -641,7 +676,7 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
if (component.tableName) {
fetchTableColumns();
}
}, [component.tableName]);
}, [component.tableName, component.componentId, user?.userId]);
// 실제 사용할 필터 (설정된 필터만 사용, 자동 생성 안함)
const searchFilters = useMemo(() => {
@@ -1052,6 +1087,29 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
}
}, [isAdding]);
// 🆕 검색 필터 저장 함수
const handleSaveSearchFilter = useCallback(() => {
if (user?.userId && component.componentId) {
const storageKey = `table-search-filter-${user.userId}-${component.componentId}`;
const filterArray = Array.from(searchFilterColumns);
localStorage.setItem(storageKey, JSON.stringify(filterArray));
toast.success("검색 필터 설정이 저장되었습니다.");
}
}, [user?.userId, component.componentId, searchFilterColumns]);
// 🆕 검색 필터 토글 함수
const handleToggleFilterColumn = useCallback((columnName: string) => {
setSearchFilterColumns((prev) => {
const newSet = new Set(prev);
if (newSet.has(columnName)) {
newSet.delete(columnName);
} else {
newSet.add(columnName);
}
return newSet;
});
}, []);
// 데이터 삭제 핸들러
const handleDeleteData = useCallback(() => {
if (selectedRows.size === 0) {