@propriety/court-calendar 1.0.195 → 1.0.196

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -274,7 +274,7 @@ If a `cdId` or `ci` value in the URL doesn't match any loaded data, a brief erro
274
274
  | Hook | Description |
275
275
  |------|-------------|
276
276
  | `useCourtDates` | Fetches and caches court dates, negotiations, and collections. Handles polling and optimistic in-memory updates. |
277
- | `useCaseData` | Fetches and caches cases for all court dates. Maintains a `Record<caseKey, Case[]>` memory store. |
277
+ | `useCaseData` | Fetches cases for the loaded court dates into a `Record<caseKey, Case[]>` memory store. Never cached, so a reload always fetches. |
278
278
  | `useCalendarEvents` | Derives FullCalendar event objects and `CalEvent` buckets from court date + case data. Applies filter context. |
279
279
  | `useModalSelection` | Tracks which court date event is selected and manages `openDetailsModal` / `openCreateModal`. |
280
280
  | `useModalState` | Manages form state for Edit/Create modes and `clickedCase` for Case Details mode. |
@@ -288,11 +288,11 @@ If a `cdId` or `ci` value in the URL doesn't match any loaded data, a brief erro
288
288
  |--------|-------------|
289
289
  | `helpers/routing.ts` | `parseCalendarSearchParams`, `serializeCalendarParams`, `buildCalendarRouteParams`, `extractFilterFields`. Pure functions for URL encoding/decoding. |
290
290
  | `helpers/CalEvent.ts` | `buildCalEvents` — derives main, extra-day, and adjournment `CalEvent` buckets from court date + case data. |
291
- | `helpers/cases.ts` | Case fetching (by court date, paginated, search). Settlement and evidence checks. |
291
+ | `helpers/cases.ts` | Case predicates: settled, out for decision, evidence, search match. |
292
292
  | `helpers/courtDates.ts` | `caseKey` (memory-map key), `isVillageDate` (municipality code check), `isCountyCode` (one-letter county code). |
293
293
  | `helpers/documentActions.ts` | Open, download, and print document helpers (used by DocCard). |
294
294
  | `helpers/formatter.ts` | Date formatting for API (`YYYY-MM-DD` or `YYYY-MM-DD HH:mm:00`). Evidence string formatting. |
295
- | `helpers/cache.ts` | Dexie-based IndexedDB caching with TTL. |
295
+ | `helpers/cache.ts` | Dexie-based IndexedDB caching of the court-date lists, with TTL. Cases are not cached. |
296
296
  | `helpers/api/` | Fetch wrappers for each API endpoint group (court dates, cases, munis, people). |
297
297
 
298
298
  ### CalEvent
@@ -454,7 +454,7 @@ All data is fetched from `https://utils.aventine.ai`. Every request requires the
454
454
  | `/court-dates/{id}` | DELETE | Delete a court date |
455
455
  | `/court-dates/{id}/cases` | GET | Fetch cases for a court date |
456
456
  | `/court-cases/search?term=...&page=...` | GET | Search cases (paginated) |
457
- | `/court-cases/filtering?page=...&page_size=...` | GET | List all cases (paginated) |
457
+ | `/court-cases/by-court-dates` | POST | Cases for up to 1000 court dates, `{"ids": [...]}` → `{"cases": {id: [...]}}` |
458
458
  | `/court-cases/snooze/upload/{id}` | GET | Snooze upload deadline by 1 business day |
459
459
  | `/users/all` | GET | Fetch all users |
460
460
  | `/users/hearing-officers` | GET | Fetch hearing officers |
@@ -483,7 +483,7 @@ Publishing is automated via GitHub Actions (`.github/workflows/publish.yml`).
483
483
  ## Known limitations
484
484
 
485
485
  - **Port 8000 only:** The backend API enforces CORS that only allows requests from `localhost:8000`. Applies to the dev server and any locally running consumer.
486
- - **Cache is not invalidated on external changes:** If another user *modifies* a court date, the change won't appear until the local cache expires (1 minute for dates, 2 minutes for cases). A *deletion* does propagate: the poll drops any in-window date the server stops returning, and a save answered with 404 removes the row immediately — which matters because polling is suspended while a modal is open.
486
+ - **Cache is not invalidated on external changes:** If another user *modifies* a court date, the change won't appear until the local cache expires (1 minute for dates). Cases are not cached, but a case edited in another tab shows only after a reload unless the edit changed its date's case count or day. A *deletion* does propagate: the poll drops any in-window date the server stops returning, and a save answered with 404 removes the row immediately — which matters because polling is suspended while a modal is open.
487
487
  - **No pagination for court dates:** `getAllDates` fetches every court date in a single request.
