diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-01 13:52:21 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-01 13:52:21 +0000 |
| commit | bac0228d21b7195065e9cddcc327ae33659c7bcc (patch) | |
| tree | 8f3016ae4533c8706d0c00a605d9b1d41968c2bc /components/data-table/data-table-pagination.tsx | |
| parent | 2fdce8d7a57c792bba0ac36fa554dca9c9cc31e3 (diff) | |
(대표님) 20250601까지 작업사항
Diffstat (limited to 'components/data-table/data-table-pagination.tsx')
| -rw-r--r-- | components/data-table/data-table-pagination.tsx | 219 |
1 files changed, 70 insertions, 149 deletions
diff --git a/components/data-table/data-table-pagination.tsx b/components/data-table/data-table-pagination.tsx index 922dacf1..4ed63a1b 100644 --- a/components/data-table/data-table-pagination.tsx +++ b/components/data-table/data-table-pagination.tsx @@ -7,7 +7,6 @@ import { ChevronRight, ChevronsLeft, ChevronsRight, - Infinity, } from "lucide-react" import { Button } from "@/components/ui/button" @@ -22,99 +21,57 @@ import { interface DataTablePaginationProps<TData> { table: Table<TData> pageSizeOptions?: Array<number | "All"> - // 무한 스크롤 관련 props - infiniteScroll?: { - enabled: boolean - hasNextPage: boolean - isLoadingMore: boolean - totalCount?: number | null - onLoadMore?: () => void - } - // 페이지 크기 변경 콜백 (필수!) - onPageSizeChange?: (pageSize: number) => void } export function DataTablePagination<TData>({ table, pageSizeOptions = [10, 20, 30, 40, 50, "All"], - infiniteScroll, - onPageSizeChange, }: DataTablePaginationProps<TData>) { // 현재 테이블 pageSize const currentPageSize = table.getState().pagination.pageSize - const isInfiniteMode = infiniteScroll?.enabled || currentPageSize >= 1_000_000 - // "All"을 1,000,000으로 처리하고, 무한 스크롤 모드 표시 - const selectValue = isInfiniteMode ? "All" : String(currentPageSize) - - const handlePageSizeChange = (value: string) => { - if (!onPageSizeChange) { - console.warn('DataTablePagination: onPageSizeChange prop is required for page size changes to work') - return - } - - if (value === "All") { - // "All" 선택 시 무한 스크롤 모드로 전환 - onPageSizeChange(1_000_000) // URL 상태 업데이트만 수행 - } else { - const newSize = Number(value) - onPageSizeChange(newSize) // URL 상태 업데이트만 수행 - } - - // table.setPageSize()는 호출하지 않음! - // URL 상태 변경이 테이블 상태로 자동 반영됨 - } + // "All"을 1,000,000으로 처리할 것이므로, + // 만약 현재 pageSize가 1,000,000이면 화면상 "All"로 표시 + const selectValue = + currentPageSize === 1_000_000 + ? "All" + : String(currentPageSize) return ( <div className="flex w-full flex-col-reverse items-center justify-between gap-4 overflow-auto p-1 sm:flex-row sm:gap-8"> - {/* 선택된 행 및 총 개수 정보 */} <div className="flex-1 whitespace-nowrap text-sm text-muted-foreground"> {table.getFilteredSelectedRowModel().rows.length} of{" "} - {isInfiniteMode ? ( - // 무한 스크롤 모드일 때 - <> - {table.getRowModel().rows.length} row(s) selected. - {infiniteScroll?.totalCount !== null && ( - <span className="ml-4"> - Total: {infiniteScroll.totalCount?.toLocaleString()} records - <span className="ml-2 text-xs"> - ({table.getRowModel().rows.length.toLocaleString()} loaded) - </span> - </span> - )} - </> - ) : ( - // 페이지네이션 모드일 때 - <> - {table.getFilteredRowModel().rows.length} row(s) selected. - <span className="ml-4">Total: {table.getRowCount()} records</span> - </> - )} + {table.getFilteredRowModel().rows.length} row(s) selected. + <span className="ml-4">Total: {table.getRowCount()} records</span> </div> - <div className="flex flex-col-reverse items-center gap-4 sm:flex-row sm:gap-6 lg:gap-8"> {/* Rows per page Select */} <div className="flex items-center space-x-2"> - <p className="whitespace-nowrap text-sm font-medium"> - {isInfiniteMode ? "View mode" : "Rows per page"} - </p> - <Select value={selectValue} onValueChange={handlePageSizeChange}> + <p className="whitespace-nowrap text-sm font-medium">Rows per page</p> + <Select + value={selectValue} + onValueChange={(value) => { + if (value === "All") { + // "All"을 1,000,000으로 치환 + table.setPageSize(1_000_000) + } else { + table.setPageSize(Number(value)) + } + }} + > <SelectTrigger className="h-8 w-[4.5rem]"> <SelectValue placeholder={selectValue} /> </SelectTrigger> <SelectContent side="top"> {pageSizeOptions.map((option) => { + // 화면에 표시할 라벨 const label = option === "All" ? "All" : String(option) + // value도 문자열화 const val = option === "All" ? "All" : String(option) return ( <SelectItem key={val} value={val}> - <div className="flex items-center space-x-2"> - {option === "All" && ( - <Infinity className="h-3 w-3 text-muted-foreground" /> - )} - <span>{label}</span> - </div> + {label} </SelectItem> ) })} @@ -122,90 +79,54 @@ export function DataTablePagination<TData>({ </Select> </div> - {/* 페이지네이션 모드일 때만 페이지 정보 표시 */} - {!isInfiniteMode && ( - <> - {/* 현재 페이지 / 전체 페이지 */} - <div className="flex items-center justify-center text-sm font-medium"> - Page {table.getState().pagination.pageIndex + 1} of{" "} - {table.getPageCount()} - </div> - - {/* 페이지 이동 버튼 */} - <div className="flex items-center space-x-2"> - <Button - aria-label="Go to first page" - variant="outline" - className="hidden size-8 p-0 lg:flex" - onClick={() => table.setPageIndex(0)} - disabled={!table.getCanPreviousPage()} - > - <ChevronsLeft className="size-4" aria-hidden="true" /> - </Button> - <Button - aria-label="Go to previous page" - variant="outline" - size="icon" - className="size-8" - onClick={() => table.previousPage()} - disabled={!table.getCanPreviousPage()} - > - <ChevronLeft className="size-4" aria-hidden="true" /> - </Button> - <Button - aria-label="Go to next page" - variant="outline" - size="icon" - className="size-8" - onClick={() => table.nextPage()} - disabled={!table.getCanNextPage()} - > - <ChevronRight className="size-4" aria-hidden="true" /> - </Button> - <Button - aria-label="Go to last page" - variant="outline" - size="icon" - className="hidden size-8 lg:flex" - onClick={() => table.setPageIndex(table.getPageCount() - 1)} - disabled={!table.getCanNextPage()} - > - <ChevronsRight className="size-4" aria-hidden="true" /> - </Button> - </div> - </> - )} + {/* 현재 페이지 / 전체 페이지 */} + <div className="flex items-center justify-center text-sm font-medium"> + Page {table.getState().pagination.pageIndex + 1} of{" "} + {table.getPageCount()} + </div> - {/* 무한 스크롤 모드일 때 로드 더 버튼 */} - {isInfiniteMode && infiniteScroll && ( - <div className="flex items-center space-x-2"> - {infiniteScroll.hasNextPage && ( - <Button - variant="outline" - size="sm" - onClick={infiniteScroll.onLoadMore} - disabled={infiniteScroll.isLoadingMore} - > - {infiniteScroll.isLoadingMore ? ( - <> - <div className="mr-2 h-3 w-3 animate-spin rounded-full border-2 border-current border-t-transparent" /> - Loading... - </> - ) : ( - <> - <ChevronRight className="mr-2 h-3 w-3" /> - Load More - </> - )} - </Button> - )} - {!infiniteScroll.hasNextPage && table.getRowModel().rows.length > 0 && ( - <span className="text-xs text-muted-foreground"> - All data loaded - </span> - )} - </div> - )} + {/* 페이지 이동 버튼 */} + <div className="flex items-center space-x-2"> + <Button + aria-label="Go to first page" + variant="outline" + className="hidden size-8 p-0 lg:flex" + onClick={() => table.setPageIndex(0)} + disabled={!table.getCanPreviousPage()} + > + <ChevronsLeft className="size-4" aria-hidden="true" /> + </Button> + <Button + aria-label="Go to previous page" + variant="outline" + size="icon" + className="size-8" + onClick={() => table.previousPage()} + disabled={!table.getCanPreviousPage()} + > + <ChevronLeft className="size-4" aria-hidden="true" /> + </Button> + <Button + aria-label="Go to next page" + variant="outline" + size="icon" + className="size-8" + onClick={() => table.nextPage()} + disabled={!table.getCanNextPage()} + > + <ChevronRight className="size-4" aria-hidden="true" /> + </Button> + <Button + aria-label="Go to last page" + variant="outline" + size="icon" + className="hidden size-8 lg:flex" + onClick={() => table.setPageIndex(table.getPageCount() - 1)} + disabled={!table.getCanNextPage()} + > + <ChevronsRight className="size-4" aria-hidden="true" /> + </Button> + </div> </div> </div> ) |
