All files / src/lib pagination.ts

100% Statements 16/16
100% Branches 13/13
100% Functions 4/4
100% Lines 16/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103                                                              7x               7x               22x   22x             22x 13x 10x       22x                             7x       8x                     7x 8x 8x   8x 1x     7x    
// Generic pagination types that can be used across the application
export interface PaginationMeta {
  page: number;
  pageSize: number;
  pageCount: number;
  total: number;
}
 
// Generic paginated response from API
export interface PaginatedApiResponse<T> {
  data: T[];
  meta: {
    pagination: PaginationMeta;
  };
}
 
// Generic paginated result for services
export interface PaginatedResult<T> {
  data: T[];
  pagination: PaginationMeta;
}
 
// Generic pagination parameters interface
export interface PaginationParams {
  page?: number;
  pageSize?: number;
  sort?: string;
  [key: string]: any; // Allow additional filter parameters
}
 
// Pagination configuration constants
export const PAGINATION_DEFAULTS = {
  page: 1,
  pageSize: 10,
  maxPageSize: 100,
  sort: 'createdAt:desc',
} as const;
 
// Query parameter builder for pagination
export const buildPaginationQuery = (
  params: PaginationParams = {}
): URLSearchParams => {
  const {
    page = PAGINATION_DEFAULTS.page,
    pageSize = PAGINATION_DEFAULTS.pageSize,
    sort = PAGINATION_DEFAULTS.sort,
    ...filters
  } = params;
 
  const queryParams = new URLSearchParams({
    page: page.toString(),
    pageSize: pageSize.toString(),
    sort,
  });
 
  // Add filters
  Object.entries(filters).forEach(([key, value]) => {
    if (value !== undefined && value !== '' && value !== null) {
      queryParams.append(key, value.toString());
    }
  });
 
  return queryParams;
};
 
// Generic pagination state for React hooks
export interface PaginationState {
  currentPage: number;
  hasNextPage: boolean;
  hasPreviousPage: boolean;
  isLoading: boolean;
  isLoadingMore: boolean;
  totalItems: number;
  totalPages: number;
}
 
// Pagination navigation helpers
export const getPaginationState = (
  pagination: PaginationMeta,
  isLoading: boolean = false,
  isLoadingMore: boolean = false
): PaginationState => ({
  currentPage: pagination.page,
  hasNextPage: pagination.page < pagination.pageCount,
  hasPreviousPage: pagination.page > 1,
  isLoading,
  isLoadingMore,
  totalItems: pagination.total,
  totalPages: pagination.pageCount,
});
 
// Pagination info text generator
export const getPaginationInfo = (pagination: PaginationMeta): string => {
  const start = (pagination.page - 1) * pagination.pageSize + 1;
  const end = Math.min(pagination.page * pagination.pageSize, pagination.total);
 
  if (pagination.total === 0) {
    return 'No items found';
  }
 
  return `Showing ${start}-${end} of ${pagination.total} items`;
};