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