picker + inline-create — closing #1281Slice 1 (#329) wired the Matter Types settings catalog to the real
/app/matter-types contract and left one piece open: the Add-Matter
wizard could not pick or mint a matter type, and never sent
matter_type_id on create. Functions S3 (#1279) landed
MatterCreateRequest.matterTypeId and the server-side type resolution.
This slice is the consumer side — the last piece of #1281.
| Piece | What & why |
|---|---|
| Picker component | add-matter/matter-type-select.tsx (new) — a live combobox of firm matter types rendered mono-caps, mirroring participant-label-select.tsx: type to filter, "+ Add new type…" at the foot swaps the popover body to an inline create form. Copy-injected (i18n-agnostic), with a co-located story. |
| Inline create | Minting a type calls the slice-1 path: useAppCreateMatterType (POST /app/matter-types) wired in live-matters-list-page.tsx via createWizardMatterType — dedupes by name, then invalidates appListMatterTypesQueryKey(). The minted type is firm-wide and immediately selected. |
| Step-2 field | step2-matter-body.tsx renders the picker as the first field, mono-caps label + required marker on the scratch path, with a helper line (scratch hint vs "set by the selected preset"). |
| Gating | add-matter-wizard.tsx holds matterTypeId state and folds it into the Step-2 Next gate: !isScratch || matterTypeId. Scratch requires a type; the preset path does not. |
| Send the id | matterTypeId flows AddMatterCreatePayload → wizardCreateInputFromPayload → WizardMatterInput → createMatterFromWizardAction → MatterCreateRequest.matterTypeId. |
| Data wiring | live-matters-list-page.tsx reads live types with useAppListMatterTypes() (no-arg = live only, distinct from the catalog's { includeArchived: true } entry) and passes options + the create handler down through AddMatterModal. |
| i18n | 10 new keys under the AddMatter namespace (placeholder, add-new, create/creating/cancel, error, scratch/preset hints, field label), full en + hi parity. |
The contract does not expose matter_type_id on the
matter-template View (verified against both the vendored mirror and functions
main HEAD), so the wizard cannot pre-fill the combobox with the
preset's type by name. It does not need to: functions
_resolve_matter_type_id makes the preset's type win
(template.matter_type_id || requested), and requires a type only on the
scratch path (else pramaan.matter.matter_type_required). So the app sends
null on the preset path and the backend derives the type; on the scratch
path the wizard gates Next until one is chosen. The brief's "pre-select the preset's id"
is the only unmet detail and is purely cosmetic — surfacing the preset's type name would need
a new field on the template View (a follow-up functions ticket).
pnpm tsc clean
pnpm lint clean (0 errors; only pre-existing warnings)
pnpm build green
vitest add-matter + matter-create suites pass
(matters-internal-route flake is pre-existing — fails identically on clean HEAD)
contract no openapi/ or src/gen changes — mirror byte-identical to functions HEAD; freshness guard untouched
i18n parity en/hi AddMatter — 10 keys added to both
/app/matter-types hooks
(useAppListMatterTypes / useAppCreateMatterType) and proxy. No
LEGACY_MATTER_TYPE_ID_COMPAT sentinel existed on the app side, so nothing to retire here.15 file(s), +570 / -5 lines
| Path | Role | + | - |
|---|---|---|---|
| messages/en.json | Config | +10 | -0 |
| messages/hi.json | Config | +10 | -0 |
| src/app/[locale]/(workspace)/matters/actions.ts | App route | +2 | -0 |
| src/components/add-matter/__mocks__/matter-types.ts | Component | +20 | -0 |
| src/components/add-matter/add-matter-types.ts | Component | +10 | -0 |
| src/components/add-matter/add-matter-wizard.stories.tsx | Component | +15 | -0 |
| src/components/add-matter/add-matter-wizard.tsx | Component | +34 | -4 |
| src/components/add-matter/matter-type-select.stories.tsx | Component | +68 | -0 |
| src/components/add-matter/matter-type-select.tsx | Component | +246 | -0 |
| src/components/add-matter/step2-matter-body.tsx | Component | +42 | -0 |
| src/components/matters/live-matters-list-page.tsx | Component | +47 | -1 |
| src/components/matters/live-matters-wizard-payload.ts | Component | +4 | -0 |
| tests/unit/add-matter-wizard-label-gate.test.tsx | Test | +1 | -0 |
| tests/unit/live-matters-wizard-payload.test.ts | Test | +44 | -0 |
| tests/unit/wizard-matter-actions.test.ts | Test | +17 | -0 |