feat(billing): inline company validation on invoice form, drop UUID wording (PMS-579) #388

Merged
longjacksonle merged 2 commits from feat/PMS-579-invoice-company-inline-error into main 2026-06-30 17:29:28 +02:00

Problem (PMS-579, found in PMS-560 Invoices smoke)

The invoice create form's Company field diverged from the standard field-level validation pattern and leaked an implementation detail:

  • A missing company set a top-level banner error reading "A valid company ID (UUID) is required." Every other required field on the form renders a red outline + message under the field.
  • Users pick a company by name and should never see "UUID".

Fix

CompanyPicker already accepts and forwards an error prop to its wrapped Input (MAPPS-322), so this is purely a caller-side change in InvoiceNewPage:

  • Add a field-level company_error signal, passed to the picker's error prop, so a blank-company submit paints the red outline + inline message under the field.
  • Both submit paths that share the picker (manual create and generate-from-time-entries) set company_error to "Company is required." instead of the banner.
  • The manual path ties into the FormGuard first-invalid focus order via the picker's input id (company_search), so a blank company focuses the field like other required fields.
  • company_error clears when a company is selected.
  • The banner is retained for submit/server errors.

Scope note

RecordPaymentModal uses the same CompanyPicker and the same "company ID (UUID)" wording, but it is a separate payment-recording form, not the invoice create form this ticket covers. Left unchanged; can be a follow-up if we want the payment form standardized too.

Stacking / housekeeping

  • Branched off the PMS-577 checkbox-checkmark branch (PR #387) so the source-mounted dev stack keeps both fixes while #387 is still open. Once #387 merges, this PR's diff reduces to just the billing change.
  • Cargo.lock: syncs mokosh-apps 0.3.0 -> 0.4.0 to match the Cargo.toml left by the merged Release v0.4.0 (the release updated the manifest but not the lock).

Test

Invoice create form -> submit with no company: red outline + "Company is required." under the picker, focus lands on it, no banner, no "UUID". Pick a company: error clears, submit proceeds.

🤖 Generated with Claude Code

## Problem (PMS-579, found in PMS-560 Invoices smoke) The invoice create form's Company field diverged from the standard field-level validation pattern and leaked an implementation detail: - A missing company set a top-level banner error reading "A valid company ID (UUID) is required." Every other required field on the form renders a red outline + message under the field. - Users pick a company by name and should never see "UUID". ## Fix `CompanyPicker` already accepts and forwards an `error` prop to its wrapped `Input` (MAPPS-322), so this is purely a caller-side change in `InvoiceNewPage`: - Add a field-level `company_error` signal, passed to the picker's `error` prop, so a blank-company submit paints the red outline + inline message under the field. - Both submit paths that share the picker (manual create and generate-from-time-entries) set `company_error` to "Company is required." instead of the banner. - The manual path ties into the FormGuard first-invalid focus order via the picker's input id (`company_search`), so a blank company focuses the field like other required fields. - `company_error` clears when a company is selected. - The banner is retained for submit/server errors. ## Scope note `RecordPaymentModal` uses the same `CompanyPicker` and the same "company ID (UUID)" wording, but it is a separate payment-recording form, not the invoice create form this ticket covers. Left unchanged; can be a follow-up if we want the payment form standardized too. ## Stacking / housekeeping - Branched off the PMS-577 checkbox-checkmark branch (PR #387) so the source-mounted dev stack keeps both fixes while #387 is still open. Once #387 merges, this PR's diff reduces to just the billing change. - Cargo.lock: syncs mokosh-apps 0.3.0 -> 0.4.0 to match the Cargo.toml left by the merged Release v0.4.0 (the release updated the manifest but not the lock). ## Test Invoice create form -> submit with no company: red outline + "Company is required." under the picker, focus lands on it, no banner, no "UUID". Pick a company: error clears, submit proceeds. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(forms): paint checkbox checkmark on :checked (PMS-577)
Some checks failed
Check / fmt + clippy + tests (pull_request) Failing after 1s
Create release / Create release from merged PR (pull_request) Has been skipped
44eb3a6ea8
The shared Checkbox set `bg-surface` on the input. The @tailwindcss/forms base layer paints a checked box as a white checkmark SVG over a `currentColor` (accent) fill, but the `bg-surface` utility outranks that base rule and held the background at the theme surface color. In light mode `--surface` is `#ffffff`, so the white checkmark rendered white-on-white and was invisible: clicking toggled state (signal confirmed via diagnostic) but no checkmark appeared. Reported on the timesheet certify and billable checkboxes; the cause was the shared component, so every checkbox was affected.

Re-assert the accent fill and drop the border on `:checked` (`checked:bg-accent checked:border-transparent`) so the white checkmark has contrast in both light and dark themes. One-line component change fixes all checkboxes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(billing): inline company validation on invoice form, drop UUID wording (PMS-579)
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 1m24s
Create release / Create release from merged PR (pull_request) Has been skipped
32e95d0678
The invoice create form (`InvoiceNewPage`) flagged a missing company in the top-level error banner with the message "A valid company ID (UUID) is required." That diverged from every other required field (which render a red outline + message under the field) and leaked an implementation detail: users pick a company by name and should never see "UUID".

`CompanyPicker` already accepts and forwards an `error` prop to its wrapped `Input` (MAPPS-322), so this is a caller-side fix. Both submit paths that share the picker (manual create and generate-from-time-entries) now set a field-level `company_error` reading "Company is required." instead of the banner, clear it once a company is selected, and tie the manual path into the FormGuard first-invalid focus order via the picker's input id. The banner stays for submit/server errors.

Out of scope: `RecordPaymentModal` has the same picker and wording but is a separate payment form, not the invoice create form PMS-579 covers.

Also syncs Cargo.lock mokosh-apps 0.3.0 -> 0.4.0 to match the Cargo.toml left by the merged Release v0.4.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle deleted branch feat/PMS-579-invoice-company-inline-error 2026-06-30 17:29:28 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
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!388
No description provided.