Files
template-app/modules/documents/ui/document-header.ts
T
2026-11-14 09:56:45 +00:00

62 lines
2.6 KiB
TypeScript

// What a document's page says about the document above its lines: its status, how many lines wait and
// how many are approved, and which pages the extraction left out. The page keeps the document live, so
// these are built wherever it renders -- on the server for the first paint and in the browser on each
// change -- from messages that keep their placeholders (`@conusai-kit/i18n/format`: the language's plural
// rules, and no catalogue).
import { formatMessage } from "@conusai-kit/i18n/format"
import type { PAGE_CLASSES } from "../contract/constants.js"
import type { DocumentView } from "../contract/procedures.js"
import type { DocumentListLabels } from "./document-list.js"
export interface DocumentHeaderLabels {
/** "Status", the word before the status. */
readonly status: string
readonly statuses: DocumentListLabels["statuses"]
readonly failures: DocumentListLabels["failures"]
/** `{count, plural, ...}`, with its placeholder left in. */
readonly pendingCount: string
/** `{count, plural, ...}`, with its placeholder left in. */
readonly approvedCount: string
/** What a document nobody has read yet says. */
readonly waiting: string
readonly skippedTitle: string
/** `Page {page}: {kind}. ...`, with both placeholders left in. */
readonly skippedPage: string
readonly pageClasses: Readonly<Record<(typeof PAGE_CLASSES)[number], string>>
}
export interface DocumentHeader {
readonly status: string
readonly counts: string
readonly waiting?: string
readonly skipped?: {
readonly title: string
readonly pages: readonly { readonly page: number; readonly text: string }[]
}
}
export function documentHeader(document: DocumentView, labels: DocumentHeaderLabels, locale: string): DocumentHeader {
const failure = document.failureCode ? ` ${labels.failures[document.failureCode]}` : ""
return {
status: `${labels.status}: ${labels.statuses[document.status]}${failure}`,
counts: `${formatMessage(labels.pendingCount, { count: document.pending }, locale)}. ${formatMessage(labels.approvedCount, { count: document.approved }, locale)}.`,
...(document.status === "queued" || document.status === "processing" ? { waiting: labels.waiting } : {}),
...(document.skippedPages.length > 0
? {
skipped: {
title: labels.skippedTitle,
pages: document.skippedPages.map((skipped) => ({
page: skipped.page,
text: formatMessage(
labels.skippedPage,
{ page: skipped.page, kind: labels.pageClasses[skipped.pageClass] },
locale,
),
})),
},
}
: {}),
}
}