Skip to content

Build Unified Filter Bottom Sheet & Filter State Manager #1523

Description

@pedrazamiguez

Problem / Motivation

As part of Phase 3 (Expenses Analytics & Filters), multiple filter mechanisms (search, categories, members, date ranges) are being added to the Expenses List screen. Implementing all of these directly on the main screen would severely clutter the UI, violating the "Whitespace" and "Premium" pillars of the Horizon Narrative design language. A unified orchestration mechanism is required to hold complex filters in a bottom sheet and manage the unified active filter state.

Note: To keep the expenses list screen as clean as possible, only the search bar should remain on the main screen. The category chips (#1501) should also be moved into this bottom sheet filter. In the future, the search bar could become omni-functional and suggest categories dynamically as the user types.

Proposed Solution

  • Create a new domain data class, ExpenseFilterCriteria, to hold the active filter state (search query, selected categories, selected members, date range).
  • In ExpensesViewModel, expose a MutableStateFlow<ExpenseFilterCriteria> and use combine with the expensesFlow to apply the filters in-memory on Dispatchers.Default.
  • Create a new UI component (e.g., ExpenseFilterBottomSheet) using the ActionBottomSheet from :core:design-system to house the complex filters (Categories, Members, Dates) to keep the main screen clean.
  • Ensure the active filter state is bundled into the MVI UiState so the UI can accurately reflect active filter badges and provide a "Clear Filters" action.

Acceptance Criteria

  • ExpenseFilterCriteria model is created.
  • ExpensesViewModel successfully filters expenses in-memory based on the active criteria using Dispatchers.Default.
  • ExpenseFilterBottomSheet is created (using ActionBottomSheet) and can be opened/closed from the Expenses List screen.
  • All existing tests pass; new unit tests added for the ExpensesViewModel filtering logic.
  • make fast-check passes during iterative development (~15–30s).
  • make check > build.log 2>&1 && echo "Check passed successfully" || (tail -n 100 build.log && exit 1) passes with 0 failures before merging.
  • No new detekt findings introduced.

Out of Scope

Related Issues / PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew app features

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions