{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "transfer-note",
  "title": "Transfer Note",
  "description": "A sectioned UK waste transfer note form — parties, waste description with an EWC selector slot, SIC code, quantity and container, transfer details, broker/dealer and signed declarations — plus a read-only TransferNoteSummary card for review states.",
  "dependencies": [
    "@untitledui/icons@^0.0.22"
  ],
  "registryDependencies": [
    "@nx-ui/button",
    "@nx-ui/checkbox",
    "@nx-ui/field",
    "@nx-ui/input",
    "@nx-ui/select",
    "@nx-ui/textarea",
    "@nx-ui/utils"
  ],
  "files": [
    {
      "path": "components/blocks/domain/transfer-note/index.ts",
      "content": "export { TransferNoteForm, type TransferNoteFormProps } from \"./transfer-note-form\"\nexport {\n  TransferNoteSummary,\n  type TransferNoteSummaryProps,\n} from \"./transfer-note-summary\"\nexport {\n  EMPTY_TRANSFER_NOTE,\n  type TransferNoteParty,\n  type TransferNoteValues,\n} from \"./types\"\n",
      "type": "registry:component",
      "target": "components/blocks/domain/transfer-note/index.ts"
    },
    {
      "path": "components/blocks/domain/transfer-note/transfer-note-form.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { Checkbox } from \"@/components/ui/checkbox\"\nimport {\n  Field,\n  FieldDescription,\n  FieldGroup,\n  FieldLabel,\n  FieldLegend,\n  FieldSeparator,\n  FieldSet,\n} from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"@/components/ui/select\"\nimport { Textarea } from \"@/components/ui/textarea\"\n\nimport { EMPTY_TRANSFER_NOTE, type TransferNoteValues, type TransferNoteParty } from \"./types\"\n\nexport interface TransferNoteFormProps {\n  /** Initial values; the form manages its own state from here. */\n  defaultValues?: Partial<TransferNoteValues>\n  onSubmit?: (values: TransferNoteValues) => void\n  /**\n   * Slot rendered in place of the plain EWC code input — pass an EwcSelector\n   * (or any picker) bound to your own state; its value is not merged into\n   * the submitted values unless you also control `defaultValues`.\n   */\n  ewcFieldSlot?: React.ReactNode\n  submitLabel?: string\n  /** Optional extra footer actions rendered before the submit button. */\n  footerSlot?: React.ReactNode\n  disabled?: boolean\n  className?: string\n}\n\nconst QUANTITY_UNITS = [\"tonnes\", \"kilograms\", \"cubic metres\", \"litres\"]\nconst CONTAINER_TYPES = [\"Skip\", \"Loose\", \"Bagged\", \"Drum\", \"Baled\", \"Pallet\"]\n\nfunction RequiredMark() {\n  return (\n    <span aria-hidden=\"true\" className=\"text-text-brand-secondary\">\n      *\n    </span>\n  )\n}\n\nfunction PartyFields({\n  legend,\n  idPrefix,\n  party,\n  licenceLabel,\n  onChange,\n  disabled,\n}: {\n  legend: string\n  idPrefix: string\n  party: TransferNoteParty\n  licenceLabel: string\n  onChange: (party: TransferNoteParty) => void\n  disabled?: boolean\n}) {\n  return (\n    <FieldSet className=\"gap-4\">\n      <FieldLegend>{legend}</FieldLegend>\n      <FieldGroup className=\"gap-4\">\n        <div className=\"grid gap-4 sm:grid-cols-2\">\n          <Field>\n            <FieldLabel htmlFor={`${idPrefix}-name`}>\n              Name <RequiredMark />\n            </FieldLabel>\n            <Input\n              id={`${idPrefix}-name`}\n              value={party.name}\n              disabled={disabled}\n              onChange={(e) => onChange({ ...party, name: e.target.value })}\n              placeholder=\"Organisation or person\"\n            />\n          </Field>\n          <Field>\n            <FieldLabel htmlFor={`${idPrefix}-licence`}>{licenceLabel}</FieldLabel>\n            <Input\n              id={`${idPrefix}-licence`}\n              value={party.licenceNumber}\n              disabled={disabled}\n              onChange={(e) => onChange({ ...party, licenceNumber: e.target.value })}\n              placeholder=\"e.g. CBDU123456\"\n            />\n          </Field>\n        </div>\n        <Field>\n          <FieldLabel htmlFor={`${idPrefix}-address`}>\n            Address <RequiredMark />\n          </FieldLabel>\n          <Input\n            id={`${idPrefix}-address`}\n            value={party.address}\n            disabled={disabled}\n            onChange={(e) => onChange({ ...party, address: e.target.value })}\n            placeholder=\"Site or registered address\"\n          />\n        </Field>\n      </FieldGroup>\n    </FieldSet>\n  )\n}\n\n/**\n * TransferNoteForm — a sectioned UK waste transfer note form: parties, waste\n * description (with a slot for an EWC selector), SIC code, quantity and\n * container, transfer date and place, broker/dealer, and the declaration\n * signature boxes. Purely visual and props-driven — no validation logic\n * beyond required marks.\n */\nexport function TransferNoteForm({\n  defaultValues,\n  onSubmit,\n  ewcFieldSlot,\n  submitLabel = \"Save transfer note\",\n  footerSlot,\n  disabled,\n  className,\n}: TransferNoteFormProps) {\n  const [values, setValues] = React.useState<TransferNoteValues>({\n    ...EMPTY_TRANSFER_NOTE,\n    ...defaultValues,\n  })\n\n  // Scope every field id to this instance so multiple forms on one page\n  // (e.g. an editable and a read-only preview) never collide on ids.\n  const uid = React.useId()\n  const fid = (suffix: string) => `${uid}-${suffix}`\n\n  const set = <K extends keyof TransferNoteValues>(\n    key: K,\n    value: TransferNoteValues[K]\n  ) => setValues((v) => ({ ...v, [key]: value }))\n\n  return (\n    <form\n      className={cn(\n        \"flex flex-col gap-6 rounded-xl border border-border bg-background p-6 shadow-xs\",\n        className\n      )}\n      onSubmit={(e) => {\n        e.preventDefault()\n        onSubmit?.(values)\n      }}\n    >\n      <PartyFields\n        legend=\"Transferor (producer)\"\n        idPrefix={fid(\"producer\")}\n        party={values.producer}\n        licenceLabel=\"Permit / exemption no.\"\n        onChange={(p) => set(\"producer\", p)}\n        disabled={disabled}\n      />\n      <FieldSeparator />\n      <PartyFields\n        legend=\"Carrier\"\n        idPrefix={fid(\"carrier\")}\n        party={values.carrier}\n        licenceLabel=\"Carrier registration no.\"\n        onChange={(p) => set(\"carrier\", p)}\n        disabled={disabled}\n      />\n      <FieldSeparator />\n      <PartyFields\n        legend=\"Transferee (receiver)\"\n        idPrefix={fid(\"receiver\")}\n        party={values.receiver}\n        licenceLabel=\"Permit / exemption no.\"\n        onChange={(p) => set(\"receiver\", p)}\n        disabled={disabled}\n      />\n\n      <FieldSeparator />\n\n      <FieldSet className=\"gap-4\">\n        <FieldLegend>Waste description</FieldLegend>\n        <FieldGroup className=\"gap-4\">\n          <Field>\n            <FieldLabel htmlFor={fid(\"description\")}>\n              Description of the waste <RequiredMark />\n            </FieldLabel>\n            <Textarea\n              id={fid(\"description\")}\n              rows={3}\n              value={values.wasteDescription}\n              disabled={disabled}\n              onChange={(e) => set(\"wasteDescription\", e.target.value)}\n              placeholder=\"e.g. Clean crushed concrete from demolition of a single-storey retail unit\"\n            />\n            <FieldDescription>\n              Enough detail for the receiver to handle the waste safely.\n            </FieldDescription>\n          </Field>\n          <div className=\"grid gap-4 sm:grid-cols-2\">\n            {ewcFieldSlot ?? (\n              <Field>\n                <FieldLabel htmlFor={fid(\"ewc\")}>\n                  EWC code <RequiredMark />\n                </FieldLabel>\n                <Input\n                  id={fid(\"ewc\")}\n                  value={values.ewcCode}\n                  disabled={disabled}\n                  onChange={(e) => set(\"ewcCode\", e.target.value)}\n                  placeholder=\"17 01 01\"\n                  className=\"tabular-nums\"\n                />\n                <FieldDescription>\n                  Six-digit List of Wastes code.\n                </FieldDescription>\n              </Field>\n            )}\n            <Field>\n              <FieldLabel htmlFor={fid(\"sic\")}>SIC code</FieldLabel>\n              <Input\n                id={fid(\"sic\")}\n                value={values.sicCode}\n                disabled={disabled}\n                onChange={(e) => set(\"sicCode\", e.target.value)}\n                placeholder=\"41.20\"\n                className=\"tabular-nums\"\n              />\n              <FieldDescription>\n                Standard Industrial Classification of the transferor.\n              </FieldDescription>\n            </Field>\n          </div>\n          <div className=\"grid gap-4 sm:grid-cols-3\">\n            <Field>\n              <FieldLabel htmlFor={fid(\"quantity\")}>\n                Quantity <RequiredMark />\n              </FieldLabel>\n              <Input\n                id={fid(\"quantity\")}\n                inputMode=\"decimal\"\n                value={values.quantity}\n                disabled={disabled}\n                onChange={(e) => set(\"quantity\", e.target.value)}\n                placeholder=\"12.4\"\n                className=\"tabular-nums\"\n              />\n            </Field>\n            <Field>\n              <FieldLabel htmlFor={fid(\"unit\")}>Unit</FieldLabel>\n              <Select\n                value={values.quantityUnit}\n                onValueChange={(unit) => set(\"quantityUnit\", unit as string)}\n                disabled={disabled}\n              >\n                <SelectTrigger id={fid(\"unit\")} className=\"w-full\">\n                  <SelectValue />\n                </SelectTrigger>\n                <SelectContent>\n                  {QUANTITY_UNITS.map((unit) => (\n                    <SelectItem key={unit} value={unit}>\n                      {unit}\n                    </SelectItem>\n                  ))}\n                </SelectContent>\n              </Select>\n            </Field>\n            <Field>\n              <FieldLabel htmlFor={fid(\"container\")}>Container</FieldLabel>\n              <Select\n                value={values.containerType || null}\n                onValueChange={(c) => set(\"containerType\", c as string)}\n                disabled={disabled}\n              >\n                <SelectTrigger id={fid(\"container\")} className=\"w-full\">\n                  <SelectValue placeholder=\"Select…\" />\n                </SelectTrigger>\n                <SelectContent>\n                  {CONTAINER_TYPES.map((c) => (\n                    <SelectItem key={c} value={c}>\n                      {c}\n                    </SelectItem>\n                  ))}\n                </SelectContent>\n              </Select>\n            </Field>\n          </div>\n        </FieldGroup>\n      </FieldSet>\n\n      <FieldSeparator />\n\n      <FieldSet className=\"gap-4\">\n        <FieldLegend>Transfer</FieldLegend>\n        <div className=\"grid gap-4 sm:grid-cols-2\">\n          <Field>\n            <FieldLabel htmlFor={fid(\"date\")}>\n              Date of transfer <RequiredMark />\n            </FieldLabel>\n            <Input\n              id={fid(\"date\")}\n              type=\"date\"\n              value={values.transferDate}\n              disabled={disabled}\n              onChange={(e) => set(\"transferDate\", e.target.value)}\n            />\n          </Field>\n          <Field>\n            <FieldLabel htmlFor={fid(\"place\")}>\n              Place of transfer <RequiredMark />\n            </FieldLabel>\n            <Input\n              id={fid(\"place\")}\n              value={values.transferPlace}\n              disabled={disabled}\n              onChange={(e) => set(\"transferPlace\", e.target.value)}\n              placeholder=\"e.g. Gate 2, Hollis Yard, Leeds LS10 1AB\"\n            />\n          </Field>\n        </div>\n      </FieldSet>\n\n      <FieldSeparator />\n\n      <FieldSet className=\"gap-4\">\n        <FieldLegend>Broker or dealer</FieldLegend>\n        <FieldDescription>\n          Complete only if a broker or dealer arranged this transfer.\n        </FieldDescription>\n        <div className=\"grid gap-4 sm:grid-cols-2\">\n          <Field>\n            <FieldLabel htmlFor={fid(\"broker-name\")}>Name</FieldLabel>\n            <Input\n              id={fid(\"broker-name\")}\n              value={values.brokerName}\n              disabled={disabled}\n              onChange={(e) => set(\"brokerName\", e.target.value)}\n              placeholder=\"Broker or dealer\"\n            />\n          </Field>\n          <Field>\n            <FieldLabel htmlFor={fid(\"broker-licence\")}>Registration no.</FieldLabel>\n            <Input\n              id={fid(\"broker-licence\")}\n              value={values.brokerLicenceNumber}\n              disabled={disabled}\n              onChange={(e) => set(\"brokerLicenceNumber\", e.target.value)}\n              placeholder=\"e.g. CBDU654321\"\n            />\n          </Field>\n        </div>\n      </FieldSet>\n\n      <FieldSeparator />\n\n      <FieldSet className=\"gap-4\">\n        <FieldLegend>Declarations</FieldLegend>\n        <Field orientation=\"horizontal\">\n          <Checkbox\n            id={fid(\"hierarchy\")}\n            checked={values.hierarchyDeclared}\n            disabled={disabled}\n            onCheckedChange={(checked) => set(\"hierarchyDeclared\", checked === true)}\n          />\n          <FieldLabel htmlFor={fid(\"hierarchy\")} className=\"font-normal\">\n            I confirm the waste hierarchy has been applied, as required by\n            regulation 12 of the Waste (England and Wales) Regulations 2011.{\" \"}\n            <RequiredMark />\n          </FieldLabel>\n        </Field>\n        <div className=\"grid gap-4 sm:grid-cols-2\">\n          <Field>\n            <FieldLabel htmlFor={fid(\"transferor-signature\")}>\n              Transferor — signed (full name) <RequiredMark />\n            </FieldLabel>\n            <Input\n              id={fid(\"transferor-signature\")}\n              value={values.transferorSignature}\n              disabled={disabled}\n              onChange={(e) => set(\"transferorSignature\", e.target.value)}\n              placeholder=\"Full name\"\n            />\n          </Field>\n          <Field>\n            <FieldLabel htmlFor={fid(\"transferee-signature\")}>\n              Transferee — signed (full name) <RequiredMark />\n            </FieldLabel>\n            <Input\n              id={fid(\"transferee-signature\")}\n              value={values.transfereeSignature}\n              disabled={disabled}\n              onChange={(e) => set(\"transfereeSignature\", e.target.value)}\n              placeholder=\"Full name\"\n            />\n          </Field>\n        </div>\n      </FieldSet>\n\n      <div className=\"flex items-center justify-end gap-3 border-t border-border pt-4\">\n        {footerSlot}\n        <Button type=\"submit\" disabled={disabled}>\n          {submitLabel}\n        </Button>\n      </div>\n    </form>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/blocks/domain/transfer-note/transfer-note-form.tsx"
    },
    {
      "path": "components/blocks/domain/transfer-note/transfer-note-summary.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { CheckCircle, File02, MinusCircle } from \"@untitledui/icons\"\n\nimport { cn } from \"@/lib/utils\"\n\nimport type { TransferNoteValues, TransferNoteParty } from \"./types\"\n\nexport interface TransferNoteSummaryProps {\n  values: TransferNoteValues\n  /** Heading shown above the note, e.g. the WTN reference. */\n  title?: string\n  /** Optional status chip content rendered beside the title (e.g. a Badge). */\n  statusSlot?: React.ReactNode\n  className?: string\n}\n\nfunction SummaryRow({ label, value }: { label: string; value?: React.ReactNode }) {\n  return (\n    <div className=\"flex flex-col gap-0.5\">\n      <dt className=\"text-xs text-text-quaternary\">{label}</dt>\n      <dd className=\"text-sm text-text-secondary\">\n        {value || <span className=\"text-text-quaternary\">—</span>}\n      </dd>\n    </div>\n  )\n}\n\nfunction PartySummary({ label, party }: { label: string; party: TransferNoteParty }) {\n  return (\n    <div className=\"flex flex-col gap-0.5 rounded-lg border border-border bg-bg-primary px-3 py-2.5\">\n      <div className=\"text-xs font-medium tracking-wide text-text-quaternary uppercase\">\n        {label}\n      </div>\n      <div className=\"text-sm font-medium text-text-secondary\">\n        {party.name || <span className=\"font-normal text-text-quaternary\">—</span>}\n      </div>\n      {party.address ? (\n        <div className=\"text-xs text-text-tertiary\">{party.address}</div>\n      ) : null}\n      {party.licenceNumber ? (\n        <div className=\"text-xs text-text-tertiary tabular-nums\">\n          {party.licenceNumber}\n        </div>\n      ) : null}\n    </div>\n  )\n}\n\n/**\n * TransferNoteSummary — a read-only review card for a completed waste transfer\n * note: parties, waste description with EWC and SIC codes, quantity, transfer\n * date and place, broker and the signed declarations.\n */\nexport function TransferNoteSummary({\n  values,\n  title = \"Waste transfer note\",\n  statusSlot,\n  className,\n}: TransferNoteSummaryProps) {\n  return (\n    <div\n      className={cn(\n        \"flex flex-col overflow-hidden rounded-xl border border-border bg-background shadow-xs\",\n        className\n      )}\n    >\n      <div className=\"flex items-center justify-between gap-3 border-b border-border px-4 py-3\">\n        <div className=\"flex items-center gap-2\">\n          <File02 className=\"size-5 text-muted-foreground\" aria-hidden=\"true\" />\n          <h3 className=\"text-sm font-semibold text-foreground\">{title}</h3>\n        </div>\n        {statusSlot}\n      </div>\n\n      <div className=\"flex flex-col gap-5 p-4\">\n        <div className=\"grid gap-2 sm:grid-cols-3\">\n          <PartySummary label=\"Transferor\" party={values.producer} />\n          <PartySummary label=\"Carrier\" party={values.carrier} />\n          <PartySummary label=\"Transferee\" party={values.receiver} />\n        </div>\n\n        <dl className=\"grid gap-x-4 gap-y-3 sm:grid-cols-2\">\n          <div className=\"sm:col-span-2\">\n            <SummaryRow label=\"Waste description\" value={values.wasteDescription} />\n          </div>\n          <SummaryRow\n            label=\"EWC code\"\n            value={\n              values.ewcCode ? (\n                <span className=\"font-medium tabular-nums\">{values.ewcCode}</span>\n              ) : undefined\n            }\n          />\n          <SummaryRow\n            label=\"SIC code\"\n            value={\n              values.sicCode ? (\n                <span className=\"tabular-nums\">{values.sicCode}</span>\n              ) : undefined\n            }\n          />\n          <SummaryRow\n            label=\"Quantity\"\n            value={\n              values.quantity\n                ? `${values.quantity} ${values.quantityUnit}`\n                : undefined\n            }\n          />\n          <SummaryRow label=\"Container\" value={values.containerType} />\n          <SummaryRow label=\"Date of transfer\" value={values.transferDate} />\n          <SummaryRow label=\"Place of transfer\" value={values.transferPlace} />\n          {values.brokerName ? (\n            <div className=\"sm:col-span-2\">\n              <SummaryRow\n                label=\"Broker / dealer\"\n                value={\n                  <>\n                    {values.brokerName}\n                    {values.brokerLicenceNumber ? (\n                      <span className=\"text-text-tertiary tabular-nums\">\n                        {\" \"}\n                        · {values.brokerLicenceNumber}\n                      </span>\n                    ) : null}\n                  </>\n                }\n              />\n            </div>\n          ) : null}\n        </dl>\n\n        <div className=\"flex flex-col gap-2 border-t border-border pt-4\">\n          <div className=\"flex items-center gap-2 text-sm\">\n            {values.hierarchyDeclared ? (\n              <CheckCircle\n                className=\"size-4 shrink-0 text-utility-green-600\"\n                aria-hidden=\"true\"\n              />\n            ) : (\n              <MinusCircle\n                className=\"size-4 shrink-0 text-text-quaternary\"\n                aria-hidden=\"true\"\n              />\n            )}\n            <span\n              className={cn(\n                values.hierarchyDeclared\n                  ? \"text-text-secondary\"\n                  : \"text-text-quaternary\"\n              )}\n            >\n              Waste hierarchy declaration{\" \"}\n              {values.hierarchyDeclared ? \"confirmed\" : \"not confirmed\"}\n            </span>\n          </div>\n          <div className=\"grid gap-2 sm:grid-cols-2\">\n            <SummaryRow label=\"Transferor — signed\" value={values.transferorSignature} />\n            <SummaryRow label=\"Transferee — signed\" value={values.transfereeSignature} />\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/blocks/domain/transfer-note/transfer-note-summary.tsx"
    },
    {
      "path": "components/blocks/domain/transfer-note/types.ts",
      "content": "/** Shared types for the TransferNote form and summary blocks. */\n\nexport interface TransferNoteParty {\n  name: string\n  address: string\n  /** Carrier registration or permit number, e.g. \"CBDU123456\". */\n  licenceNumber: string\n}\n\nexport interface TransferNoteValues {\n  producer: TransferNoteParty\n  carrier: TransferNoteParty\n  receiver: TransferNoteParty\n  /** Free-text waste description. */\n  wasteDescription: string\n  /** European Waste Catalogue code, e.g. \"17 01 01\". */\n  ewcCode: string\n  /** SIC code of the transferor's business, e.g. \"41.20\". */\n  sicCode: string\n  quantity: string\n  /** e.g. \"tonnes\", \"kilograms\", \"cubic metres\". */\n  quantityUnit: string\n  /** e.g. \"Skip\", \"Loose\", \"Bagged\". */\n  containerType: string\n  /** ISO-style date string for the date input, e.g. \"2026-07-06\". */\n  transferDate: string\n  transferPlace: string\n  /** Optional broker or dealer involved in the transfer. */\n  brokerName: string\n  brokerLicenceNumber: string\n  /** Declaration signature name boxes. */\n  transferorSignature: string\n  transfereeSignature: string\n  /** Waste-hierarchy declaration confirmed by the transferor. */\n  hierarchyDeclared: boolean\n}\n\nexport const EMPTY_TRANSFER_NOTE: TransferNoteValues = {\n  producer: { name: \"\", address: \"\", licenceNumber: \"\" },\n  carrier: { name: \"\", address: \"\", licenceNumber: \"\" },\n  receiver: { name: \"\", address: \"\", licenceNumber: \"\" },\n  wasteDescription: \"\",\n  ewcCode: \"\",\n  sicCode: \"\",\n  quantity: \"\",\n  quantityUnit: \"tonnes\",\n  containerType: \"\",\n  transferDate: \"\",\n  transferPlace: \"\",\n  brokerName: \"\",\n  brokerLicenceNumber: \"\",\n  transferorSignature: \"\",\n  transfereeSignature: \"\",\n  hierarchyDeclared: false,\n}\n",
      "type": "registry:component",
      "target": "components/blocks/domain/transfer-note/types.ts"
    }
  ],
  "type": "registry:block"
}