PR: #386: feat(documents): page totals in slice/group summaries + Total-pages field-sum [Story-1535] by @ankitmaheshwari-com
View PR →
Story 1535 ยท EPIC-1489 Documents & Intake ยท APP-2 Page totals

The Record learns to count pages, not just files

The Documents Register already aggregates each slice value and each group header into a small summary: how many files and how big (count + total size). But the question counsel actually asks of a bundle is "how many pages am I about to read?" โ€” a 3-file slice can be 600 pages, and a 40-file slice can be 80. This Story adds page totals alongside count and size in both the slice-navigator and the group headers, and a new Total pages option to the View field-sum control.

๐Ÿ›ฐ๏ธ Satellite โ€” why pages, and why "known so far"

Files and bytes are a proxy for effort; pages are the real unit of legal reading. The register groups and slices the whole corpus (by type, by tag, by Side, by participant), and every bucket already carries a summary. The missing number is pages. The wrinkle: a document's page count is unknown until it is segmented โ€” fresh uploads sit in a processing state with pageCount === null. We must not block the total on a slow pipeline, nor invent a page count. So the rule is: totals are pages known so far โ€” a still-processing doc contributes 0 to the aggregate, and the row itself shows โ€” until it is segmented.

โœˆ๏ธ Airplane โ€” one aggregate, three surfaces, one toggle

The pure engine (view-state.ts) already folds every group and slice bucket into a Summary. We taught that fold one more field and let every existing surface read it:

๐Ÿ”ฌ Microscope โ€” the reducer is the whole change

The fold that makes "known so far" true (view-state.ts)

function addToSummary(summary: Summary, doc: RegisterDocument): void {
  summary.count += 1;
  summary.totalSize += doc.sizeBytes ?? 0;
  // Pages are unknown until a doc is segmented; null contributes 0, so the
  // total is "pages known so far" (the row itself shows "โ€”").
  summary.totalPages += doc.pageCount ?? 0;
}

Because every group, every slice value, and the corpus-wide "All" row all flow through this one reducer (and the parallel slice-bucket loop), the new number is correct everywhere at once โ€” no surface re-implements counting.

The field-sum modes gain one member

export type FieldSumMode = "count" | "size" | "pages" | "both" | "none";

// presentation.ts โ€” summaryParts() now returns a third piece:
case "pages":
  return { count: null, size: null, pages: summary.totalPages };

The components localise the page label through next-intl (DocumentsRegister.summary.pages, an ICU plural) โ€” never a hardcoded word โ€” and the control label (DocumentsRegister.fieldSum.pages โ†’ "Total pages") ships in both en and hi.

What you can do now

SurfaceBeforeAfter (mode = Total pages)
Slice navigator value 5 15.4 MB 142 pages
Group header Bank statement ยท 2 ยท 1.0 MB Bank statement ยท 32 pages
View โ†’ Field sum Count ยท Total size ยท Count + size ยท None Count ยท Total size ยท Total pages ยท Count + size ยท None
A still-processing document (pageCount === null) adds nothing to the total and shows โ€” in its own row โ€” the summary is honest about what is known, and grows as the pipeline indexes more docs.

Acceptance

Files changed

13 file(s), +77 / -30 lines

Path Role + -
messages/en.jsonConfig+2-0
messages/hi.jsonConfig+2-0
src/components/documents/register/presentation.tsComponent+10-6
src/components/documents/register/register-group-header.stories.tsxComponent+3-2
src/components/documents/register/register-group-header.tsxComponent+6-2
src/components/documents/register/register-slice-navigator.stories.tsxComponent+4-1
src/components/documents/register/register-slice-navigator.tsxComponent+9-9
src/components/documents/register/view-popover/view-sub-panel.tsxComponent+1-1
src/lib/documents/register/pagination.test.tsLibrary+3-3
src/lib/documents/register/saved-view.tsLibrary+1-1
src/lib/documents/register/types.tsLibrary+6-2
src/lib/documents/register/view-state.test.tsLibrary+22-1
src/lib/documents/register/view-state.tsLibrary+8-2