diff --git a/src/features/instance/databases/components/TablePagination.tsx b/src/features/instance/databases/components/TablePagination.tsx new file mode 100644 index 000000000..f57c98c30 --- /dev/null +++ b/src/features/instance/databases/components/TablePagination.tsx @@ -0,0 +1,225 @@ +'use client'; + +import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { addCommasToNumbers } from '@/lib/addCommasToNumbers'; +import { cn } from '@/lib/cn'; +import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'; +import { ComponentProps, Dispatch, FormEvent, SetStateAction, useState } from 'react'; + +const PAGE_SIZE_OPTIONS = [20, 50, 100, 250]; + +interface TablePaginationProps { + pageIndex: number; + pageSize: number; + totalPages?: number; + totalRecords?: number; + setPageIndex: Dispatch>; + setPageSize: Dispatch>; +} + +export function TablePagination( + { pageIndex, pageSize, totalPages, totalRecords, setPageIndex, setPageSize }: TablePaginationProps, +) { + const isLoading = totalPages === undefined || totalRecords === undefined; + const pageCount = totalPages && totalPages > 0 ? totalPages : 1; + const currentPage = pageIndex + 1; + + const canPrevious = pageIndex > 0; + const canNext = !isLoading && currentPage < pageCount; + + const goToPage = (page: number) => { + setPageIndex(Math.max(0, Math.min(page, pageCount) - 1)); + }; + + const changePageSize = (size: number) => { + setPageSize(size); + setPageIndex(0); + }; + + const items = getPaginationItems(currentPage, pageCount); + + return ( +
+
+ {/* Summary — record count is the essential, kept at every width */} +
+ + Page {addCommasToNumbers(currentPage)} of {isLoading ? '…' : addCommasToNumbers(pageCount)} + + + • + + + {isLoading + ? + : <>{addCommasToNumbers(totalRecords)} {totalRecords === 1 ? 'record' : 'records'}} + +
+ +
+ + {/* Navigation — back/forward is the essential, kept at every width */} + + + {/* Keep the nav centered only while the "Go to" field is shown; otherwise pin it right */} +
+ + {/* Rows per page — extra control, only shown when there is ample room */} + + + {/* Go to page — last to appear, first to be dropped */} + +
+
+ ); +} + +function PaginationButton({ + isActive, + className, + ...props +}: ComponentProps<'button'> & { isActive?: boolean }) { + return ( + - -
- -
-
Records
-
- {totalRecords === undefined - ? - : addCommasToNumbers(totalRecords)} -
-
- {totalRecords !== undefined && totalRecords > 0 && ( - <> -
- -
- - {totalPages !== undefined && totalPages > 1 && ( - <> -
-
Pages
-
{addCommasToNumbers(totalPages)}
-
-
-
Page
-
{addCommasToNumbers(pageIndex + 1)}
-
- - )} - - )} - -
- - -
+ ); } @@ -209,8 +134,6 @@ function TableBodyRow( const isExpired = original && original.message === 'This entry has expired'; const visibleCells = row.getVisibleCells(); - console.log('primaryKey, visibleCells', primaryKey, visibleCells); - if (isExpired) { if (visibleCells[0]?.column?.id === primaryKey) { return [