feat(contacts): freeform company entry on contact form (+ Add Company) #258

Merged
vas2000-work merged 1 commit from feat/mapps-251-freeform-company-contact into main 2026-06-18 03:01:39 +02:00
Owner

The New / Edit Contact form previously hard-required selecting an existing CRM company before a contact could be saved. A contact is closer to a Google Contacts entry (a name plus a phone), so the company must be optional and accept a freeform typed value that creates no companies row.

Frontend DTOs: CreateContactRequest.company_id is now Option<Uuid> with a new company_name: Option<String>; Contact.company_id and ContactResponse.company_id are Option<Uuid>. The local page structs ContactDetail and ContactEditPayload carry company_id: Option<Uuid> with serde defaults so a freeform-only contact deserializes without panicking.

Contact form: a "+ Add Company" toggle flips the company field between the existing CompanyPicker (link an existing CRM company) and a freeform text input. Switching modes clears the other mode's value so only one source is ever submitted. The picker is no longer required. handle_submit sends company_id when a CRM company is picked, company_name when a freeform name is typed, neither when blank, and blocks supplying both with an inline error. On Edit the form opens in freeform mode when the loaded contact has a company_name but no resolvable company_id.

Render paths: the contact list row and detail view render a freeform company name as plain text (no CompanyDetail link) and an FK-linked company name as a link, with no panic on a None company_id.

#MAPPS-251

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

The New / Edit Contact form previously hard-required selecting an existing CRM company before a contact could be saved. A contact is closer to a Google Contacts entry (a name plus a phone), so the company must be optional and accept a freeform typed value that creates no `companies` row. Frontend DTOs: `CreateContactRequest.company_id` is now `Option<Uuid>` with a new `company_name: Option<String>`; `Contact.company_id` and `ContactResponse.company_id` are `Option<Uuid>`. The local page structs `ContactDetail` and `ContactEditPayload` carry `company_id: Option<Uuid>` with serde defaults so a freeform-only contact deserializes without panicking. Contact form: a "+ Add Company" toggle flips the company field between the existing `CompanyPicker` (link an existing CRM company) and a freeform text input. Switching modes clears the other mode's value so only one source is ever submitted. The picker is no longer `required`. `handle_submit` sends `company_id` when a CRM company is picked, `company_name` when a freeform name is typed, neither when blank, and blocks supplying both with an inline error. On Edit the form opens in freeform mode when the loaded contact has a `company_name` but no resolvable `company_id`. Render paths: the contact list row and detail view render a freeform company name as plain text (no `CompanyDetail` link) and an FK-linked company name as a link, with no panic on a `None` `company_id`. #MAPPS-251 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(contacts): freeform company entry on contact form (+ Add Company)
Some checks failed
Check / clippy + fmt + tests (pull_request) Failing after 1m12s
85367f1605
The New / Edit Contact form previously hard-required selecting an existing CRM company before a contact could be saved. A contact is closer to a Google Contacts entry (a name plus a phone), so the company must be optional and accept a freeform typed value that creates no `companies` row.

Frontend DTOs: `CreateContactRequest.company_id` is now `Option<Uuid>` with a new `company_name: Option<String>`; `Contact.company_id` and `ContactResponse.company_id` are `Option<Uuid>`. The local page structs `ContactDetail` and `ContactEditPayload` carry `company_id: Option<Uuid>` with serde defaults so a freeform-only contact deserializes without panicking.

Contact form: a "+ Add Company" toggle flips the company field between the existing `CompanyPicker` (link an existing CRM company) and a freeform text input. Switching modes clears the other mode's value so only one source is ever submitted. The picker is no longer `required`. `handle_submit` sends `company_id` when a CRM company is picked, `company_name` when a freeform name is typed, neither when blank, and blocks supplying both with an inline error. On Edit the form opens in freeform mode when the loaded contact has a `company_name` but no resolvable `company_id`.

Render paths: the contact list row and detail view render a freeform company name as plain text (no `CompanyDetail` link) and an FK-linked company name as a link, with no panic on a `None` `company_id`.

#MAPPS-251

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vas2000-work force-pushed feat/mapps-251-freeform-company-contact from 85367f1605
Some checks failed
Check / clippy + fmt + tests (pull_request) Failing after 1m12s
to 005739dc09
All checks were successful
Check / clippy + fmt + tests (pull_request) Successful in 1m0s
Create release / Create release from merged PR (pull_request) Has been skipped
2026-06-18 02:43:51 +02:00
Compare
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-apps!258
No description provided.