feat: Implement pagination and enhanced keyword search in work instruction retrieval
- Added pagination support to the `getList` function in the work instruction controller, allowing for efficient data retrieval with `page` and `pageSize` parameters. - Enhanced the keyword search functionality to include checks for item numbers in the work instruction details, improving search accuracy. - Updated the frontend components to utilize the new `SmartSelect` component for supplier and partner selection, enhancing user experience. - Adjusted the `EDataTable` component to support server-side pagination, ensuring better performance with large datasets.
This commit is contained in:
@@ -83,6 +83,15 @@ export interface EDataTableProps<T extends Record<string, any> = any> {
|
||||
showPagination?: boolean;
|
||||
defaultPageSize?: number;
|
||||
|
||||
// ─── 서버사이드 페이지네이션 모드 ───
|
||||
// serverPagination=true 일 때: 내부 slice/filter/sort 미사용, data는 이미 해당 페이지 분량
|
||||
serverPagination?: boolean;
|
||||
serverCurrentPage?: number;
|
||||
serverPageSize?: number;
|
||||
serverTotalCount?: number;
|
||||
onServerPageChange?: (page: number) => void;
|
||||
onServerPageSizeChange?: (size: number) => void;
|
||||
|
||||
className?: string;
|
||||
}
|
||||
|
||||
@@ -275,6 +284,12 @@ export function EDataTable<T extends Record<string, any> = any>({
|
||||
showRowNumber = false,
|
||||
showPagination = true,
|
||||
defaultPageSize = 50,
|
||||
serverPagination = false,
|
||||
serverCurrentPage,
|
||||
serverPageSize,
|
||||
serverTotalCount,
|
||||
onServerPageChange,
|
||||
onServerPageSizeChange,
|
||||
className,
|
||||
}: EDataTableProps<T>) {
|
||||
const [columns, setColumns] = useState(initialColumns);
|
||||
@@ -287,10 +302,21 @@ export function EDataTable<T extends Record<string, any> = any>({
|
||||
// 헤더 필터
|
||||
const [headerFilters, setHeaderFilters] = useState<Record<string, Set<string>>>({});
|
||||
|
||||
// 페이지네이션
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [pageSize, setPageSize] = useState(defaultPageSize);
|
||||
const [pageSizeInput, setPageSizeInput] = useState(String(defaultPageSize));
|
||||
// 페이지네이션 — 서버사이드 모드면 외부 state 사용
|
||||
const [internalCurrentPage, setInternalCurrentPage] = useState(1);
|
||||
const [internalPageSize, setInternalPageSize] = useState(defaultPageSize);
|
||||
const currentPage = serverPagination ? (serverCurrentPage ?? 1) : internalCurrentPage;
|
||||
const pageSize = serverPagination ? (serverPageSize ?? defaultPageSize) : internalPageSize;
|
||||
const setCurrentPage = (next: number | ((prev: number) => number)) => {
|
||||
const resolved = typeof next === "function" ? (next as (p: number) => number)(currentPage) : next;
|
||||
if (serverPagination) onServerPageChange?.(resolved);
|
||||
else setInternalCurrentPage(resolved);
|
||||
};
|
||||
const setPageSize = (n: number) => {
|
||||
if (serverPagination) onServerPageSizeChange?.(n);
|
||||
else setInternalPageSize(n);
|
||||
};
|
||||
const [pageSizeInput, setPageSizeInput] = useState(String(serverPagination ? (serverPageSize ?? defaultPageSize) : defaultPageSize));
|
||||
|
||||
// 그룹 접기/펼치기
|
||||
const [collapsedGroups, setCollapsedGroups] = useState<Set<string>>(new Set());
|
||||
@@ -394,8 +420,9 @@ export function EDataTable<T extends Record<string, any> = any>({
|
||||
});
|
||||
};
|
||||
|
||||
// 필터 + 정렬
|
||||
// 필터 + 정렬 (서버사이드 모드면 원본 data 그대로 사용)
|
||||
const processedData = useMemo(() => {
|
||||
if (serverPagination) return data;
|
||||
let result = [...data];
|
||||
|
||||
// 헤더 필터
|
||||
@@ -425,24 +452,28 @@ export function EDataTable<T extends Record<string, any> = any>({
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [data, headerFilters, sortState, onSortChange]);
|
||||
}, [data, headerFilters, sortState, onSortChange, serverPagination]);
|
||||
|
||||
// 필터/데이터 건수 변경 시 1페이지 리셋 (참조만 바뀐 경우는 리셋 안 함)
|
||||
useEffect(() => { setCurrentPage(1); }, [data.length, headerFilters]);
|
||||
// 필터/데이터 건수 변경 시 1페이지 리셋 (서버사이드에선 외부가 제어)
|
||||
useEffect(() => {
|
||||
if (!serverPagination) setCurrentPage(1);
|
||||
}, [data.length, headerFilters, serverPagination]);
|
||||
|
||||
// 페이지네이션
|
||||
const totalItems = processedData.length;
|
||||
const totalItems = serverPagination ? (serverTotalCount ?? data.length) : processedData.length;
|
||||
const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
|
||||
const safePage = Math.min(currentPage, totalPages);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentPage > totalPages) setCurrentPage(totalPages);
|
||||
}, [currentPage, totalPages]);
|
||||
if (!serverPagination && currentPage > totalPages) setCurrentPage(totalPages);
|
||||
}, [currentPage, totalPages, serverPagination]);
|
||||
|
||||
const pageOffset = (safePage - 1) * pageSize;
|
||||
const paginatedDataRaw = showPagination
|
||||
? processedData.slice(pageOffset, pageOffset + pageSize)
|
||||
: processedData;
|
||||
const paginatedDataRaw = serverPagination
|
||||
? processedData
|
||||
: showPagination
|
||||
? processedData.slice(pageOffset, pageOffset + pageSize)
|
||||
: processedData;
|
||||
|
||||
// 접힌 그룹의 데이터 행 숨김
|
||||
const paginatedData = useMemo(() => {
|
||||
|
||||
Reference in New Issue
Block a user