Skip to content

fix: reject unsubmittable participant shares in the percentage UI - #1381

Merged
SheyeJDev merged 2 commits into
Split-Naira:mainfrom
blesswill88:fix/1321-percentage-validation
Sep 27, 2026
Merged

SheyeJDev merged 2 commits into
Split-Naira:mainfrom
blesswill88:fix/1321-percentage-validation

Conversation

@blesswill88

Copy link
Copy Markdown
Contributor

Overview

The percentage UI validated only the total. Because shares are basis-point
integers, a total of exactly 10000 said nothing about whether the individual
shares were submittable:

const totalBasisPoints = participants.reduce((sum, p) => sum + p.basisPoints, 0);
const isValid = totalBasisPoints === BASIS_POINTS_TOTAL;

[10500, -500] sums to 10000, so the form showed a green "Shares total 100%."
and let the user submit a split where one participant is owed a negative amount
and another is above 100%. The server then rejected it — the UI's job is to
catch that first. Fractional and non-numeric shares slipped through the same
way.

Related Issue

Closes #1321

Changes

  • ParticipantPercentageValidation.tsx
    • Each share is now checked individually: it must be a finite, whole,
      non-negative number of basis points not exceeding 10000. Violations are
      reported as invalidShares with an index, label and machine-readable
      problem (not_a_number, not_whole_basis_points, negative,
      above_total).
    • An impossible share contributes nothing to the total instead of being
      added; otherwise two broken shares could mask each other, which is exactly
      the bug above.
    • isValid now requires both no invalid shares and a total of 10000. The
      message names the offending participant(s) and counts the remainder, so the
      user is told which row to fix rather than only that the sum is wrong.
    • The panel lists the broken shares and keeps the existing
      data-testid/data-valid hooks and role="status" semantics.
    • onValidityChange moved out of useMemo into useEffect. Calling the
      parent's setter during the render phase is a side effect in render — React
      warns about it and it could loop when the parent's state fed back in — and
      it fired on every keystroke even when validity had not changed.
  • ParticipantPercentageValidation.test.ts — adds the per-share cases: a
    legal total built from illegal shares, fractional and non-numeric shares,
    message wording, the zero-share exclusion, and a missing list. The four
    original tests are unchanged apart from asserting invalidShares.

Verification Results

$ npx vitest run src/components/splits/ParticipantPercentageValidation.test.ts
 ✓ src/components/splits/ParticipantPercentageValidation.test.ts (13 tests)
 Test Files  1 passed (1)
      Tests  13 passed (13)
Not run in this environment: the React render behaviour of the `useEffect`
change, and the rest of the frontend suite (the change was applied through the
GitHub Contents API with no local clone, so no browser/RTL run was possible).
Acceptance Criteria Status
Show percentage totals ✅ unchanged total readout, now excluding unsubmittable shares
Highlight invalid totals ✅ red styling preserved and extended to individual shares
Prevent invalid submission ✅ shouldBlockSubmit/isValid reject impossible shares even when the total is 100%
Server validation stays authoritative ✅ client is a pre-check only; the server remains the enforcement point

…omponents/splits/ParticipantPercentageValidation.tsx
…omponents/splits/ParticipantPercentageValidation.test.ts
@drips-wave

drips-wave Bot commented Sep 27, 2026

Copy link
Copy Markdown

@blesswill88 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@SheyeJDev

Copy link
Copy Markdown
Contributor

LGTM

@SheyeJDev
SheyeJDev merged commit 9077d53 into Split-Naira:main Sep 27, 2026
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.

[Product] Add participant percentage validation UI

2 participants