feat(Tables): implement pagination and loading state handling across multiple tables

- Added `getPaginatedRowNumber` utility function to calculate the correct row number based on pagination.
- Integrated `isLoading` prop in `EmptyListWrapper` to conditionally render loading state.
- Updated various table components (Admins, CMS, Companies, Inquiries, etc.) to utilize the new pagination logic and loading state handling.
- Wrapped pagination components in `IsVisible` to conditionally display based on data availability.
This commit is contained in:
AmirReza Jamali
2026-04-15 15:57:36 +03:30
parent 2e3b721585
commit c1b6b4ccf1
16 changed files with 149 additions and 65 deletions
+6
View File
@@ -6,6 +6,7 @@ interface EmptyListWrapperProps<T> {
emptyMessage: string; emptyMessage: string;
columns: string[]; columns: string[];
children: ReactNode; children: ReactNode;
isLoading?: boolean;
} }
function EmptyListWrapper<T>({ function EmptyListWrapper<T>({
@@ -13,7 +14,12 @@ function EmptyListWrapper<T>({
emptyMessage, emptyMessage,
columns, columns,
children, children,
isLoading = false,
}: EmptyListWrapperProps<T>) { }: EmptyListWrapperProps<T>) {
if (isLoading) {
return null;
}
if (!list.length) { if (!list.length) {
return ( return (
<TableRow> <TableRow>
+2 -1
View File
@@ -17,6 +17,7 @@ import {
import TableSkeleton from "@/components/ui/TableSkeleton"; import TableSkeleton from "@/components/ui/TableSkeleton";
import { AdminStatus } from "@/constants/enums"; import { AdminStatus } from "@/constants/enums";
import { _TooltipDefaultParams } from "@/constants/tooltip"; import { _TooltipDefaultParams } from "@/constants/tooltip";
import { getPaginatedRowNumber } from "@/utils/shared";
import { Tooltip } from "react-tooltip"; import { Tooltip } from "react-tooltip";
import AdminListFilters from "./AdminListFilters"; import AdminListFilters from "./AdminListFilters";
import ChangeStatusModalContent from "./ChangeStatusModalContent"; import ChangeStatusModalContent from "./ChangeStatusModalContent";
@@ -77,7 +78,7 @@ const AdminsTable = () => {
className="odd:bg-gray-2 dark:odd:bg-gray-7" className="odd:bg-gray-2 dark:odd:bg-gray-7"
> >
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{index + 1} {getPaginatedRowNumber({ index })}
</TableCell> </TableCell>
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{item?.full_name} {item?.full_name}
+6 -2
View File
@@ -7,7 +7,7 @@ import Modal from "@/components/ui/modal";
import { Table, TableBody, TableCell, TableHead } from "@/components/ui/table"; import { Table, TableBody, TableCell, TableHead } from "@/components/ui/table";
import TableSkeleton from "@/components/ui/TableSkeleton"; import TableSkeleton from "@/components/ui/TableSkeleton";
import { _TooltipDefaultParams } from "@/constants/tooltip"; import { _TooltipDefaultParams } from "@/constants/tooltip";
import { unixToDate } from "@/utils/shared"; import { getPaginatedRowNumber, unixToDate } from "@/utils/shared";
import { Tooltip } from "react-tooltip"; import { Tooltip } from "react-tooltip";
import { TableHeader, TableRow } from "../../ui/table"; import { TableHeader, TableRow } from "../../ui/table";
import CmsListFilters from "./CmsListFilters"; import CmsListFilters from "./CmsListFilters";
@@ -60,7 +60,11 @@ const CmsTable = () => {
className="odd:bg-gray-2 dark:odd:bg-gray-7" className="odd:bg-gray-2 dark:odd:bg-gray-7"
> >
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{index + 1} {getPaginatedRowNumber({
index,
page: data?.meta?.page,
limit: data?.meta?.limit,
})}
</TableCell> </TableCell>
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{item.key} {item.key}
@@ -14,7 +14,7 @@ import {
} from "@/components/ui/table"; } from "@/components/ui/table";
import TableSkeleton from "@/components/ui/TableSkeleton"; import TableSkeleton from "@/components/ui/TableSkeleton";
import { _TooltipDefaultParams } from "@/constants/tooltip"; import { _TooltipDefaultParams } from "@/constants/tooltip";
import { unixToDate } from "@/utils/shared"; import { getPaginatedRowNumber, unixToDate } from "@/utils/shared";
import { Tooltip } from "react-tooltip"; import { Tooltip } from "react-tooltip";
import { Skeleton } from "../../../ui/skeleton"; import { Skeleton } from "../../../ui/skeleton";
import useCompanyCategoriesPresenter from "./useCompanyCategoriesPresenter"; import useCompanyCategoriesPresenter from "./useCompanyCategoriesPresenter";
@@ -83,7 +83,9 @@ const CompanyCategoriesTable = () => {
key={category.id} key={category.id}
className="odd:bg-gray-2 dark:odd:bg-gray-7" className="odd:bg-gray-2 dark:odd:bg-gray-7"
> >
<TableCell colSpan={100}>{index + 1}</TableCell> <TableCell colSpan={100}>
{getPaginatedRowNumber({ index })}
</TableCell>
<TableCell colSpan={100}>{category.name}</TableCell> <TableCell colSpan={100}>{category.name}</TableCell>
<TableCell colSpan={100}>{category.description}</TableCell> <TableCell colSpan={100}>{category.description}</TableCell>
<TableCell colSpan={100}> <TableCell colSpan={100}>
+2 -2
View File
@@ -17,7 +17,7 @@ import {
} from "@/components/ui/table"; } from "@/components/ui/table";
import TableSkeleton from "@/components/ui/TableSkeleton"; import TableSkeleton from "@/components/ui/TableSkeleton";
import { _TooltipDefaultParams } from "@/constants/tooltip"; import { _TooltipDefaultParams } from "@/constants/tooltip";
import { formatPhoneNumber } from "@/utils/shared"; import { formatPhoneNumber, getPaginatedRowNumber } from "@/utils/shared";
import { Tooltip } from "react-tooltip"; import { Tooltip } from "react-tooltip";
import { useCompanyListPresenter } from "./useCompanyListPresenter"; import { useCompanyListPresenter } from "./useCompanyListPresenter";
import ListHeader from "@/components/ui/ListHeader"; import ListHeader from "@/components/ui/ListHeader";
@@ -81,7 +81,7 @@ const CompaniesTable = () => {
className="odd:bg-gray-2 dark:odd:bg-gray-7" className="odd:bg-gray-2 dark:odd:bg-gray-7"
> >
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{index + 1} {getPaginatedRowNumber({ index })}
</TableCell> </TableCell>
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{company.name} {company.name}
+2 -2
View File
@@ -12,7 +12,7 @@ import {
} from "@/components/ui/table"; } from "@/components/ui/table";
import TableSkeleton from "@/components/ui/TableSkeleton"; import TableSkeleton from "@/components/ui/TableSkeleton";
import { _TooltipDefaultParams } from "@/constants/tooltip"; import { _TooltipDefaultParams } from "@/constants/tooltip";
import { unixToDate } from "@/utils/shared"; import { getPaginatedRowNumber, unixToDate } from "@/utils/shared";
import { Tooltip } from "react-tooltip"; import { Tooltip } from "react-tooltip";
import { useContactUsListPresenter } from "./useContactUsListPresenter"; import { useContactUsListPresenter } from "./useContactUsListPresenter";
@@ -58,7 +58,7 @@ const ContactUsTable = () => {
className="odd:bg-gray-2 dark:odd:bg-gray-7" className="odd:bg-gray-2 dark:odd:bg-gray-7"
> >
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{index + 1} {getPaginatedRowNumber({ index })}
</TableCell> </TableCell>
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{item?.full_name} {item?.full_name}
+14 -2
View File
@@ -3,6 +3,7 @@ import { ExclamationIcon, PencilSquareIcon, TrashIcon } from "@/assets/icons";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper"; import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import { Building } from "@/components/Layouts/sidebar/icons"; import { Building } from "@/components/Layouts/sidebar/icons";
import ConfirmationModal from "@/components/ui/ConfirmationModal"; import ConfirmationModal from "@/components/ui/ConfirmationModal";
import IsVisible from "@/components/ui/IsVisible";
import ListHeader from "@/components/ui/ListHeader"; import ListHeader from "@/components/ui/ListHeader";
import Modal from "@/components/ui/modal"; import Modal from "@/components/ui/modal";
import Pagination from "@/components/ui/pagination"; import Pagination from "@/components/ui/pagination";
@@ -17,7 +18,7 @@ import {
} from "@/components/ui/table"; } from "@/components/ui/table";
import TableSkeleton from "@/components/ui/TableSkeleton"; import TableSkeleton from "@/components/ui/TableSkeleton";
import { _TooltipDefaultParams } from "@/constants/tooltip"; import { _TooltipDefaultParams } from "@/constants/tooltip";
import { unixToDate } from "@/utils/shared"; import { getPaginatedRowNumber, unixToDate } from "@/utils/shared";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { Tooltip } from "react-tooltip"; import { Tooltip } from "react-tooltip";
import AssignToCompanyModalContent from "./AssignToCompanyModalContent"; import AssignToCompanyModalContent from "./AssignToCompanyModalContent";
@@ -52,7 +53,9 @@ const CustomersTable = () => {
isMutating, isMutating,
setParams, setParams,
assignCompanyCompaniesQuery, assignCompanyCompaniesQuery,
shouldShowPagination,
} = useCustomerListPresenter(); } = useCustomerListPresenter();
return ( return (
<div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card"> <div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card">
<ListHeader <ListHeader
@@ -79,10 +82,17 @@ const CustomersTable = () => {
list={allCustomers ?? []} list={allCustomers ?? []}
columns={columns} columns={columns}
emptyMessage="No Customers were found" emptyMessage="No Customers were found"
isLoading={isPending}
> >
{allCustomers?.map((customer, index) => ( {allCustomers?.map((customer, index) => (
<TableRow key={customer?.id ?? index}> <TableRow key={customer?.id ?? index}>
<TableCell colSpan={100}>{index + 1}</TableCell> <TableCell colSpan={100}>
{getPaginatedRowNumber({
index,
page: metadata?.page,
limit: metadata?.limit,
})}
</TableCell>
<TableCell colSpan={100}>{customer?.full_name}</TableCell> <TableCell colSpan={100}>{customer?.full_name}</TableCell>
<TableCell colSpan={100}>{customer?.email}</TableCell> <TableCell colSpan={100}>{customer?.email}</TableCell>
<TableCell colSpan={100}> <TableCell colSpan={100}>
@@ -174,6 +184,7 @@ const CustomersTable = () => {
</EmptyListWrapper> </EmptyListWrapper>
</TableBody> </TableBody>
</Table> </Table>
<IsVisible condition={shouldShowPagination}>
<Pagination <Pagination
currentPage={metadata?.page ? metadata?.page - 1 : 0} currentPage={metadata?.page ? metadata?.page - 1 : 0}
totalPages={metadata?.pages ?? 1} totalPages={metadata?.pages ?? 1}
@@ -185,6 +196,7 @@ const CustomersTable = () => {
})); }));
}} }}
/> />
</IsVisible>
<Modal <Modal
isOpen={isFilterModalOpen} isOpen={isFilterModalOpen}
onClose={() => setIsFilterModalOpen(false)} onClose={() => setIsFilterModalOpen(false)}
@@ -82,6 +82,9 @@ const useCustomerListPresenter = () => {
}; };
const customers = data?.data?.customers ?? []; const customers = data?.data?.customers ?? [];
const shouldShowPagination =
!isPending && (data?.meta?.pages ?? 1) * (data?.meta?.limit ?? 10) > 10;
return { return {
allCustomers: customers, allCustomers: customers,
metadata: data?.meta, metadata: data?.meta,
@@ -109,6 +112,7 @@ const useCustomerListPresenter = () => {
isMutating, isMutating,
setParams, setParams,
assignCompanyCompaniesQuery, assignCompanyCompaniesQuery,
shouldShowPagination,
}; };
}; };
@@ -10,7 +10,7 @@ import {
} from "@/components/ui/table"; } from "@/components/ui/table";
import TableSkeleton from "@/components/ui/TableSkeleton"; import TableSkeleton from "@/components/ui/TableSkeleton";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { capitalize, unixToDate } from "@/utils/shared"; import { capitalize, getPaginatedRowNumber, unixToDate } from "@/utils/shared";
import { ShowcaseSection } from "@/components/Layouts/showcase-section"; import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import useFeedbackTablePresenter from "./useFeedbackTablePresenter"; import useFeedbackTablePresenter from "./useFeedbackTablePresenter";
@@ -60,7 +60,7 @@ const FeedbackTable = ({ id, paramKey }: IProps) => {
className="odd:bg-gray-2 dark:odd:bg-gray-7" className="odd:bg-gray-2 dark:odd:bg-gray-7"
> >
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{index + 1} {getPaginatedRowNumber({ index })}
</TableCell> </TableCell>
<TableCell className="uppercase" colSpan={100}> <TableCell className="uppercase" colSpan={100}>
{item.feedback_type} {item.feedback_type}
+12 -2
View File
@@ -2,6 +2,7 @@
import { PencilSquareIcon, TrashIcon } from "@/assets/icons"; import { PencilSquareIcon, TrashIcon } from "@/assets/icons";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper"; import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import ConfirmationModal from "@/components/ui/ConfirmationModal"; import ConfirmationModal from "@/components/ui/ConfirmationModal";
import IsVisible from "@/components/ui/IsVisible";
import ListHeader from "@/components/ui/ListHeader"; import ListHeader from "@/components/ui/ListHeader";
import Modal from "@/components/ui/modal"; import Modal from "@/components/ui/modal";
import Pagination from "@/components/ui/pagination"; import Pagination from "@/components/ui/pagination";
@@ -16,7 +17,7 @@ import {
} from "@/components/ui/table"; } from "@/components/ui/table";
import TableSkeleton from "@/components/ui/TableSkeleton"; import TableSkeleton from "@/components/ui/TableSkeleton";
import { _TooltipDefaultParams } from "@/constants/tooltip"; import { _TooltipDefaultParams } from "@/constants/tooltip";
import { formatPhoneNumber, unixToDate } from "@/utils/shared"; import { formatPhoneNumber, getPaginatedRowNumber, unixToDate } from "@/utils/shared";
import { Tooltip } from "react-tooltip"; import { Tooltip } from "react-tooltip";
import ChangeStatusForm from "./ChangeStatusForm"; import ChangeStatusForm from "./ChangeStatusForm";
import InquiriesListFilters from "./InquiriesListFilters"; import InquiriesListFilters from "./InquiriesListFilters";
@@ -45,7 +46,9 @@ const InquiriesTable = () => {
setFilterValue, setFilterValue,
isMutating, isMutating,
setParams, setParams,
shouldShowPagination,
} = useInquiriesListPresenter(); } = useInquiriesListPresenter();
return ( return (
<div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card"> <div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card">
<ListHeader <ListHeader
@@ -68,11 +71,16 @@ const InquiriesTable = () => {
columns={columns} columns={columns}
list={inquiries ?? []} list={inquiries ?? []}
emptyMessage="No Inquiries were found" emptyMessage="No Inquiries were found"
isLoading={isPending}
> >
{inquiries?.map((inquiry, index) => ( {inquiries?.map((inquiry, index) => (
<TableRow key={inquiry?.id ?? index}> <TableRow key={inquiry?.id ?? index}>
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{index + 1} {getPaginatedRowNumber({
index,
page: allInquiries?.meta?.page,
limit: allInquiries?.meta?.limit,
})}
</TableCell> </TableCell>
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{inquiry?.company_name} {inquiry?.company_name}
@@ -146,6 +154,7 @@ const InquiriesTable = () => {
watch={watch} watch={watch}
/> />
</Modal> </Modal>
<IsVisible condition={shouldShowPagination}>
<Pagination <Pagination
currentPage={ currentPage={
allInquiries?.meta?.page ? allInquiries?.meta?.page - 1 : 0 allInquiries?.meta?.page ? allInquiries?.meta?.page - 1 : 0
@@ -159,6 +168,7 @@ const InquiriesTable = () => {
})); }));
}} }}
/> />
</IsVisible>
<Modal <Modal
isOpen={isChangeStatusModalOpen} isOpen={isChangeStatusModalOpen}
onClose={() => setIsChangeStatusModalOpen(false)} onClose={() => setIsChangeStatusModalOpen(false)}
@@ -52,6 +52,8 @@ const useInquiriesListPresenter = () => {
}, [searchParams, filterFormReset]); }, [searchParams, filterFormReset]);
const { data, isPending } = useGetInquiries(params); const { data, isPending } = useGetInquiries(params);
const shouldShowPagination =
!isPending && (data?.meta?.pages ?? 1) * (data?.meta?.limit ?? 10) > 10;
const { mutate } = useDeleteInquiry(() => setIsDeleteModalOpen(false)); const { mutate } = useDeleteInquiry(() => setIsDeleteModalOpen(false));
const { mutate: changeStatus } = const { mutate: changeStatus } =
useChangeInquiryStatus(() => setIsChangeStatusModalOpen(false)); useChangeInquiryStatus(() => setIsChangeStatusModalOpen(false));
@@ -100,6 +102,7 @@ const useInquiriesListPresenter = () => {
setFilterValue, setFilterValue,
isMutating, isMutating,
setParams, setParams,
shouldShowPagination,
}; };
}; };
@@ -2,6 +2,7 @@
import { EyeIcon } from "@/assets/icons"; import { EyeIcon } from "@/assets/icons";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper"; import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import { ShowcaseSection } from "@/components/Layouts/showcase-section"; import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import IsVisible from "@/components/ui/IsVisible";
import Pagination from "@/components/ui/pagination"; import Pagination from "@/components/ui/pagination";
import Status from "@/components/ui/Status"; import Status from "@/components/ui/Status";
import { import {
@@ -14,7 +15,7 @@ import {
} from "@/components/ui/table"; } from "@/components/ui/table";
import TableSkeleton from "@/components/ui/TableSkeleton"; import TableSkeleton from "@/components/ui/TableSkeleton";
import { _TooltipDefaultParams } from "@/constants/tooltip"; import { _TooltipDefaultParams } from "@/constants/tooltip";
import { truncateString, unixToDate } from "@/utils/shared"; import { getPaginatedRowNumber, truncateString, unixToDate } from "@/utils/shared";
import { Tooltip } from "react-tooltip"; import { Tooltip } from "react-tooltip";
import Boolean from "@/components/ui/Boolean"; import Boolean from "@/components/ui/Boolean";
@@ -40,6 +41,7 @@ const NotificationHistoryTable = () => {
watch, watch,
search, search,
isMutating, isMutating,
shouldShowPagination,
} = useNotificationHistoryTablePresenter(); } = useNotificationHistoryTablePresenter();
return ( return (
@@ -65,10 +67,17 @@ const NotificationHistoryTable = () => {
list={notificationHistory ?? []} list={notificationHistory ?? []}
columns={columns} columns={columns}
emptyMessage="No notifications were found" emptyMessage="No notifications were found"
isLoading={isLoading}
> >
{(notificationHistory ?? []).map((item, index) => ( {(notificationHistory ?? []).map((item, index) => (
<TableRow key={item.id}> <TableRow key={item.id}>
<TableCell colSpan={100}>{index + 1}</TableCell> <TableCell colSpan={100}>
{getPaginatedRowNumber({
index,
page: metadata?.page,
limit: metadata?.limit,
})}
</TableCell>
<TableCell colSpan={100}>{item.title}</TableCell> <TableCell colSpan={100}>{item.title}</TableCell>
<TableCell colSpan={100}>{item.event_type}</TableCell> <TableCell colSpan={100}>{item.event_type}</TableCell>
<TableCell colSpan={100}> <TableCell colSpan={100}>
@@ -117,6 +126,7 @@ const NotificationHistoryTable = () => {
</EmptyListWrapper> </EmptyListWrapper>
</TableBody> </TableBody>
</Table> </Table>
<IsVisible condition={shouldShowPagination}>
<Pagination <Pagination
currentPage={metadata?.page ? metadata?.page - 1 : 0} currentPage={metadata?.page ? metadata?.page - 1 : 0}
totalPages={metadata?.pages ?? 1} totalPages={metadata?.pages ?? 1}
@@ -128,6 +138,7 @@ const NotificationHistoryTable = () => {
})); }));
}} }}
/> />
</IsVisible>
</ShowcaseSection> </ShowcaseSection>
<Modal <Modal
isOpen={isFilterModalOpen} isOpen={isFilterModalOpen}
@@ -14,6 +14,8 @@ const useNotificationHistoryTablePresenter = () => {
...apiDefaultParams, ...apiDefaultParams,
}); });
const { data, isLoading } = useGetNotificationHistoryQuery(params); const { data, isLoading } = useGetNotificationHistoryQuery(params);
const shouldShowPagination =
!isLoading && (data?.meta?.pages ?? 1) * (data?.meta?.limit ?? 10) > 10;
const isMutating = useIsMutating(); const isMutating = useIsMutating();
const columns: string[] = [ const columns: string[] = [
"row", "row",
@@ -54,6 +56,7 @@ const useNotificationHistoryTablePresenter = () => {
setIsFilterModalOpen, setIsFilterModalOpen,
isMutating, isMutating,
search, search,
shouldShowPagination,
}; };
}; };
+11 -1
View File
@@ -15,12 +15,14 @@ import useTenderListPresenter from "./useTenderListPresenter";
import { ExclamationIcon, EyeIcon } from "@/assets/icons"; import { ExclamationIcon, EyeIcon } from "@/assets/icons";
import IsVisible from "@/components/ui/IsVisible";
import ListHeader from "@/components/ui/ListHeader"; import ListHeader from "@/components/ui/ListHeader";
import Modal from "@/components/ui/modal"; import Modal from "@/components/ui/modal";
import Pagination from "@/components/ui/pagination"; import Pagination from "@/components/ui/pagination";
import TableSkeleton from "@/components/ui/TableSkeleton"; import TableSkeleton from "@/components/ui/TableSkeleton";
import { _TooltipDefaultParams } from "@/constants/tooltip"; import { _TooltipDefaultParams } from "@/constants/tooltip";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { getPaginatedRowNumber } from "@/utils/shared";
import Link from "next/link"; import Link from "next/link";
import TenderListFilters from "./TenderListFilters"; import TenderListFilters from "./TenderListFilters";
const TendersTable = () => { const TendersTable = () => {
@@ -39,6 +41,7 @@ const TendersTable = () => {
watch, watch,
setFilterValue, setFilterValue,
isMutating, isMutating,
shouldShowPagination,
} = useTenderListPresenter(); } = useTenderListPresenter();
return ( return (
@@ -64,6 +67,7 @@ const TendersTable = () => {
list={allTenders?.data.tenders ?? []} list={allTenders?.data.tenders ?? []}
columns={columns} columns={columns}
emptyMessage="No tenders were found" emptyMessage="No tenders were found"
isLoading={isPending}
> >
{(allTenders?.data.tenders ?? []).map((item, index) => ( {(allTenders?.data.tenders ?? []).map((item, index) => (
<TableRow <TableRow
@@ -71,7 +75,11 @@ const TendersTable = () => {
className="odd:bg-gray-2 dark:odd:bg-gray-7" className="odd:bg-gray-2 dark:odd:bg-gray-7"
> >
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{index + 1} {getPaginatedRowNumber({
index,
page: allTenders?.meta?.page,
limit: allTenders?.meta?.limit,
})}
</TableCell> </TableCell>
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{item.title} {item.title}
@@ -145,6 +153,7 @@ const TendersTable = () => {
watch={watch} watch={watch}
/> />
</Modal> </Modal>
<IsVisible condition={shouldShowPagination}>
<Pagination <Pagination
currentPage={allTenders?.meta?.page ? allTenders?.meta?.page - 1 : 0} currentPage={allTenders?.meta?.page ? allTenders?.meta?.page - 1 : 0}
totalPages={allTenders?.meta?.pages ?? 1} totalPages={allTenders?.meta?.pages ?? 1}
@@ -156,6 +165,7 @@ const TendersTable = () => {
})); }));
}} }}
/> />
</IsVisible>
</div> </div>
); );
}; };
@@ -43,6 +43,8 @@ const useTenderListPresenter = () => {
}, [searchParams, filterFormReset]); }, [searchParams, filterFormReset]);
const { data, error, isPending } = useTendersQuery(params); const { data, error, isPending } = useTendersQuery(params);
const shouldShowPagination =
!isPending && (data?.meta?.pages ?? 1) * (data?.meta?.limit ?? 10) > 10;
const search = (data: any) => { const search = (data: any) => {
const newParams = { ...params, ...data, offset: 0 }; const newParams = { ...params, ...data, offset: 0 };
@@ -82,6 +84,7 @@ const useTenderListPresenter = () => {
watch, watch,
setFilterValue, setFilterValue,
isMutating, isMutating,
shouldShowPagination,
}; };
}; };
+15
View File
@@ -111,3 +111,18 @@ export const deleteEmptyKeys = (obj: Record<string, any>) => {
return newObj; return newObj;
}; };
export const isValidAlpha2CountryCode = (code: string) => /^[A-Za-z]{2}$/.test(code); export const isValidAlpha2CountryCode = (code: string) => /^[A-Za-z]{2}$/.test(code);
export const getPaginatedRowNumber = ({
index,
page = 1,
limit = 10,
}: {
index: number;
page?: number;
limit?: number;
}) => {
const safePage = page > 0 ? page : 1;
const safeLimit = limit > 0 ? limit : 10;
return (safePage - 1) * safeLimit + index + 1;
};