import { formatDate } from '../dateUtils'; // WHICH PERIOD MY HISTORY IS SPEAKING ABOUT, said on the screen rather than assumed by the reader. // // A populated list with no stated bound reads as "this is everything", and on the feature built for // spotting an access that should not have happened that is the worst thing it could imply. So the line // is always a date: never "the last 90 days" (a count the reader has to convert) and never // "everything" (false on the tabs, which narrow the stream). A sentence, not a date picker: "Show older // activity" widens the window and this line follows it. /** The server's default. Ninety days is a floor on the window, never a ceiling. */ const DEFAULT_WINDOW_DAYS = 90; const DAY_MS = 24 * 60 * 60 * 1000; export interface HistoryWindow { /** True while the server may still have more behind the window. */ mayHaveOlder: boolean; /** The server's cursor: the oldest moment it looked at. */ olderThan?: string; /** The floor the server applied to a default-window search, when it said one. */ earlierThan?: string; /** The earliest row on screen, for a server that sends no cursor. */ oldest: string | undefined; /** Injected so the boundary can be tested rather than depended on. */ now?: Date; } const earlier = (a: string, b: string): string => (new Date(a).getTime() <= new Date(b).getTime() ? a : b); /** The first day of the window the server actually searched. */ export const historyWindowStart = ({ mayHaveOlder, olderThan, earlierThan, oldest, now = new Date() }: HistoryWindow): string => { // The server's own floor when it said one; the client's estimate of it otherwise. const floor = earlierThan ?? new Date(now.getTime() - DEFAULT_WINDOW_DAYS * DAY_MS).toISOString(); // Nothing left behind it: the search reached at least the floor, and further if a row did. if (!mayHaveOlder) return [olderThan, oldest].reduce((start, value) => (value ? earlier(start, value) : start), floor); // More remains: name the oldest loaded row, never the ninety-day floor. Claiming the floor // would say the screen already holds ninety days while Show older is still offered. if (oldest) return oldest; if (olderThan) return olderThan; return floor; }; export const describeHistoryWindow = (window: HistoryWindow): string => `Showing ${formatDate(historyWindowStart(window))} to today.`; // An empty search speaks for the window searched, never for the whole record. export const describeEmptyWindow = (window: HistoryWindow): string => `No activity on your record since ${formatDate(historyWindowStart(window))}.`; /** The door past the default window, offered once that window has nothing further. */ export const SEARCH_EARLIER_LABEL = 'Search earlier activity'; export const describeEarlierDoor = (window: HistoryWindow): string => `Activity before ${formatDate(historyWindowStart(window))} has not been searched.`; // The server has more but gave no cursor past it: stopping here is not the end of the record. export const STALLED_HISTORY_LINE = 'Older activity could not be reached just now, so this is not everything. Try again.';