import type { WorkOrderDayGroup } from "@/domain/work-orders/types/work-order-table-row"; export const DAY_PAGE_SIZE_OPTIONS = [25, 50, 100, 200] as const; export const DEFAULT_DAY_PAGE_SIZE = 50; export type DayPageSize = (typeof DAY_PAGE_SIZE_OPTIONS)[number]; export type PaginatedSlice = { visible: T[]; pageCount: number; pageIndex: number; }; export function pageIndexForItem(itemIndex: number, pageSize: number): number { if (itemIndex < 0) { return 0; } const size = pageSize > 0 ? pageSize : DEFAULT_DAY_PAGE_SIZE; return Math.floor(itemIndex / size); } export function findItemPageIndex( items: readonly T[], id: string | number, pageSize: number, ): number | null { const index = items.findIndex((item) => String(item.id) === String(id)); if (index < 0) { return null; } return pageIndexForItem(index, pageSize); } export function totalPageCount(totalCount: number, pageSize: number): number { const size = pageSize > 0 ? pageSize : DEFAULT_DAY_PAGE_SIZE; return Math.max(1, Math.ceil(Math.max(0, totalCount) / size) || 1); } export function asDayPageSize(value: number): DayPageSize { return (DAY_PAGE_SIZE_OPTIONS as readonly number[]).includes(value) ? (value as DayPageSize) : DEFAULT_DAY_PAGE_SIZE; } export function paginateItems( items: readonly T[], pageIndex: number, pageSize: number, ): PaginatedSlice { const size = pageSize > 0 ? pageSize : DEFAULT_DAY_PAGE_SIZE; const pageCount = totalPageCount(items.length, size); const page = Math.min(Math.max(0, pageIndex), pageCount - 1); const start = page * size; return { visible: items.slice(start, start + size), pageCount, pageIndex: page, }; } export const SEARCH_PAGER_FOOTER_LABEL = "Results"; export function shouldShowDayPagination(input: { flatListMode: boolean; isLoading: boolean; noSearchResults: boolean; }): boolean { return !input.flatListMode && !input.isLoading && !input.noSearchResults; } export function shouldShowSearchPagination(input: { isLoading: boolean; hasResults: boolean; }): boolean { return !input.isLoading && input.hasResults; } export function resolveSearchPager(input: { page: number; pageSize: number; totalCount: number }): { pageSize: DayPageSize; pageIndex: number; pageCount: number; itemCount: number; } { const pageSize = asDayPageSize(input.pageSize); const pageCount = totalPageCount(input.totalCount, pageSize); return { pageSize, pageIndex: Math.min(Math.max(0, input.page), pageCount - 1), pageCount, itemCount: input.totalCount, }; } export function nextSearchPageIfOutOfRange(input: { page: number; pageSize: number; totalCount: number; }): number | null { if (input.totalCount <= 0) { return null; } const pageCount = totalPageCount(input.totalCount, asDayPageSize(input.pageSize)); if (input.page < pageCount) { return null; } return pageCount - 1; } export function pickBoardPager(input: { advActive: boolean; isLoading: boolean; noSearchResults: boolean; advResultCount: number; search: { page: number; pageSize: number; totalCount: number }; day: { pageSize: DayPageSize; pageIndex: number; pageCount: number; itemCount: number; footerLabel: string; }; }): { show: boolean; pageSize: DayPageSize; pageIndex: number; pageCount: number; itemCount: number; footerLabel: string; } { if (input.advActive) { return { show: shouldShowSearchPagination({ isLoading: input.isLoading, hasResults: input.search.totalCount > 0, }), ...resolveSearchPager(input.search), footerLabel: SEARCH_PAGER_FOOTER_LABEL, }; } return { show: shouldShowDayPagination({ flatListMode: false, isLoading: input.isLoading, noSearchResults: input.noSearchResults, }), ...input.day, }; } export function formatDayPaginationSummary(dayLabel: string, itemCount: number): string { const label = dayLabel.trim().toUpperCase(); const noun = itemCount === 1 ? "item" : "items"; return `${label} ยท ${itemCount} ${noun}`; } export function pageSelectedDayGroups( dayGroups: WorkOrderDayGroup[], pageIndex: number, pageSize: number, ): { groups: WorkOrderDayGroup[]; pageIndex: number; pageCount: number; totalCount: number } { const group = dayGroups[0]; if (!group) { return { groups: dayGroups, pageIndex: 0, pageCount: 1, totalCount: 0 }; } const slice = paginateItems(group.items, pageIndex, pageSize); return { groups: [{ ...group, items: slice.visible, totalCount: group.items.length }], pageIndex: slice.pageIndex, pageCount: slice.pageCount, totalCount: group.items.length, }; }