76 lines
2.4 KiB
TypeScript
76 lines
2.4 KiB
TypeScript
"use client"
|
|
|
|
import type { ProjectSlugs } from "@conusai-kit/ui"
|
|
import { describeError, useDataClient } from "@conusai-kit/ui/data"
|
|
import { ResourceList, serviceNotice, useResourceList } from "@conusai-kit/ui/patterns"
|
|
import { type ReactElement, useMemo } from "react"
|
|
import type { DocumentView } from "../contract/index.js"
|
|
|
|
export interface DocumentListLabels {
|
|
readonly caption: string
|
|
readonly empty: string
|
|
readonly title: string
|
|
readonly retentionClass: string
|
|
readonly status: string
|
|
readonly created: string
|
|
/** `Open {title}`: the link's accessible name. */
|
|
readonly open: string
|
|
readonly search: string
|
|
readonly searchSubmit: string
|
|
readonly more: string
|
|
readonly failed: string
|
|
/** The text of each business refusal by problem code (`businessRefusalNotices` of `@conusai-kit/business/refusals`). */
|
|
readonly refusals: Readonly<Record<string, string>>
|
|
}
|
|
|
|
type Page = { rows: DocumentView[]; after?: string | undefined }
|
|
|
|
export function DocumentList({
|
|
slugs,
|
|
seed,
|
|
statuses,
|
|
listHref,
|
|
labels,
|
|
locale,
|
|
}: {
|
|
slugs: ProjectSlugs
|
|
seed: Page
|
|
locale: string
|
|
statuses: Readonly<Record<DocumentView["status"], string>>
|
|
listHref: string
|
|
labels: DocumentListLabels
|
|
}): ReactElement {
|
|
const date = useMemo(() => new Intl.DateTimeFormat(locale, { dateStyle: "medium", timeZone: "UTC" }), [locale])
|
|
const client = useDataClient()
|
|
const { list } = useResourceList<DocumentView>({
|
|
seed,
|
|
rowId: (row) => row.documentId,
|
|
searchLabel: labels.search,
|
|
describeError: (error) =>
|
|
labels.failed.replace("{detail}", serviceNotice(error, labels.refusals)?.text ?? describeError(error)),
|
|
read: async ({ q, after }) =>
|
|
(
|
|
await client.call<Page>("archive.document.list", {
|
|
...slugs,
|
|
...(q ? { q } : {}),
|
|
...(after ? { after } : {}),
|
|
})
|
|
).value,
|
|
})
|
|
return (
|
|
<ResourceList
|
|
{...list}
|
|
label={labels.caption}
|
|
empty={{ title: labels.empty }}
|
|
columns={[
|
|
{ id: "title", header: labels.title, wrap: true },
|
|
{ id: "retentionClass", header: labels.retentionClass },
|
|
{ id: "status", header: labels.status, cell: (row) => statuses[row.status] },
|
|
{ id: "createdAt", header: labels.created, cell: (row) => date.format(new Date(row.createdAt)) },
|
|
]}
|
|
rowHref={(row) => `${listHref}/${encodeURIComponent(row.documentId)}`}
|
|
rowLinkLabel={(row) => labels.open.replace("{title}", row.title)}
|
|
/>
|
|
)
|
|
}
|