Customer-scoped ticket list hook that wraps `POST /api/chat/agent/find-ticket`, returning paginated results with filtering support for search text and ticket status. ## Key Components ### `UseTicketsListFilters` Input interface controlling the query: - `customerEmail` — required identity (drilled from parent to avoid race conditions with `useChatIdentity`) - `search` — free-text FTS filter; empty string returns all tickets - `status` — `'open'` | `'closed'` | `'all'` (empty/`'all'` omits the filter) - `page` / `pageSize` — 1-based pagination; server caps `pageSize` at 100 ### `UseTicketsListReturn` Output shape: - `tickets` — current page rows - `isLoading` — true when `data === undefined` or fetching with zero results (avoids TanStack v5 flag race conditions) - `totalCount` / `page` / `pageSize` / `totalPages` — server-echoed pagination metadata; `totalPages` is clamped to ≥ 1 - `lastUpdatedAt` — wall-clock timestamp of last successful fetch ### `useTicketsList(filters)` Core hook. Key behaviors: - Disabled when `customerEmail` is falsy (short-circuits the fetch) - Cache keyed by `['tickets', 'self', identity, search, status, page, pageSize]` — each filter/page combo gets its own slot - `staleTime: 0`, `gcTime: 0`, `refetchOnMount: 'always'` — deliberately no caching (live customer data) - Endpoint resolved from `useRequiredChatRuntime()` for reverse-proxy compatibility ## Usage Example ```typescript const { tickets, isLoading, totalCount, totalPages, page, refetch, } = useTicketsList({ customerEmail: identity.user.email, search: searchQuery, status: 'open', page: currentPage, pageSize: 20, }) ``` > Invalidate all ticket slots after mutations via `queryClient.invalidateQueries({ queryKey: ['tickets'] })`.