488
488
  - **Single API key:** No built-in token refresh or rotation.
489
489
  - **No error UI for API failures:** Network errors are logged to the console but not surfaced to the user (except for bootstrap errors, which show a brief snackbar).
@@ -1,12 +1,10 @@
1
1
  import { Case } from '../../../types';
2
2
  export declare const DIFF_FIELDS: (keyof Case)[];
3
3
  export declare function fieldDiff(a: Case | undefined, b: Case | undefined, field: keyof Case): boolean;
4
- export declare function CaseComparisonSection({ allIndexNumbers, memById, cacheById, apiById, resolvedCache, loading }: {
4
+ export declare function CaseComparisonSection({ allIndexNumbers, memById, apiById, loading }: {
5
5
  allIndexNumbers: string[];
6
6
  memById: Map<string, Case>;
7
- cacheById: Map<string, Case>;
8
7
  apiById: Map<string, Case>;
9
- resolvedCache: Case[] | null;
10
8
  loading: boolean;
11
9
  }): import("react/jsx-runtime").JSX.Element;
12
10
  export declare function RawDiffSection({ diffCases, memById, apiById }: {
@@ -1,6 +1,4 @@
1
- import { Case, CourtDate } from '../../../types';
2
- export declare function CourtDateSection({ courtDate, cacheCases, resolvedCache }: {
1
+ import { CourtDate } from '../../../types';
2
+ export declare function CourtDateSection({ courtDate }: {
3
3
  courtDate: CourtDate;
4
- cacheCases: Case[] | 'none' | null;
5
- resolvedCache: Case[] | null;
6
4
  }): import("react/jsx-runtime").JSX.Element;
@@ -1,10 +1,8 @@
1
1
  interface LoadingBarProps {
2
2
  isFetchingDates: boolean;
3
3
  isFetchingCases: boolean;
4
- loadedCount: number;
5
- totalCount: number;
6
4
  isSearching?: boolean;
7
5
  isFiltering?: boolean;
8
6
  }
9
- export default function LoadingBar({ isFetchingDates, isFetchingCases, loadedCount, totalCount, isSearching, isFiltering, }: LoadingBarProps): import("react/jsx-runtime").JSX.Element | null;
7
+ export default function LoadingBar({ isFetchingDates, isFetchingCases, isSearching, isFiltering, }: LoadingBarProps): import("react/jsx-runtime").JSX.Element | null;
10
8
  export {};
@@ -6,7 +6,6 @@ export declare const S3_DOCS_URL = "https://aventine-court-docs.s3.amazonaws.com
6
6
  export declare const SETTLED_ACTIONS: string[];
7
7
  export declare const EXCLUDED_USER_NAMES: string[];
8
8
  export declare const PRIMARY_USER_IDS: number[];
9
- export declare const CASES_CACHE_EXPIRY: number;
10
9
  export declare const COURT_DATES_CACHE_EXPIRY: number;
11
10
  export declare const NEGOTIATIONS_CACHE_EXPIRY: number;
12
11
  export declare const COLLECTIONS_CACHE_EXPIRY: number;
@@ -1,7 +1,14 @@
1
1
  import { DateType, CourtDate, Case } from '../../types';
2
2
  export declare function searchByCaseTerm(term: string, apiKey: string): AsyncGenerator<any, void, unknown>;
3
3
  export declare function fetchCasesByCourtDate(id: string, apiKey: string, type?: DateType): Promise<Case[]>;
4
- export declare function fetchAllCasesPaginated(apiKey: string, pageSize?: number, dateFrom?: string): AsyncGenerator<Record<string, Case[]>, void, unknown>;
4
+ /**
5
+ * Cases for many court dates (Court.HearingDates ids) in one request, keyed by CourtDateID. Each case
6
+ * is the thinner bulk shape: the open date's modal needs fetchCasesByCourtDate.
7
+ *
8
+ * Throws on a failed request after reporting it, so the caller can leave those dates unloaded
9
+ * rather than recording them as dates with no cases.
10
+ */
11
+ export declare function fetchCasesForCourtDates(ids: string[], apiKey: string): Promise<Record<string, Case[]>>;
5
12
  export interface SkippedAdjournment {
6
13
  index_number: string | null;
7
14
  /** `ambiguous`, `not_found`, `no_index_number`, or `settled:<determination>` / `settled:SettleDate`. */
@@ -1,19 +1,4 @@
1
- import { Case, CourtDate } from '../types';
2
- export declare function getCasesCache(): Promise<{
3
- [courtDateId: string]: {
4
- data: Case[];
5
- timestamp: number;
6
- };
7
- }>;
8
- export declare function setCasesCache(cache: {
9
- [courtDateId: string]: {
10
- data: Case[];
11
- timestamp: number;
12
- };
13
- }): Promise<void>;
14
- export declare function getCachedCases(courtDateId: string): Promise<Case[] | null>;
15
- export declare function updateCasesCache(courtDateId: string, data: Case[]): Promise<void>;
16
- export declare function removeCasesCache(courtDateId: string): Promise<void>;
1
+ import { CourtDate } from '../types';
17
2
  export declare function clearAllCache(): Promise<void>;
18
3
  export declare function getCourtDatesCache(): Promise<CourtDate[] | null>;
19
4
  export declare function setCourtDatesCache(data: CourtDate[], ttl?: number): Promise<void>;
@@ -1,27 +1,25 @@
1
1
  import { Case, CourtDate } from '../types';
2
2
  /**
3
- * Manages fetching, caching, and in-memory storage of cases for court dates.
3
+ * Manages fetching and in-memory storage of cases for court dates.
4
4
  *
5
- * Uses a three-tier lookup strategy for each court date ID:
6
- * 1. **Memory** – React state already holds the cases; no I/O needed.
7
- * 2. **Cache** – IndexedDB/session cache is checked for any IDs missing from memory.
8
- * 3. **API** – Remaining IDs are fetched; bulk pagination is used when >10 IDs are missing.
9
- *
10
- * State is updated incrementally as each tier resolves so the UI stays responsive.
5
+ * Each court date is served from memory if React state already holds its cases, otherwise from the
6
+ * API: per date for up to BULK_THRESHOLD SCAR dates, one bulk by-ids request above that. The open
7
+ * date always loads per date, because the bulk case is thinner than its modal reads. There is no
8
+ * browser cache: a reload starts from an empty memory, so every reload reaches the API.
11
9
  *
12
10
  * @param apiKey API key forwarded to case fetch helpers.
13
- * @param courtDates Full list of court dates; cases are loaded for every ID in this list.
11
+ * @param courtDates The court dates to load cases for.
14
12
  * @param selectedCourtDate The currently-selected court date; its cases are always force-refreshed
15
- * from the API (bypassing memory and cache) when the selection changes.
13
+ * from the API (bypassing memory) when the selection changes.
16
14
  *
17
15
  * @returns
18
- * - `allCases` – Map of `CourtDateID → Case[]` for all loaded court dates.
19
- * - `selectedCases` – Cases belonging to `selectedCourtDate`.
20
- * - `isFetchingCases` – `true` while any API fetch is in flight.
21
- * - `forceRefreshCases` – Re-fetches every court date from the API (manual refresh).
22
- * - `updateCases` – Optimistically merges a partial cases map into state and cache.
23
- * - `refreshCases` – Silently reconciles one court date with the server after a mutation.
24
- * - `deleteCaseMemoryAndCache` – Removes all cases for a given court date from memory and cache.
16
+ * - `allCases` – Map of `caseKey → Case[]` for all loaded court dates.
17
+ * - `selectedCases` – Cases belonging to `selectedCourtDate`.
18
+ * - `isFetchingCases` – `true` while any non-silent fetch is in flight.
19
+ * - `forceRefreshCases` – Re-fetches every court date from the API (manual refresh).
20
+ * - `updateCases` – Optimistically merges a partial cases map into state.
21
+ * - `refreshCases` – Silently reconciles one court date with the server after a mutation.
22
+ * - `deleteCasesFromMemory` – Removes all cases for a given court date from memory.
25
23
  */
26
24
  export declare function useCaseData({ apiKey, courtDates, selectedCourtDate, }: {
27
25
  apiKey: string;
@@ -32,7 +30,7 @@ export declare function useCaseData({ apiKey, courtDates, selectedCourtDate, }:
32
30
  selectedCases: Case[];
33
31
  isFetchingCases: boolean;
34
32
  forceRefreshCases: () => void;
35
- updateCases: (cases: Record<string, Case[]>) => Promise<void>;
33
+ updateCases: (cases: Record<string, Case[]>) => void;
36
34
  refreshCases: (courtDate: CourtDate) => Promise<void>;
37
- deleteCaseMemoryAndCache: (courtDateID: string) => Promise<void>;
35
+ deleteCasesFromMemory: (courtDateID: string) => void;
38
36
  };