Skip to content

refactor(frontend): extract column-filter primitives into a shared module — adopt on Plans / History / RI Exchange #166

@cristim

Description

@cristim

Symptom

PR #160 introduced a generic column-filter primitive (parser + state + apply pipeline + portal-pattern popover infrastructure) that lives inside frontend/src/recommendations.ts and frontend/src/state.ts. The same mechanism would benefit:

  • Purchase Plans (frontend/src/plans.ts) — currently has a hardcoded provider/account filter bar much like the old Recommendations one.
  • Purchase History (frontend/src/history.ts) — same pattern.
  • RI Exchange (frontend/src/riexchange.ts) — its own column UI.

Without harvesting, each of these tabs would either keep its old filter bar (inconsistent UX) or grow its own copy of the column-filter logic (drift).

What "shared module" would look like

  • New file: frontend/src/lib/column-filters.ts exporting:
    • parseNumericFilter (already lives in recommendations.ts; move).
    • applyColumnFilters<T> (generic over row type — caller supplies cell extractors per column).
    • mountColumnFilterPopover<T>(triggerBtn, columnId, distinctValues, currentFilter, onChange) — the portal-pattern popover lifecycle.
    • renderFilterStatusBar(loaded, visible, onClearAll) — the Clear-filters badge + aria-live count.
  • State module: each consuming tab owns its own filter record (PlansColumnFilters, HistoryColumnFilters, RIExchangeColumnFilters) — keeps tab-specific column ids type-safe.
  • Tests: lift the existing parser/apply tests into frontend/src/__tests__/lib-column-filters.test.ts; per-tab tests just exercise their wiring.

Order of operations

  1. Wait for PR feat(recommendations): per-column header filters + sticky bottom action box #160 to bake — confirm the column-filter UX feels right before locking the API of a shared module.
  2. Refactor in place: extract parseNumericFilter + applyColumnFilters into frontend/src/lib/column-filters.ts. Make it a no-op for Recommendations (just import + re-export). Tests stay green.
  3. One follow-up PR per consuming tab (Plans, History, RI Exchange) that swaps its old filter bar for the shared popover. Sequential; each one a focused review.

Severity

Medium for the shared-module refactor (consistency win). Low per consuming tab (each is independent; can prioritise based on user feedback).

Acceptance

  • frontend/src/lib/column-filters.ts exposes the shared API.
  • frontend/src/recommendations.ts imports from it; existing 1342 frontend tests still pass.
  • Plans / History / RI Exchange tabs use the shared module and remove their own filter bar code.
  • No tab has a stale copy of parseNumericFilter or applyColumnFilters.

Related

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions