ConusAI vendor v0.1.0-beta.114
ci / gate (push) Waiting to run

This commit is contained in:
ConusAI vendor v0.1.0-beta.114
2026-11-14 09:56:45 +00:00
commit 1ce8d23c35
867 changed files with 122104 additions and 0 deletions
+100
View File
@@ -0,0 +1,100 @@
"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<Record<string, string>>
}
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<Record<string, string>>
listHref: string
labels: ReservationListLabels
}): ReactElement {
const list = useRead<Page>("inventory.reservation.list", { ...slugs, status: "open" }, { initial: seed })
const release = useWrite<Record<string, unknown>, 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<ReservationView>[] = [
{ 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 (
<Can permission="inventory.stock.reserve">
<ConfirmDialog
trigger={
<Button variant="outline" size="sm" aria-label={name}>
{labels.releaseShort}
</Button>
}
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()
}}
/>
</Can>
)
},
},
]
return (
<PageSection title={labels.title}>
<ResourceList
label={labels.caption}
columns={columns}
data={list.data?.rows ?? []}
rowId={(row) => 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()}
/>
</PageSection>
)
}