Filters and saved views
Every filter is a route, a setup can be named and reopened, and defaults are a setting — the three decisions that make a twelve-filter board usable on a phone.
src/app/filter-sheets · src/app/filters · feature-owned filter stacks
| Group | Screens |
|---|---|
screener-filters/ | leagues, players, bookmakers, stats, ranges, games, availability, sort, card-information, saved-filters |
player-filters/ | competitions, bookmakers |
board-card-settings/[board]/ | what each card shows, and saved views |
[sheet]/, fixture-trend-filters | the generic sheet route, and the trends panel |
A filter panel is a route
Not a modal component. That is the decision the whole surface rests on, and it buys three things a component cannot:
- it can be linked to, so a support answer can be a URL;
- it can be restored, so backgrounding the app mid-filter does not lose it;
- it is dismissible by the back gesture, which is what the platform's users
expect and what a
<Modal>has to reimplement badly.
Saved views
filter-presets.ts and board-view-presets.ts — a setup is named and reopened.
On a phone, reconstructing twelve filters is a minute of tapping, so a screener
that cannot remember one is a screener nobody uses twice.
Both have tests beside them, because "saved" is a promise that fails silently.
Defaults
filter-defaults.ts, reachable from profile/filter-defaults. Saved views are for setups you switch
between; defaults are for the one you always start from.
State
Expo Router owns applied filter values and the address of each filter screen. A filter screen may hold an unsubmitted draft locally; Apply serializes the normalized result back to the board route. Zustand owns saved views and default preferences, never the active board selection. See Where state lives for the full boundary.