83 lines
2.6 KiB
TypeScript
83 lines
2.6 KiB
TypeScript
"use client"
|
|
|
|
// Adds an item to the organization's catalogue, then opens its stock page. The service checks the SKU
|
|
// and the unit again and answers a taken SKU as a duplicate, shown here in the kit's words for that refusal.
|
|
|
|
import type { ProjectSlugs } from "@conusai-kit/ui"
|
|
import { describeError, useWrite } from "@conusai-kit/ui/data"
|
|
import {
|
|
FormLayout,
|
|
type FormValues,
|
|
PageSection,
|
|
serviceNotice,
|
|
TextField,
|
|
usePageNavigation,
|
|
} from "@conusai-kit/ui/patterns"
|
|
import type { ReactElement } from "react"
|
|
|
|
export interface ItemFormLabels {
|
|
readonly heading: string
|
|
readonly sku: string
|
|
readonly skuHint: string
|
|
readonly name: string
|
|
readonly unit: string
|
|
readonly unitHint: string
|
|
readonly description: string
|
|
readonly submit: string
|
|
readonly busy: string
|
|
/** The text of each business refusal by problem code (`businessRefusalNotices` of `@conusai-kit/business/refusals`). */
|
|
readonly refusals: Readonly<Record<string, string>>
|
|
}
|
|
|
|
export function ItemForm({
|
|
slugs,
|
|
listHref,
|
|
labels,
|
|
}: {
|
|
slugs: ProjectSlugs
|
|
listHref: string
|
|
labels: ItemFormLabels
|
|
}): ReactElement {
|
|
const navigation = usePageNavigation()
|
|
// No live collection follows a service's rows, so the write resolves with the answer.
|
|
const create = useWrite<Record<string, unknown>, { itemId: string }>("inventory.item.create")
|
|
|
|
const submit = async ({ sku, name, unit, description = "" }: FormValues): Promise<void> => {
|
|
const trimmed = description.trim()
|
|
const created = await create.mutate({ ...slugs, sku, name, unit, ...(trimmed ? { description: trimmed } : {}) })
|
|
navigation.navigate(`${listHref}/${created.itemId}`)
|
|
}
|
|
|
|
return (
|
|
<PageSection title={labels.heading}>
|
|
<FormLayout
|
|
submitLabel={labels.submit}
|
|
busyLabel={labels.busy}
|
|
onSubmit={submit}
|
|
describeError={(error) => serviceNotice(error, labels.refusals)?.text ?? describeError(error)}
|
|
>
|
|
<TextField
|
|
name="sku"
|
|
label={labels.sku}
|
|
description={labels.skuHint}
|
|
errorMessage={labels.skuHint}
|
|
required
|
|
maxLength={64}
|
|
pattern="[A-Za-z0-9][A-Za-z0-9._\-]*"
|
|
/>
|
|
<TextField name="name" label={labels.name} required maxLength={200} />
|
|
<TextField
|
|
name="unit"
|
|
label={labels.unit}
|
|
description={labels.unitHint}
|
|
errorMessage={labels.unitHint}
|
|
required
|
|
maxLength={16}
|
|
pattern="[a-z][a-z0-9_]*"
|
|
/>
|
|
<TextField multiline name="description" label={labels.description} rows={3} maxLength={1000} />
|
|
</FormLayout>
|
|
</PageSection>
|
|
)
|
|
}
|