# useDocyrusPivotFilter URL: /docs/native/hooks/use-docyrus-pivot-filter Connects a Docyrus data source to a native PivotFilter strip. It detects the field type, runs a pivot aggregate query, builds pill items and date buckets, and emits filter rules. DocyrusPivotFilterGroup stacks several strips that cross-filter each other. ## Installation ```bash pnpm dlx @docyrus/cli add @docyrus/rn-hooks-use-docyrus-pivot-filter ``` **Dependencies:** - [@docyrus/app-utils](https://www.npmjs.com/package/@docyrus/app-utils) - [@docyrus/api-client](https://www.npmjs.com/package/@docyrus/api-client) - [@tanstack/react-query](https://tanstack.com/query/latest) - [date-fns](https://date-fns.org) This is a straight port of the web hook, with the same signature and the same query payloads. It needs an authenticated `RestApiClient` and a `QueryClientProvider` above it. The hook: - loads the data source schema (`createDataSourceClient(client).getBySlug(app, ds, { expand: 'enums' })`) - detects the field strategy from `field.type` - sends a native Docyrus pivot query to `/v1/apps/{app}/data-sources/{ds}/items`: `columns: '(id, name, icon, color)'` for list fields, `'(id, name)'` for users, `'@'` for dates, together with `calculations` - turns the rows into `PivotFilterItem`s. Enum colours and icons come straight from the join. Date buckets are generated on the device, with `Before`, `Upcoming` and `Not Set` pills. - returns `filterRule` for the current selection and `settingsContent` (the `PivotFilterSettings` panel), which [rn-pivot-filter](/docs/native/docyrus/pivot-filter) renders in a bottom sheet | Field type | Strategy | Filter rule emitted | |-----------|----------|---------------------| | `field-select`, `field-status`, `field-radioGroup`, `field-relation` | `list` | `{ field, operator: '=', value: id }` | | `field-userSelect` | `user` | `{ field, operator: '=', value: userId }` | | `field-date` | `date` | `between` with wall-clock bounds stamped `+00:00` | | `field-dateTime` | `date` | `between` with the device's local offset | | `field-multiSelect`, `field-tagSelect`, `field-userMultiSelect` | `unsupported` | none (query skipped) | The `Not Set` pill emits `{ operator: 'empty', value: null }`. `Before` and `Upcoming` emit `<` and `>` against the window bounds. ## Usage ### Single strip ```tsx import { useDocyrusClient } from '@docyrus/signin/react-native'; import { PivotFilter } from '@/components/docyrus-native/pivot-filter'; import { useDocyrusPivotFilter } from '@/hooks/docyrus-native/use-docyrus-pivot-filter'; export function TaskStatusFilter() { const client = useDocyrusClient(); const pivot = useDocyrusPivotFilter({ client: client!, appSlug: 'base', dataSourceSlug: 'task', fieldSlug: 'status' }); // pivot.filterRule → AND it into your list query return ; } ``` ### DocyrusPivotFilterGroup ```tsx import { DocyrusPivotFilterGroup } from '@/hooks/docyrus-native/use-docyrus-pivot-filter'; setPivotRule(rule)} /> ``` Each strip is fed the other strips' selections through `activeFilters`, so the counts react to what is selected elsewhere. `onFilterRuleChange` receives the AND of all selections, or `null`. On native, horizontal strips stack vertically with thin separators between them. With `vertical`, the rails sit side by side in a row (this suits tablets; on phones, prefer horizontal strips). ## API Reference ### Options (`UseDocyrusPivotFilterOptions`) | Option | Type | Default | Description | |--------|------|---------|-------------| | `client` | `RestApiClient` | — | Authenticated API client (required). | | `appSlug` | `string` | — | App slug (required). | | `dataSourceSlug` | `string` | — | Data source slug (required). | | `fieldSlug` | `string` | — | Field to pivot on (required). | | `calculation` | `PivotFilterCalculation \| null` | `null` | Initial aggregate; `null` = COUNT of `id`. | | `defaultDateBucket` | `PivotFilterDateBucket` | `'days_of_week'` | Initial date bucket (date fields only). | | `defaultFilters` | `unknown` | — | Base filter merged into every query (e.g. a saved view's filter). | | `activeFilters` | `unknown` | — | The consumer's active filter. Pill counts react to it. | | `parentPivotFilters` | `unknown` | — | Filter from a parent pivot (drill-down). A change resets the selection. | | `hideZeroValues` | `boolean` | `false` | Hide items with a zero stat (except the selected one). | | `defaultSelectedItemId` | `string \| null` | `null` | Initial selection. | | `referenceDate` | `Date` | `new Date()` | Reference date for the date-bucket window. | | `disableSettings` | `boolean` | `false` | Hide the settings sheet (`settingsContent` becomes `undefined`). | | `onConfigurationChange` | `(config: { dateBucket: PivotFilterDateBucket; calculation: PivotFilterCalculation \| null }) => void` | — | Fired when the bucket or calculation changes. | | `staleTime` | `number` | `30000` | TanStack Query `staleTime` (ms). | | `enabled` | `boolean` | `true` | Skip fetching when `false`. | | `dataSourceExpand` | `string \| false` | `'enums'` | `expand` param of the schema fetch. `false` or `''` omits it (core/tenant system data sources). | Date buckets (`PivotFilterDateBucket`): `hours_of_today`, `days_of_week`, `days_of_month`, `weeks_of_month`, `weeks_of_quarter`, `months_of_quarter`, `months_of_year`, `quarters_of_year`. Weeks start on Monday. ### Result (`UseDocyrusPivotFilterResult`) | Field | Type | Description | |-------|------|-------------| | `pivotFilterProps` | `PivotFilterProps` | Spread onto `` (items, selection, total, loading, hideZeroValues, onRefresh, settingsContent). | | `items` | `PivotFilterItem[]` | Items built from the response. | | `total` | `number` | Sum of all item stats. | | `selectedItemId` | `string \| null` | Current selection (`null` = All). | | `setSelectedItemId` | `(id: string \| null) => void` | Set the selection programmatically. | | `selectedItem` | `PivotFilterItem \| null` | Selected item. | | `filterRule` | `PivotFilterRule[] \| null` | Rule(s) for the selection; `null` for All. | | `field` | `DataSourceField \| null` | Resolved field definition. | | `fieldType` | `PivotFilterFieldType` | Strategy derived from `field.type`. | | `dateBucket` | `PivotFilterDateBucket` | Current bucket. | | `setDateBucket` | `(bucket: PivotFilterDateBucket) => void` | Change the bucket (also resets the selection). | | `calculation` | `PivotFilterCalculation \| null` | Current calculation. | | `setCalculation` | `(calc: PivotFilterCalculation \| null) => void` | Change the calculation. | | `reload` | `() => void` | Invalidate the schema and refetch the items. | | `isLoading` | `boolean` | First load of the schema or items. | | `isFetching` | `boolean` | Any fetch in progress. | | `error` | `Error \| null` | Schema or items error. | ### DocyrusPivotFilterGroupProps | Prop | Type | Default | Description | |------|------|---------|-------------| | `client` | `RestApiClient` | — | Authenticated API client (required). | | `appSlug` | `string` | — | App slug (required). | | `dataSourceSlug` | `string` | — | Data source slug (required). | | `fields` | `ReadonlyArray` | — | One entry per strip, top to bottom (required). | | `defaultFilters` | `unknown` | — | Base filter for every strip. | | `activeFilters` | `unknown` | — | External filter for every strip (e.g. the list's toolbar filter). | | `onFilterRuleChange` | `(rule: PivotFilterRule[] \| null) => void` | — | AND-combined rule of every selection. | | `vertical` | `boolean` | `false` | Vertical rails side by side instead of stacked horizontal strips. | | `compact` | `boolean` | `false` | Compact pills. | | `className` | `string` | — | Wrapper `View` classes. | | `staleTime` | `number` | — | Forwarded to every strip. | | `dataSourceExpand` | `string \| false` | — | Forwarded to every strip. | ### DocyrusPivotFilterGroupField | Field | Type | Description | |-------|------|-------------| | `fieldSlug` | `string` | Field to pivot on (required). | | `defaultDateBucket` | `PivotFilterDateBucket` | Initial bucket for date fields. | | `calculation` | `PivotFilterCalculation \| null` | Initial calculation. | | `totalLabel` | `string` | "All" pill label for this strip. | | `hideZeroValues` | `boolean` | Hide zero-stat items. | | `disableSettings` | `boolean` | Hide the settings sheet for this strip. | | `defaultSelectedItemId` | `string \| null` | Initial selection. | ## Translation keys The hook reads `ui.pivotFilter.notSet` ("Not Set"), `ui.pivotFilter.before` ("Before") and `ui.pivotFilter.upcoming` ("Upcoming") through `useUiTranslation()`. For the component and settings-panel keys, see [PivotFilter](/docs/native/docyrus/pivot-filter#translation-keys). ## Differences from web - The settings content renders in a bottom sheet instead of a popover. Its aggregate-function and field pickers are chip rows instead of `Select`s. - `DocyrusPivotFilterGroup` puts a thin separator between horizontal strips. - `PivotFilterAggregateFunc` / `PivotFilterCalculation` / `PivotFilterDateBucket` / `PivotFilterFieldType` are declared in the component's `types.ts` and re-exported here under the same names. ## Type Exports | Type | Description | |------|-------------| | `UseDocyrusPivotFilterOptions` | Hook options. | | `UseDocyrusPivotFilterResult` | Hook result. | | `DocyrusPivotFilterGroupProps` | Group component props. | | `DocyrusPivotFilterGroupField` | Per-strip config of the group. | | `PivotFilterRule` | `{ field, operator, value }`. | | `PivotFilterAggregateFunc` | `'count' \| 'sum' \| 'avg' \| 'min' \| 'max'`. | | `PivotFilterCalculation` | `{ func, field }`. | | `PivotFilterDateBucket` | The 8 date buckets. | | `PivotFilterFieldType` | `'list' \| 'user' \| 'user-multi' \| 'date' \| 'unsupported'`. |