@@ -0,0 +1,96 @@
|
||||
"use client"
|
||||
|
||||
// Adds a party (a person or an organization), then opens it. "This is me" links a person to the
|
||||
// member's own account, so the platform's export or erasure of that member reaches the party.
|
||||
|
||||
import type { ProjectSlugs } from "@conusai-kit/ui"
|
||||
import { describeError, useWrite } from "@conusai-kit/ui/data"
|
||||
import {
|
||||
CheckField,
|
||||
FormLayout,
|
||||
type FormValues,
|
||||
PageSection,
|
||||
SelectField,
|
||||
serviceNotice,
|
||||
TextField,
|
||||
usePageNavigation,
|
||||
} from "@conusai-kit/ui/patterns"
|
||||
import { type ReactElement, useState } from "react"
|
||||
|
||||
export interface PartyFormLabels {
|
||||
readonly heading: string
|
||||
readonly kind: string
|
||||
readonly person: string
|
||||
readonly organization: string
|
||||
readonly displayName: string
|
||||
readonly legalName: string
|
||||
readonly country: string
|
||||
readonly countryHint: string
|
||||
readonly linkSelf: 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 PartyForm({
|
||||
slugs,
|
||||
listHref,
|
||||
labels,
|
||||
}: {
|
||||
slugs: ProjectSlugs
|
||||
listHref: string
|
||||
labels: PartyFormLabels
|
||||
}): ReactElement {
|
||||
const navigation = usePageNavigation()
|
||||
const create = useWrite<Record<string, unknown>, { partyId: string }>("crm.party.create")
|
||||
const [requestId] = useState(() => crypto.randomUUID())
|
||||
const [kind, setKind] = useState("organization")
|
||||
|
||||
const submit = async ({ displayName, legalName, country = "", linkSelf }: FormValues): Promise<void> => {
|
||||
const created = await create.mutate({
|
||||
...slugs,
|
||||
kind,
|
||||
displayName,
|
||||
...(legalName ? { legalName } : {}),
|
||||
country: country.toUpperCase(),
|
||||
...(kind === "person" && linkSelf === "on" ? { linkSelf: true } : {}),
|
||||
requestId,
|
||||
})
|
||||
navigation.navigate(`${listHref}/${encodeURIComponent(created.partyId)}`)
|
||||
}
|
||||
|
||||
return (
|
||||
<PageSection title={labels.heading}>
|
||||
<FormLayout
|
||||
submitLabel={labels.submit}
|
||||
busyLabel={labels.busy}
|
||||
onSubmit={submit}
|
||||
describeError={(error) => serviceNotice(error, labels.refusals)?.text ?? describeError(error)}
|
||||
>
|
||||
<SelectField
|
||||
label={labels.kind}
|
||||
value={kind}
|
||||
onValueChange={setKind}
|
||||
options={[
|
||||
{ value: "organization", label: labels.organization },
|
||||
{ value: "person", label: labels.person },
|
||||
]}
|
||||
/>
|
||||
<TextField name="displayName" label={labels.displayName} required maxLength={300} />
|
||||
<TextField name="legalName" label={labels.legalName} maxLength={300} />
|
||||
<TextField
|
||||
name="country"
|
||||
label={labels.country}
|
||||
description={labels.countryHint}
|
||||
errorMessage={labels.countryHint}
|
||||
required
|
||||
minLength={2}
|
||||
maxLength={2}
|
||||
pattern="[A-Za-z]{2}"
|
||||
/>
|
||||
{kind === "person" ? <CheckField name="linkSelf" label={labels.linkSelf} /> : null}
|
||||
</FormLayout>
|
||||
</PageSection>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user