From f2ab4f11bda249fe76d4f0a4394eb5ec2d36202d Mon Sep 17 00:00:00 2001 From: leeheejin Date: Mon, 19 Jan 2026 10:14:20 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=EC=A7=84=EC=A7=9C=20=ED=95=B4=EA=B2=B0?= =?UTF-8?q?=ED=96=88=EC=9D=8C=20=EC=A7=84=EC=A7=9C=EC=A7=84=EC=A7=9C?= =?UTF-8?q?=EB=A1=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../registry/components/pivot-grid/PivotGridComponent.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/lib/registry/components/pivot-grid/PivotGridComponent.tsx b/frontend/lib/registry/components/pivot-grid/PivotGridComponent.tsx index 57bc2e8a..53ad204d 100644 --- a/frontend/lib/registry/components/pivot-grid/PivotGridComponent.tsx +++ b/frontend/lib/registry/components/pivot-grid/PivotGridComponent.tsx @@ -1674,7 +1674,11 @@ export const PivotGridComponent: React.FC = ({ className="flex-1 overflow-auto focus:outline-none" style={{ maxHeight: enableVirtualScroll && containerHeight > 0 ? containerHeight : undefined, - minHeight: 100 // 최소 높이 보장 - 블라인드 효과 방지 + // 최소 200px 보장 + 데이터에 맞게 조정 (최대 400px) + minHeight: Math.max( + 200, // 절대 최소값 - 블라인드 효과 방지 + Math.min(400, (sortedFlatRows.length + 3) * ROW_HEIGHT + 50) + ) }} tabIndex={0} onKeyDown={handleKeyDown} From c282d5c611bfa0bac9e43a7f478dbffa1ccdd1a3 Mon Sep 17 00:00:00 2001 From: leeheejin Date: Mon, 19 Jan 2026 10:14:48 +0900 Subject: [PATCH 2/3] Merge branch 'main' of http://39.117.244.52:3000/kjs/ERP-node into lhj From d09a6977f7083b394d0837aa248d699fa00c8799 Mon Sep 17 00:00:00 2001 From: leeheejin Date: Mon, 19 Jan 2026 17:25:12 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=EA=B2=80=EC=83=89=ED=95=84=ED=84=B0=20?= =?UTF-8?q?=EC=97=85=EA=B7=B8=EB=A0=88=EC=9D=B4=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../table-list/TableListComponent.tsx | 62 ++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/frontend/lib/registry/components/table-list/TableListComponent.tsx b/frontend/lib/registry/components/table-list/TableListComponent.tsx index 78abf111..366aa05b 100644 --- a/frontend/lib/registry/components/table-list/TableListComponent.tsx +++ b/frontend/lib/registry/components/table-list/TableListComponent.tsx @@ -41,7 +41,7 @@ import { Lock, } from "lucide-react"; import * as XLSX from "xlsx"; -import { FileText, ChevronRightIcon } from "lucide-react"; +import { FileText, ChevronRightIcon, Search } from "lucide-react"; import { Checkbox } from "@/components/ui/checkbox"; import { cn } from "@/lib/utils"; import { toast } from "sonner"; @@ -455,6 +455,7 @@ export const TableListComponent: React.FC = ({ // 🆕 컬럼 헤더 필터 상태 (상단에서 선언) const [headerFilters, setHeaderFilters] = useState>>({}); + const [headerLikeFilters, setHeaderLikeFilters] = useState>({}); // LIKE 검색용 const [openFilterColumn, setOpenFilterColumn] = useState(null); // 🆕 Filter Builder (고급 필터) 관련 상태 - filteredData보다 먼저 정의해야 함 @@ -488,6 +489,22 @@ export const TableListComponent: React.FC = ({ }); } + // 2-1. 🆕 LIKE 검색 필터 적용 + if (Object.keys(headerLikeFilters).length > 0) { + result = result.filter((row) => { + return Object.entries(headerLikeFilters).every(([columnName, searchText]) => { + if (!searchText || searchText.trim() === "") return true; + + // 여러 가능한 컬럼명 시도 + const cellValue = row[columnName] ?? row[columnName.toLowerCase()] ?? row[columnName.toUpperCase()]; + const cellStr = cellValue !== null && cellValue !== undefined ? String(cellValue).toLowerCase() : ""; + + // LIKE 검색 (대소문자 무시) + return cellStr.includes(searchText.toLowerCase()); + }); + }); + } + // 3. 🆕 Filter Builder 적용 if (filterGroups.length > 0) { result = result.filter((row) => { @@ -541,7 +558,7 @@ export const TableListComponent: React.FC = ({ } return result; - }, [data, splitPanelPosition, splitPanelContext?.addedItemIds, headerFilters, filterGroups]); + }, [data, splitPanelPosition, splitPanelContext?.addedItemIds, headerFilters, headerLikeFilters, filterGroups]); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(0); @@ -2935,6 +2952,7 @@ export const TableListComponent: React.FC = ({ headerFilters: Object.fromEntries( Object.entries(headerFilters).map(([key, set]) => [key, Array.from(set as Set)]), ), + headerLikeFilters, // LIKE 검색 필터 저장 pageSize: localPageSize, timestamp: Date.now(), }; @@ -2955,6 +2973,7 @@ export const TableListComponent: React.FC = ({ frozenColumnCount, showGridLines, headerFilters, + headerLikeFilters, localPageSize, ]); @@ -2991,6 +3010,9 @@ export const TableListComponent: React.FC = ({ }); setHeaderFilters(filters); } + if (state.headerLikeFilters) { + setHeaderLikeFilters(state.headerLikeFilters); + } } catch (error) { console.error("❌ 테이블 상태 복원 실패:", error); } @@ -5737,7 +5759,7 @@ export const TableListComponent: React.FC = ({ }} className={cn( "hover:bg-primary/20 ml-1 rounded p-0.5 transition-colors", - headerFilters[column.columnName]?.size > 0 && "text-primary bg-primary/10", + (headerFilters[column.columnName]?.size > 0 || headerLikeFilters[column.columnName]) && "text-primary bg-primary/10", )} title="필터" > @@ -5745,7 +5767,7 @@ export const TableListComponent: React.FC = ({ e.stopPropagation()} > @@ -5754,16 +5776,42 @@ export const TableListComponent: React.FC = ({ 필터: {columnLabels[column.columnName] || column.displayName} - {headerFilters[column.columnName]?.size > 0 && ( + {(headerFilters[column.columnName]?.size > 0 || headerLikeFilters[column.columnName]) && ( )} -
+ {/* LIKE 검색 입력 필드 */} +
+ + { + setHeaderLikeFilters((prev) => ({ + ...prev, + [column.columnName]: e.target.value, + })); + }} + className="border-input bg-background placeholder:text-muted-foreground h-7 w-full rounded-md border pl-7 pr-2 text-xs focus:outline-none focus:ring-1 focus:ring-primary" + onClick={(e) => e.stopPropagation()} + /> +
+ {/* 구분선 */} +
또는 값 선택:
+
{columnUniqueValues[column.columnName]?.slice(0, 50).map((val) => { const isSelected = headerFilters[column.columnName]?.has(val); return (