diff --git a/src/components/Tables/tenders/index.tsx b/src/components/Tables/tenders/index.tsx index 3766c09..c29b5e5 100644 --- a/src/components/Tables/tenders/index.tsx +++ b/src/components/Tables/tenders/index.tsx @@ -42,6 +42,7 @@ const TendersTable = () => { navigateToTenderDetails, navigateToTenderFeedback, handlePaginationChange, + buildWindowedPageLabel, getRowNumber, formatDateTimeCell, pagination, @@ -157,6 +158,9 @@ const TendersTable = () => { currentPage={pagination.currentPage} totalPages={pagination.totalPages} onPageChange={handlePaginationChange} + pageRangeDisplayed={3} + marginPagesDisplayed={1} + pageLabelBuilder={buildWindowedPageLabel} /> diff --git a/src/components/Tables/tenders/useTenderListPresenter.ts b/src/components/Tables/tenders/useTenderListPresenter.ts index 8857abb..8143707 100644 --- a/src/components/Tables/tenders/useTenderListPresenter.ts +++ b/src/components/Tables/tenders/useTenderListPresenter.ts @@ -346,6 +346,42 @@ const useTenderListPresenter = () => { error, }); + const MAX_PAGE_JUMP = 10; + const paginationWindow = useMemo(() => { + const windowStart = Math.max(0, pagination.currentPage - MAX_PAGE_JUMP); + const windowEnd = Math.min( + Math.max(pagination.totalPages - 1, 0), + pagination.currentPage + MAX_PAGE_JUMP, + ); + return { + windowStart, + virtualCurrent: pagination.currentPage - windowStart, + virtualTotal: Math.max(windowEnd - windowStart + 1, 1), + }; + }, [pagination.currentPage, pagination.totalPages]); + + const handleWindowedPaginationChange = useCallback( + (e: { selected: number }) => { + handlePaginationChange({ + selected: e.selected + paginationWindow.windowStart, + }); + }, + [handlePaginationChange, paginationWindow.windowStart], + ); + + const buildWindowedPageLabel = useCallback( + (virtualPage: number) => String(virtualPage + paginationWindow.windowStart), + [paginationWindow.windowStart], + ); + + const windowedPagination = useMemo( + () => ({ + currentPage: paginationWindow.virtualCurrent, + totalPages: paginationWindow.virtualTotal, + }), + [paginationWindow.virtualCurrent, paginationWindow.virtualTotal], + ); + const shouldShowPagination = !isPending && (data?.meta?.pages ?? 1) * (data?.meta?.limit ?? 10) > 10; @@ -498,10 +534,11 @@ const useTenderListPresenter = () => { tendersList, navigateToTenderDetails, navigateToTenderFeedback, - handlePaginationChange, + handlePaginationChange: handleWindowedPaginationChange, + buildWindowedPageLabel, getRowNumber, formatDateTimeCell, - pagination, + pagination: windowedPagination, }; }; diff --git a/src/components/ui/pagination.tsx b/src/components/ui/pagination.tsx index b19a474..e63fd6a 100644 --- a/src/components/ui/pagination.tsx +++ b/src/components/ui/pagination.tsx @@ -4,13 +4,23 @@ interface IProps { currentPage: number; totalPages: number; onPageChange: ReactPaginateProps["onPageChange"]; + pageRangeDisplayed?: number; + marginPagesDisplayed?: number; + pageLabelBuilder?: ReactPaginateProps["pageLabelBuilder"]; } /** Full-cell hit target: styles live on
  • , but react-paginate puts clicks on the inner . */ const pageLinkClassName = "absolute inset-0 z-[1] flex cursor-pointer items-center justify-center select-none"; -const Pagination: FC = ({ totalPages, currentPage, onPageChange }) => { +const Pagination: FC = ({ + totalPages, + currentPage, + onPageChange, + pageRangeDisplayed = 5, + marginPagesDisplayed = 3, + pageLabelBuilder, +}) => { return ( = ({ totalPages, currentPage, onPageChange }) => { forcePage={currentPage} nextLabel="›" previousLabel="‹" - pageRangeDisplayed={5} + pageRangeDisplayed={pageRangeDisplayed} + marginPagesDisplayed={marginPagesDisplayed} + pageLabelBuilder={pageLabelBuilder} activeClassName="flex h-9 min-w-9 items-center justify-center rounded-xl border border-white/35 bg-gradient-to-br from-primary/85 via-primary/75 to-primary/65 px-3 text-sm font-semibold !text-white shadow-theme-xs shadow-primary/20 backdrop-blur-md transition-all duration-300 before:pointer-events-none before:absolute before:inset-x-0 before:top-0 before:h-1/2 before:rounded-t-xl before:bg-gradient-to-b before:from-white/30 before:to-transparent dark:border-white/20 dark:before:from-white/20" onPageChange={(e) => { if (!onPageChange) return;