mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 08:32:54 +00:00
- Added parameter to and for server-side free-text search on contract reference, company name, and booking details. - Introduced new validation errors in for container clashes and space issues when creating bookings. - Implemented paginated dropdown settings retrieval in . - Updated to fetch active yards using a new method that handles pagination. - Enhanced with a method to fetch all records by walking through pages. - Refactored to support filtering and pagination in schedule listings. - Improved to return a paginated list of facilities. - Updated UI components in and to utilize debounced search inputs for better performance. - Added alerts in to inform users about booking constraints related to splits and capacity. - Enhanced to display notifications for split bookings and capacity usage.
86 lines
2.5 KiB
TypeScript
86 lines
2.5 KiB
TypeScript
import { PaginatedResponse, PaginationMeta } from '@edr/types';
|
|
import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
|
|
|
/** Raw page/pageSize as they arrive from a query DTO (both optional). */
|
|
export interface PageRequest {
|
|
page?: number;
|
|
pageSize?: number;
|
|
}
|
|
|
|
export interface PaginationOptions {
|
|
defaultPageSize?: number;
|
|
maxPageSize?: number;
|
|
}
|
|
|
|
export interface NormalizedPage {
|
|
page: number;
|
|
pageSize: number;
|
|
skip: number;
|
|
take: number;
|
|
}
|
|
|
|
const DEFAULT_PAGE_SIZE = 20;
|
|
const MAX_PAGE_SIZE = 100;
|
|
|
|
/** Clamp raw query values into a safe page window (page ≥ 1, pageSize capped). */
|
|
export function normalizePagination(
|
|
request: PageRequest,
|
|
options: PaginationOptions = {},
|
|
): NormalizedPage {
|
|
const defaultPageSize = options.defaultPageSize ?? DEFAULT_PAGE_SIZE;
|
|
const maxPageSize = options.maxPageSize ?? MAX_PAGE_SIZE;
|
|
|
|
const page = Math.max(1, Math.floor(request.page ?? 1) || 1);
|
|
const requested = Math.floor(request.pageSize ?? defaultPageSize) || defaultPageSize;
|
|
const pageSize = Math.min(Math.max(1, requested), maxPageSize);
|
|
|
|
return { page, pageSize, skip: (page - 1) * pageSize, take: pageSize };
|
|
}
|
|
|
|
export function buildPaginationMeta(
|
|
total: number,
|
|
page: number,
|
|
pageSize: number,
|
|
): PaginationMeta {
|
|
const totalPages = pageSize > 0 ? Math.ceil(total / pageSize) : 0;
|
|
return {
|
|
page,
|
|
pageSize,
|
|
total,
|
|
totalPages,
|
|
hasNextPage: page < totalPages,
|
|
hasPreviousPage: page > 1,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Apply skip/take to a query builder, run it, and wrap the result in the
|
|
* shared `PaginatedResponse` envelope. Ordering and filtering must already be
|
|
* applied by the caller.
|
|
*/
|
|
export async function paginateQuery<T extends ObjectLiteral>(
|
|
qb: SelectQueryBuilder<T>,
|
|
request: PageRequest,
|
|
options?: PaginationOptions,
|
|
): Promise<PaginatedResponse<T>> {
|
|
const { page, pageSize, skip, take } = normalizePagination(request, options);
|
|
const [items, total] = await qb.skip(skip).take(take).getManyAndCount();
|
|
return { items, meta: buildPaginationMeta(total, page, pageSize) };
|
|
}
|
|
|
|
/**
|
|
* Paginate an already-materialized array. Prefer `paginateQuery` (DB-level
|
|
* LIMIT/OFFSET); use this only for lists that are inherently in-memory.
|
|
*/
|
|
export function paginateArray<T>(
|
|
rows: readonly T[],
|
|
request: PageRequest,
|
|
options?: PaginationOptions,
|
|
): PaginatedResponse<T> {
|
|
const { page, pageSize, skip } = normalizePagination(request, options);
|
|
return {
|
|
items: rows.slice(skip, skip + pageSize),
|
|
meta: buildPaginationMeta(rows.length, page, pageSize),
|
|
};
|
|
}
|