feat(compensation): enforce effectiveDate floor via Zod schema with distinct error messages#1919
Merged
Merged
Conversation
jeffredodd
approved these changes
May 22, 2026
dmortal
approved these changes
May 22, 2026
…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>
2b17344 to
17f74b6
Compare
…angeNotification key Co-authored-by: Cursor <cursoragent@cursor.com>
17f74b6 to
790d0cc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
EFFECTIVE_DATE_BEFORE_MIN) — date is before tomorrow; derived internally byuseCompensationFormbased on mode andjob.primary, so consumers don't wire it upEFFECTIVE_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)useCompensationFormto requestinclude=all_compensationswhen acompensationIdis provided, so pending/future compensations appear in the jobs response andresolveCompAndJobcan populate the form correctly (previously the form showed empty fields for pending comps)resolveCompAndJobnow falls back tojobIdwhencompensationIdisn't found, preservingcurrentJob.primaryfor the carve-out checkTest plan
ManagementEditCompensation): type a past date → "must be in the future" errorManagementEditPendingCompensation): form loads with correct values; today's date is acceptedsrc/components/Employee/CompensationpassScreen.Recording.2026-05-22.at.12.58.38.PM.mov
Made with Cursor