3.0 KiB
3.0 KiB
TableListComponent 상세 참조
주요 상태 (State)
// 데이터
const [tableData, setTableData] = useState<any[]>([]);
const [filteredData, setFilteredData] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
// 편집
const [editingCell, setEditingCell] = useState<{
rowIndex: number; colIndex: number; columnName: string; originalValue: any;
} | null>(null);
const [pendingChanges, setPendingChanges] = useState<Map<string, Map<string, any>>>(new Map());
const [validationErrors, setValidationErrors] = useState<Map<string, Map<string, string>>>(new Map());
// 필터
const [headerFilters, setHeaderFilters] = useState<Map<string, Set<string>>>(new Map());
const [filterGroups, setFilterGroups] = useState<FilterGroup[]>([]);
const [globalSearchText, setGlobalSearchText] = useState("");
// 컬럼
const [columnWidths, setColumnWidths] = useState<Record<string, number>>({});
const [columnOrder, setColumnOrder] = useState<string[]>([]);
const [columnVisibility, setColumnVisibility] = useState<Record<string, boolean>>({});
// 선택/정렬/페이지네이션
const [selectedRows, setSelectedRows] = useState<Set<string>>(new Set());
const [sortBy, setSortBy] = useState<string>("");
const [sortOrder, setSortOrder] = useState<"asc" | "desc">("asc");
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(20);
타입 정의
type ValidationRule = {
required?: boolean;
min?: number; max?: number;
minLength?: number; maxLength?: number;
pattern?: RegExp;
customMessage?: string;
validate?: (value: any, row: any) => string | null;
};
interface FilterCondition {
id: string; column: string;
operator: "equals" | "notEquals" | "contains" | "notContains" |
"startsWith" | "endsWith" | "greaterThan" | "lessThan" |
"greaterOrEqual" | "lessOrEqual" | "isEmpty" | "isNotEmpty";
value: string;
}
interface FilterGroup { id: string; logic: "AND" | "OR"; conditions: FilterCondition[]; }
interface TableState {
columnWidths: Record<string, number>;
columnOrder: string[];
sortBy: string; sortOrder: "asc" | "desc";
frozenColumns: string[];
columnVisibility: Record<string, boolean>;
}
캐싱 전략
const tableColumnCache = new Map<string, { columns: any[]; timestamp: number }>();
const TABLE_CACHE_TTL = 5 * 60 * 1000; // 5분
키보드 네비게이션
| 키 | 동작 |
|---|---|
| Arrow Keys | 셀 이동 |
| Tab/Shift+Tab | 다음/이전 셀 |
| F2 | 편집 모드 |
| Enter | 저장 후 아래로 |
| Escape | 편집 취소 |
| Ctrl+C | 복사 |
| Delete | 셀 값 삭제 |
필수 Import
import React, { useState, useEffect, useMemo, useCallback, useRef } from "react";
import { TableListConfig, ColumnConfig } from "./types";
import { tableTypeApi } from "@/lib/api/screen";
import { entityJoinApi } from "@/lib/api/entityJoin";
import { codeCache } from "@/lib/caching/codeCache";
import * as XLSX from "xlsx";
import { toast } from "sonner";