Skip to content

feat(compensation): enforce effectiveDate floor via Zod schema with distinct error messages#1919

Merged
serikjensen merged 3 commits into
mainfrom
feat/comp-min-effective-date-zod-validation
May 22, 2026
Merged

feat(compensation): enforce effectiveDate floor via Zod schema with distinct error messages#1919
serikjensen merged 3 commits into
mainfrom
feat/comp-min-effective-date-zod-validation

Conversation

@serikjensen
Copy link
Copy Markdown
Member

@serikjensen serikjensen commented May 22, 2026

Summary

  • Adds Zod-based client-side validation to compensation management forms so typed effective dates are validated against two separate rules with distinct messages:
    • "Effective date must be in the future" (EFFECTIVE_DATE_BEFORE_MIN) — date is before tomorrow; derived internally by useCompensationForm based on mode and job.primary, so consumers don't wire it up
    • "Effective date cannot be before the employee's hire date." (EFFECTIVE_DATE_BEFORE_HIRE) — date passes the tomorrow floor but is before the job's hire date; now also fires in update mode on management screens (previously create-only)
  • Fixes useCompensationForm to request include=all_compensations when a compensationId is provided, so pending/future compensations appear in the jobs response and resolveCompAndJob can populate the form correctly (previously the form showed empty fields for pending comps)
  • resolveCompAndJob now falls back to jobId when compensationId isn't found, preserving currentJob.primary for the carve-out check

Test plan

  • Create mode (ManagementEditCompensation): type a past date → "must be in the future" error
  • Create mode: type tomorrow's date → submits successfully
  • Update mode, primary job (ManagementEditPendingCompensation): form loads with correct values; today's date is accepted
  • Update mode, secondary job: type a date after tomorrow but before hire date → "cannot be before the employee's hire date" error
  • All 134 unit tests in src/components/Employee/Compensation pass
Screen.Recording.2026-05-22.at.12.58.38.PM.mov

Made with Cursor

@serikjensen serikjensen requested a review from a team as a code owner May 22, 2026 19:03
serikjensen and others added 2 commits May 22, 2026 14:44
…istinct error messages

Adds client-side validation so typed effective dates on compensation
management forms are checked against two separate rules, each with its
own message:

- EFFECTIVE_DATE_BEFORE_MIN ("must be in the future") — fires when the
  date is before tomorrow; derived internally by useCompensationForm
  based on mode and job.primary so consumers don't need to wire it up.
- EFFECTIVE_DATE_BEFORE_HIRE ("cannot be before the hire date") — fires
  when the date passes the tomorrow floor but is still before the job's
  hire date; now also active in update mode on management screens where
  minEffectiveDate is present.

Also fixes useCompensationForm to request include=all_compensations when
a compensationId is provided, so pending/future compensations are
included in the jobs response and resolveCompAndJob can find them.
resolveCompAndJob falls back to jobId when compensationId isn't found to
preserve currentJob.primary for the carve-out check.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add optional minDate/maxDate ISO string fields to FieldMetadata so hooks
can publish date picker bounds centrally. DatePickerHookField reads them
via normalizeToDate (local-timezone-safe) when not supplied as explicit
props — explicit props still take precedence for backward compat.

useCompensationForm writes effectiveDateMinDate (max of tomorrow and
hireDate) and maximumEffectiveDate into fieldsMetadata.effectiveDate,
removing the need for every consumer to compute and thread these values
manually. ManagementCompensationFormBody, AddCompensationFormBody,
AddAnotherJob, and EditPendingCompensation all shed the manual
min-date calculations and prop drilling.

Also unify the willDeleteSecondaryJobs warning copy: both form bodies
now use the same i18n key (validations.classificationChangeNotification)
with updated text that accurately reflects immediate deletion.

Co-authored-by: Cursor <cursoragent@cursor.com>
@serikjensen serikjensen force-pushed the feat/comp-min-effective-date-zod-validation branch from 2b17344 to 17f74b6 Compare May 22, 2026 20:45
…angeNotification key

Co-authored-by: Cursor <cursoragent@cursor.com>
@serikjensen serikjensen force-pushed the feat/comp-min-effective-date-zod-validation branch from 17f74b6 to 790d0cc Compare May 22, 2026 20:49
@serikjensen serikjensen enabled auto-merge (squash) May 22, 2026 20:52
@serikjensen serikjensen merged commit c1bfb2c into main May 22, 2026
20 of 24 checks passed
@serikjensen serikjensen deleted the feat/comp-min-effective-date-zod-validation branch May 22, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants