69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
"use client"
|
|
|
|
// The organization's parties, a page at a time. The server renders the first page (`seed`); a search
|
|
// and "Show more" are reads made on a person's action, through the page's data client.
|
|
|
|
import type { ProjectSlugs } from "@conusai-kit/ui"
|
|
import { useDataClient } from "@conusai-kit/ui/data"
|
|
import { type ResourceColumn, ResourceList, useResourceList } from "@conusai-kit/ui/patterns"
|
|
import type { ReactElement } from "react"
|
|
import type { PartyView } from "../contract/index.js"
|
|
|
|
export interface PartyListLabels {
|
|
readonly caption: string
|
|
readonly empty: string
|
|
readonly name: string
|
|
readonly kind: string
|
|
readonly country: string
|
|
readonly person: string
|
|
readonly organization: string
|
|
/** `Open {name}`: the link's accessible name. */
|
|
readonly open: string
|
|
readonly search: string
|
|
}
|
|
|
|
type Page = { rows: PartyView[]; after?: string | undefined }
|
|
|
|
export function PartyList({
|
|
slugs,
|
|
seed,
|
|
listHref,
|
|
labels,
|
|
}: {
|
|
slugs: ProjectSlugs
|
|
seed: Page
|
|
listHref: string
|
|
labels: PartyListLabels
|
|
}): ReactElement {
|
|
const client = useDataClient()
|
|
const { list } = useResourceList<PartyView>({
|
|
seed,
|
|
rowId: (party) => party.partyId,
|
|
searchLabel: labels.search,
|
|
read: async ({ q, after }) => {
|
|
const input = { ...slugs, ...(q ? { q } : {}), ...(after ? { after } : {}) }
|
|
return (await client.call<Page>("crm.party.list", input)).value
|
|
},
|
|
})
|
|
const columns: ResourceColumn<PartyView>[] = [
|
|
{ id: "displayName", header: labels.name, wrap: true, minWidth: "10rem" },
|
|
{
|
|
id: "kind",
|
|
header: labels.kind,
|
|
cell: (party) => (party.kind === "person" ? labels.person : labels.organization),
|
|
},
|
|
{ id: "country", header: labels.country },
|
|
]
|
|
return (
|
|
<ResourceList
|
|
{...list}
|
|
label={labels.caption}
|
|
columns={columns}
|
|
rowHref={(party) => `${listHref}/${encodeURIComponent(party.partyId)}`}
|
|
rowLinkLabel={(party) => labels.open.replace("{name}", party.displayName)}
|
|
rowLabel={(party) => party.displayName}
|
|
empty={{ title: labels.empty }}
|
|
/>
|
|
)
|
|
}
|