97 lines
3.0 KiB
TypeScript
97 lines
3.0 KiB
TypeScript
"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>
|
|
)
|
|
}
|