@@ -0,0 +1,75 @@
|
||||
"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)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user