feat: TableListComponent에 FlowWidget과 동일한 필터 설정 UI 구현
- 전체 선택/해제 기능 추가 - 선택된 컬럼 개수 표시 추가 - 필터 설정 localStorage 저장/로드 기능 - 체크된 항목만 실제 검색 필터로 표시 - 저장 시 Toast 알림 추가 - FlowWidget과 완전히 동일한 UI/UX 적용
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user