# useDocyrusContactActivity URL: /docs/native/hooks/use-docyrus-contact-activity Merges a record's audit log, comments, related events and tasks, and status updates into one typed timeline for ContactActivityPanel, with upcoming items, a relationship summary and comment and status mutations. ## Installation ```bash pnpm dlx @docyrus/cli add @docyrus/rn-hooks-use-docyrus-contact-activity ``` **Dependencies:** - [@tanstack/react-query](https://www.npmjs.com/package/@tanstack/react-query) The hook needs a `QueryClientProvider` above it. It is also re-exported from `@/components/docyrus-native/contact-activity-panel`. ## Usage ```tsx import { useDocyrusClient } from '@docyrus/signin/react-native'; import { ContactActivityPanel } from '@/components/docyrus-native/contact-activity-panel'; import { useDocyrusContactActivity } from '@/hooks/docyrus-native/use-docyrus-contact-activity'; export function ContactActivity({ contactId, meId }: { contactId: string; meId: string }) { const client = useDocyrusClient(); const { panelProps } = useDocyrusContactActivity({ client, appSlug: 'base', dataSourceSlug: 'contact', recordId: contactId, relationSlug: 'contact', currentUserId: meId }); return ; } ``` ### Sources | Source | Request | Becomes | |--------|---------|---------| | `audit` | `GET {record}/activities` | `record_create`, `record_update`, `file`, `trace`, … rows (comment operations are skipped) | | `comments` | `GET {record}/comments` | `comment` cards. Replies stay off the timeline and are served by `onLoadReplies` | | `events` | `GET /v1/apps/{eventApp}/data-sources/{eventDs}/items` filtered by `eventRelationSlug ?? relationSlug` | `call` or `meeting` cards, classified by `classifyEvent` or `eventTypeNames` | | `tasks` | `GET /v1/apps/{taskApp}/data-sources/{taskDs}/items` filtered by `taskRelationSlug ?? relationSlug` | `task` rows plus open-task counts and upcoming tasks | | `statusUpdates` | `GET /v1/apps/{activityApp}/data-sources/{activityDs}/items` for this record | `status_update` rows | | `files` | `GET {record}/files` | `file` rows carrying a real `PostAttachment` (name, size, MIME, signed URL). With this on, the audit log's bare `UPLOAD_FILE` traces are dropped — same upload, less information | `{record}` is `/v1/apps/:appSlug/data-sources/:dataSourceSlug/items/:recordId`. Users come from `/v1/users` unless you pass `users`. Events and tasks are only fetched when a relation slug is set. Every query lives under the `['docyrus-contact-activity', {record}]` prefix, which [`useDocyrusLogActivity`](/docs/native/hooks/use-docyrus-log-activity) invalidates after each log, so a mounted timeline refreshes by itself. `CreatePostPayload.attachments` are `NativeFile`s on native. Like web, the hook currently posts only `message` and `parentId`. ## API Reference ### UseDocyrusContactActivityOptions | Option | Type | Default | Description | |--------|------|---------|-------------| | `client` | `ContactActivityClient` | - | REST client with `get` / `post` / `patch` / `delete`. `RestApiClient` fits (required) | | `appSlug` | `string` | - | Owning record's app (required) | | `dataSourceSlug` | `string` | - | Owning record's data source (required) | | `recordId` | `string` | - | Owning record id (required) | | `relationSlug` | `string` | - | Back-relation slug on events and tasks. Without it those sources stay off | | `eventRelationSlug` | `string` | `relationSlug` | Event back-relation override | | `taskRelationSlug` | `string` | `relationSlug` | Task back-relation override | | `sources` | `ContactActivitySources` | all `true` | Toggle `audit`, `comments`, `events`, `tasks`, `statusUpdates`, `files` | | `eventAppSlug` | `string` | `'base'` | Events app | | `eventDataSourceSlug` | `string` | `'event'` | Events data source | | `taskAppSlug` | `string` | `'base'` | Tasks app | | `taskDataSourceSlug` | `string` | `'task'` | Tasks data source | | `activityAppSlug` | `string` | `'base'` | Status-activity app | | `activityDataSourceSlug` | `string` | `'activity'` | Status-activity data source | | `users` | `ChatUser[]` | - | Users instead of fetching `/v1/users` | | `currentUserId` | `string` | - | Current user id | | `activityTypes` | `ActivityType[]` | - | Passed to the panel's type filter | | `eventTypeNames` | `EventTypeNameHints` | `{ call: ['call', 'phone'], meeting: ['meeting', 'visit', 'demo'] }` | Name substrings used to classify events | | `classifyEvent` | `(event: Record) => 'call' \| 'meeting'` | - | Custom classifier (wins over `eventTypeNames`) | | `relatedColumns` | `{ events?: string[]; tasks?: string[] }` | - | Extra relation columns fetched on the event / task sources and surfaced as related chips in the detail sheet. Relation slugs are per-tenant and an unknown column fails the whole request, so nothing is requested unless you name it | | `limit` | `number` | `100` | Page size per source | | `enabled` | `boolean` | `true` | Toggle every query | ### UseDocyrusContactActivityResult | Field | Type | Description | |-------|------|-------------| | `activities` | `ContactActivity[]` | Merged timeline, newest first | | `upcoming` | `UpcomingActivity[]` | Future tasks and events, soonest first | | `relationshipSummary` | `RelationshipSummary` | Last contact, next activity, open tasks | | `users` | `ChatUser[]` | Resolved users | | `currentUser` | `ChatUser \| undefined` | Resolved current user | | `panelProps` | `ContactActivityPanelData` | Spread onto `` | | `isLoading` | `boolean` | Any source loading | | `error` | `Error \| null` | First source error | | `isMutating` | `boolean` | Any mutation pending | | `mutationError` | `Error \| null` | First mutation error | | `refetch` | `() => Promise` | Invalidate every source | | `createComment` | `(payload: CreatePostPayload) => Promise` | Post a comment or reply | | `deleteComment` | `(commentId: string) => Promise` | Delete a comment | | `updateStatus` | `(input: UpdateStatusInput) => Promise` | `PATCH` the record, then log a status update | | `isUpdatingStatus` | `boolean` | Status mutation pending | ### UpdateStatusInput | Field | Type | Description | |-------|------|-------------| | `statusFieldSlug` | `string` | Status field slug (required) | | `value` | `string` | New status option id (required) | | `secondaryValue` | `string \| null` | Sub-status option id | | `description` | `string \| null` | Note | | `followupDate` | `string \| null` | Follow-up date | | `writeCompanions` | `boolean` | Also `PATCH` the `___*` companion columns. Default `true`. Set `false` for a plain `field-select` | ## Notes - **Files are on by default.** The documents source adds one request per record; pass `sources={{ files: false }}` to keep the previous behaviour (uploads then stay as bare audit traces). - **Related chips.** A comment's `assigned_to` becomes a related chip automatically (resolved against the users list). Everything else is opt-in through `relatedColumns` — the hook never guesses a tenant's relation slugs. ## Type Exports | Type | Description | |------|-------------| | `UseDocyrusContactActivityOptions` / `UseDocyrusContactActivityResult` | Options and result | | `ContactActivityClient` | Minimal REST client interface | | `ContactActivitySources` | Source toggles | | `EventTypeNameHints` | Call / meeting name hints | | `UpdateStatusInput` | Status mutation input | | `ContactActivityPanelData` | The panel props the hook fills |