You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
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.
Symptom
PR #160 introduced a generic column-filter primitive (parser + state + apply pipeline + portal-pattern popover infrastructure) that lives inside
frontend/src/recommendations.tsandfrontend/src/state.ts. The same mechanism would benefit:frontend/src/plans.ts) — currently has a hardcoded provider/account filter bar much like the old Recommendations one.frontend/src/history.ts) — same pattern.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
frontend/src/lib/column-filters.tsexporting: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.PlansColumnFilters,HistoryColumnFilters,RIExchangeColumnFilters) — keeps tab-specific column ids type-safe.frontend/src/__tests__/lib-column-filters.test.ts; per-tab tests just exercise their wiring.Order of operations
parseNumericFilter+applyColumnFiltersintofrontend/src/lib/column-filters.ts. Make it a no-op for Recommendations (just import + re-export). Tests stay green.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.tsexposes the shared API.frontend/src/recommendations.tsimports from it; existing 1342 frontend tests still pass.parseNumericFilterorapplyColumnFilters.Related
~/.claude/plans/generic-painting-volcano.md(§ Out of scope)