"use client" // The stock this project holds: its open reservations, read again after a release. Releasing is for // whoever holds `inventory.stock.reserve`; the procedure checks again, and a reservation of another // project is not found there. import type { ProjectSlugs } from "@conusai-kit/ui" import { Can, describeError, useRead, useWrite } from "@conusai-kit/ui/data" import { ConfirmDialog, PageSection, type ResourceColumn, ResourceList, serviceNotice } from "@conusai-kit/ui/patterns" import { Button, useUiLabels } from "@conusai-kit/ui/primitives" import type { ReactElement } from "react" import type { ReservationView } from "../contract/index.js" export interface ReservationListLabels { readonly title: string readonly caption: string readonly empty: string readonly item: string readonly quantity: string readonly outstanding: string readonly actions: string /** `Release the stock held of {item}`: the button's accessible name. */ readonly release: string readonly releaseShort: string readonly releasing: string /** What releasing does to the stock held. */ readonly releaseConfirm: string /** The text of each business refusal by problem code (`businessRefusalNotices` of `@conusai-kit/business/refusals`). */ readonly refusals: Readonly> } type Page = { rows: ReservationView[]; after?: string | undefined } export function ReservationList({ slugs, seed, itemLabel, listHref, labels, }: { slugs: ProjectSlugs seed: Page /** What a person reads for an item, by id, for the items the page knows; the id otherwise. */ itemLabel: Readonly> listHref: string labels: ReservationListLabels }): ReactElement { const list = useRead("inventory.reservation.list", { ...slugs, status: "open" }, { initial: seed }) const release = useWrite, ReservationView>("inventory.stock.release") const failed = useUiLabels()?.failed ?? "{detail}" const nameOf = (row: ReservationView): string => itemLabel[row.itemId] ?? row.itemId const describe = (error: unknown): string => serviceNotice(error, labels.refusals)?.text ?? describeError(error) const columns: ResourceColumn[] = [ { id: "itemId", header: labels.item, wrap: true, cell: nameOf }, { id: "quantity", header: labels.quantity, align: "end" }, { id: "outstanding", header: labels.outstanding, align: "end" }, { id: "actions", header: labels.actions, cell: (row) => { const name = labels.release.replace("{item}", nameOf(row)) return ( {labels.releaseShort} } title={name} description={labels.releaseConfirm} confirmLabel={labels.releaseShort} busyLabel={labels.releasing} describeError={describe} onConfirm={async () => { await release.mutate({ ...slugs, reservationId: row.reservationId, requestId: crypto.randomUUID() }) await list.refetch() }} /> ) }, }, ] return ( row.reservationId} rowHref={(row) => `${listHref}/${row.itemId}`} rowLabel={nameOf} empty={{ title: labels.empty }} {...(list.error === undefined ? {} : { error: failed.replace("{detail}", describe(list.error)) })} onRetry={() => void list.refetch()} /> ) }