Skip to content

Payment date filters are unvalidated: date_from after date_to ships to the backend and returns confusing results #392

Description

@usmanimamu17-create

Problem

PaymentsView (src/components/payments/payments-view.tsx) passes the raw date inputs to the API:

<input type="date" value={dateFrom} onChange={(e) => { setDateFrom(e.target.value); setPage(1); }} />
...
fetchPayments({ ..., date_from: dateFrom || undefined, date_to: dateTo || undefined, ... })

There is no check that date_from <= date_to. Consequences:

  • A reversed range reaches the server: the operator picks From = 2026-08-10 and To = 2026-08-01 (or the fields auto-fill inconsistently); the backend either returns an empty list or a validation error whose message is backend-shaped, with no client-side guidance.
  • The two inputs are independent: nothing disables or flags the invalid combination, so the operator discovers the problem only by the (possibly empty) result — indistinguishable from "no payments in range".
  • The same pattern will be reused: the export path (handleExport) forwards the same unchecked values to exportPayments, so a reversed range exports an empty file with no warning.

Root cause

The filter bar was built with bare date inputs and no cross-field validation.

Why this is architecturally hard

  1. The fix is a derived isRangeInvalid = dateFrom && dateTo && dateFrom > dateTo check with an inline message and a disabled/flagged state — small, but the pattern (cross-field validation for paired filters) should be a reusable form component, since the outages and dashboard filters will grow the same pairs.
  2. The empty-result ambiguity (no data vs. bad range) matters for UX copy: the empty state text should distinguish the two when the range is known-invalid.
  3. The export path must share the guard so exports cannot be run with a reversed range — the two call sites must stay in sync.

Proposed design

Add a cross-field range check in PaymentsView (inline error, applied to both the list fetch and the export), render the empty state distinctly when the range is invalid, and add tests for reversed and equal ranges.

Acceptance criteria

Service

  • A reversed date range is flagged inline and not submitted as-is.
  • The export path respects the same guard.

Tests

  • A test asserts a reversed range blocks the fetch.
  • A test asserts equal bounds are accepted.

Out of scope

The React Query migration and URL-state sync (tracked separately).

Getting started

npm test -- payments-view

Good first files to read: src/components/payments/payments-view.tsx, src/services/paymentService.ts.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardStellar Waveissue-trackingThird CampaignCampaign: Third Campaignarea/paymentsImported campaign issue labelpriority/mediumImported campaign issue label

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions