Cross-cutting · Filter & segment builder component

The reusable filter builder used across list screens and the segment editor: grouped filter options, per-filter operations and values, an AND/OR combinator, apply/clear, and — in the segment context — saving the filter set as a persisted definition.

AreaCross-cutting
Routescrm.users.index · crm.segments.new · crm.segments.edit · crm.commerces.index · cms.proposals.index · crm.receipts.index · marketing.campaigns.index
Centre modulesalways available
Staff levelsas per the host screen
Modelssegment
UI labelall / any-of
Coverage4 use cases · 2 happy · 4 failure

Known issues (1)

How it works

The filter palette is data-driven and module-aware: beautifyFilters(enumFilters, center) and group-filter.js strip options whose declared modules the centre does not have, so the same component offers different filters per tenant. Two correctness guards matter: _filtersHasVoidValue() refuses to apply a filter with no value and raises showFilterWarning, and requiredFilters/hasValidFilters enforce that any option marked required in the palette is present. parseFilters serialises the rows into the API’s filter shape, and the combinator (and/or, labelled ‘All’ / ‘Any of’) is sent as type. Applying and saving both emit analytics (LIST_FILTERED, SEGMENT_SAVED).

Use cases

Why someone opens this (4)

  • Narrowing any list screen without needing a bespoke filter UI per entity.
  • Switching between ‘match all’ and ‘match any’ semantics on the same filter set.
  • Promoting an ad-hoc filter set into a reusable segment.
  • Offering tenant-specific filters without code changes.

Path map

flowchart LR
    F(["Filter and segment builder component"]):::feat
    F --> H1["Filters applied"]:::ok
    F --> H2["Filter set saved to a segment"]:::ok
    F -.-> X1["Filter row with no value"]:::bad
    F -.-> X2["Required filter absent"]:::bad
    F -.-> X3["Save rejected"]:::bad
    F -.-> X4["Filter unavailable for the centre"]:::bad
    classDef feat fill:#8c5a3c,stroke:#8c5a3c,color:#ffffff,font-weight:bold
    classDef ok fill:#e3f1ea,stroke:#0d6b42,color:#0d4a2e
    classDef bad fill:#f7e6e2,stroke:#9a2d1c,color:#6e1f13

Happy paths

Filters applied

  1. User adds filter rows from the module-aware grouped palette.
  2. Each row gets an operation and a value.
  3. The combinator is set to All or Any of.
  4. applyFilters serialises them via parseFilters and refreshes the list, tracking LIST_FILTERED.

Filter set saved to a segment

  1. In the segment editor the user clicks save changes.
  2. saveChanges serialises the filters and the combinator, persists them, tracks SEGMENT_SAVED and re-applies them to refresh the preview.

Failure paths

QA checklist

Tick these off while regression-testing this feature. The boxes are plain Markdown, so progress is visible in git diffs.

  • ✅ Filters applied
  • ✅ Filter set saved to a segment
  • ⛔ Filter row with no value
  • ⛔ Required filter absent
  • ⛔ Save rejected
  • ⛔ Filter unavailable for the centre

Implementation


Generated from doc/feature-inventory.json · id xc-segment-filter-builder · commit 276788ca6