This commit is contained in:
@@ -5,7 +5,6 @@ import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
|
||||
import IsVisible from "@/components/ui/IsVisible";
|
||||
import ListHeader from "@/components/ui/ListHeader";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
import Pagination from "@/components/ui/pagination";
|
||||
import Status from "@/components/ui/Status";
|
||||
import {
|
||||
Table,
|
||||
@@ -49,7 +48,8 @@ const TendersTable = () => {
|
||||
navigateToTenderDetails,
|
||||
navigateToTenderFeedback,
|
||||
handlePaginationChange,
|
||||
buildWindowedPageLabel,
|
||||
hasNext,
|
||||
hasPrevious,
|
||||
getRowNumber,
|
||||
formatDateTimeCell,
|
||||
pagination,
|
||||
@@ -204,16 +204,37 @@ const TendersTable = () => {
|
||||
/>
|
||||
</div>
|
||||
<IsVisible condition={shouldShowPagination}>
|
||||
<Pagination
|
||||
key={`pagination-tenders-${absoluteCurrentPage}`}
|
||||
currentPage={pagination.currentPage}
|
||||
totalPages={pagination.totalPages}
|
||||
onPageChange={handlePaginationChange}
|
||||
pageRangeDisplayed={3}
|
||||
marginPagesDisplayed={1}
|
||||
pageLabelBuilder={buildWindowedPageLabel}
|
||||
variant="tenders"
|
||||
/>
|
||||
<nav
|
||||
className="mt-2 flex w-full items-center justify-center gap-3 text-sm"
|
||||
aria-label="Tender pagination"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
disabled={!hasPrevious}
|
||||
onClick={() =>
|
||||
handlePaginationChange({ selected: absoluteCurrentPage - 1 })
|
||||
}
|
||||
className="shadow-theme-xs rounded-xl border border-stroke/80 bg-white/70 px-4 py-2 font-semibold text-dark transition hover:border-primary/35 hover:text-primary disabled:cursor-not-allowed disabled:opacity-40 dark:border-dark-3 dark:bg-dark-2/70 dark:text-white"
|
||||
>
|
||||
Previous
|
||||
</button>
|
||||
<span
|
||||
className="text-gray-600 dark:text-gray-300"
|
||||
aria-current="page"
|
||||
>
|
||||
Page {pagination.currentPage + 1}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
disabled={!hasNext}
|
||||
onClick={() =>
|
||||
handlePaginationChange({ selected: absoluteCurrentPage + 1 })
|
||||
}
|
||||
className="shadow-theme-xs rounded-xl border border-stroke/80 bg-white/70 px-4 py-2 font-semibold text-dark transition hover:border-primary/35 hover:text-primary disabled:cursor-not-allowed disabled:opacity-40 dark:border-dark-3 dark:bg-dark-2/70 dark:text-white"
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</nav>
|
||||
</IsVisible>
|
||||
</ListWrapper>
|
||||
);
|
||||
|
||||
@@ -8,14 +8,20 @@ import { TCustomer } from "@/lib/api";
|
||||
import {
|
||||
buildQueryString,
|
||||
deleteEmptyKeys,
|
||||
getPaginatedRowNumber,
|
||||
isDateRangeActive,
|
||||
unixToDate,
|
||||
} from "@/utils/shared";
|
||||
import gsap from "gsap";
|
||||
import { useIsMutating } from "@tanstack/react-query";
|
||||
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
||||
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
const COMMA_SEPARATED_FILTER_KEYS = new Set([
|
||||
@@ -356,11 +362,10 @@ const useTenderListPresenter = () => {
|
||||
useEffect(() => {
|
||||
const newParams: Record<string, any> = {
|
||||
...apiDefaultParams,
|
||||
offset: 0,
|
||||
limit: 10,
|
||||
limit: 20,
|
||||
};
|
||||
for (const key of searchParams.keys()) {
|
||||
if (key === "cpv_codes") {
|
||||
if (key === "cpv_codes" || key === "include_total" || key === "cursor") {
|
||||
continue;
|
||||
}
|
||||
newParams[key] = searchParams.get(key);
|
||||
@@ -376,53 +381,21 @@ const useTenderListPresenter = () => {
|
||||
|
||||
const { data, error, isPending, isError } = useTendersQuery(params);
|
||||
|
||||
const { pagination, handlePaginationChange, buildFirstPageParams } =
|
||||
useHybridPagination({
|
||||
meta: data?.meta,
|
||||
params,
|
||||
setParams,
|
||||
isError,
|
||||
error,
|
||||
});
|
||||
const {
|
||||
pagination,
|
||||
handlePaginationChange,
|
||||
buildFirstPageParams,
|
||||
hasNext,
|
||||
hasPrevious,
|
||||
} = useHybridPagination({
|
||||
meta: data?.meta,
|
||||
params,
|
||||
setParams,
|
||||
isError,
|
||||
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;
|
||||
const shouldShowPagination = !isPending && (hasPrevious || hasNext);
|
||||
|
||||
const tendersList = data?.data?.tenders ?? [];
|
||||
|
||||
@@ -449,12 +422,11 @@ const useTenderListPresenter = () => {
|
||||
|
||||
const getRowNumber = useCallback(
|
||||
(index: number) =>
|
||||
getPaginatedRowNumber({
|
||||
index,
|
||||
page: data?.meta?.page,
|
||||
limit: data?.meta?.limit,
|
||||
}),
|
||||
[data?.meta?.limit, data?.meta?.page],
|
||||
pagination.currentPage *
|
||||
(data?.meta?.limit ?? Number(params.limit) ?? 20) +
|
||||
index +
|
||||
1,
|
||||
[data?.meta?.limit, pagination.currentPage, params.limit],
|
||||
);
|
||||
|
||||
const formatDateTimeCell = useCallback((unix: number) => {
|
||||
@@ -541,7 +513,7 @@ const useTenderListPresenter = () => {
|
||||
const clearAllFilters = useCallback(() => {
|
||||
const cleared = buildFirstPageParams({
|
||||
...apiDefaultParams,
|
||||
limit: 10,
|
||||
limit: 20,
|
||||
});
|
||||
filterFormReset(mergeTenderFilterFormState(cleared));
|
||||
router.push(pathName);
|
||||
@@ -629,11 +601,12 @@ const useTenderListPresenter = () => {
|
||||
tendersList,
|
||||
navigateToTenderDetails,
|
||||
navigateToTenderFeedback,
|
||||
handlePaginationChange: handleWindowedPaginationChange,
|
||||
buildWindowedPageLabel,
|
||||
handlePaginationChange,
|
||||
hasNext,
|
||||
hasPrevious,
|
||||
getRowNumber,
|
||||
formatDateTimeCell,
|
||||
pagination: windowedPagination,
|
||||
pagination,
|
||||
absoluteCurrentPage: pagination.currentPage,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user