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
- 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.
- 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.
- 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
Tests
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.
Problem
PaymentsView(src/components/payments/payments-view.tsx) passes the raw date inputs to the API:There is no check that
date_from <= date_to. Consequences:handleExport) forwards the same unchecked values toexportPayments, 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
isRangeInvalid = dateFrom && dateTo && dateFrom > dateTocheck 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.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
Tests
Out of scope
The React Query migration and URL-state sync (tracked separately).
Getting started
npm test -- payments-viewGood first files to read:
src/components/payments/payments-view.tsx,src/services/paymentService.ts.