Custom Hooks
Total: 9 hooks
useAuth
Seção intitulada “useAuth”Arquivo: src/hooks/use-auth.ts
Hook de autenticação. Busca user e account do Supabase. Gerencia login/logout.
| Campo | Tipo | Descrição |
|---|---|---|
userId | string | null | ID do usuário |
account | Account | null | Conta ativa |
role | AccountRole | null | Role na conta ativa |
accounts | AccountWithRole[] | Todas as contas |
isLoading | boolean | Estado de carregamento |
isAdmin | boolean | Se e platform admin |
supportMode | object | null | Support mode info |
logout | () => Promise<void> | Função de logout |
Comportamento
Seção intitulada “Comportamento”- No mount, busca
supabase.auth.getUser() - Se autenticado, busca
/api/accountspara obter contas + active_account_id - Determina conta ativa: cookie > store > primeira da lista
- Persiste em
useAuthStore - Escuta
onAuthStateChangepara redirect em SIGNED_OUT - Logout:
supabase.auth.signOut()+ clearAuth + redirect
AppLayout(garante auth em toda area protegida)SettingsLayout(botao logout)TrackingPageProfileSettingsPage
useApiQuery<T>
Seção intitulada “useApiQuery<T>”Arquivo: src/hooks/use-api-query.ts
Hook genérico para GET requests com cache e AbortController.
| Param | Tipo | Default | Descrição |
|---|---|---|---|
url | string | null | required | URL da API. null desabilita a query. |
options.enabled | boolean | true | Se a query deve ser executada |
options.refreshInterval | number | 0 | Intervalo de refresh em ms (0 = sem refresh) |
options.refreshWhenHidden | boolean | true | Se deve fazer refresh quando tab está hidden |
| Campo | Tipo | Descrição |
|---|---|---|
data | T | null | Dados retornados |
isLoading | boolean | Estado de carregamento |
error | string | null | Mensagem de erro |
refetch | () => Promise<void> | Função para re-buscar dados |
Comportamento
Seção intitulada “Comportamento”- Faz
fetch(url)comAbortController - Cancela request anterior ao fazer nova (abort)
- Extrai
json.data ?? jsondo response - Suporta refresh periodico via
setInterval - Re-fetch automático quando
urlouenabledmudam
Usado em praticamente TODAS as páginas do app (Dashboard, Chat, Contacts, Analytics, etc.).
useApiMutation<TInput>
Seção intitulada “useApiMutation<TInput>”Arquivo: src/hooks/use-api-mutation.ts
Hook genérico para POST/PUT/PATCH/DELETE requests com toast notifications.
Params (options)
Seção intitulada “Params (options)”| Param | Tipo | Default | Descrição |
|---|---|---|---|
method | "POST" | "PUT" | "PATCH" | "DELETE" | "POST" | Método HTTP |
successMessage | string | undefined | Mensagem de sucesso (toast) |
onSuccess | (data: unknown) => void | undefined | Callback após sucesso |
| Campo | Tipo | Descrição |
|---|---|---|
mutate | (url: string, body?: TInput) => Promise<unknown | null> | Função de mutação |
isLoading | boolean | Estado de carregamento |
error | string | null | Mensagem de erro |
Comportamento
Seção intitulada “Comportamento”- Faz
fetch(url, { method, body: JSON.stringify(body) }) - Em sucesso: toast success (se configurado) + chama onSuccess
- Em erro: toast error + retorna null
- Extrai
data?.data ?? datado response
Usado em todas as operações de escrita (criar contato, atualizar template, excluir automação, etc.).
usePáginatedQuery<T>
Seção intitulada “usePáginatedQuery<T>”Arquivo: src/hooks/use-páginated-query.ts
Hook para queries com paginação offset-based (page + limit).
| Param | Tipo | Default | Descrição |
|---|---|---|---|
fetcher | (params) => Promise<PáginatedResult<T>> | required | Função de fetch |
options.initialPage | number | 1 | Página inicial |
options.initialLimit | number | 20 | Itens por página |
options.initialSearch | string | "" | Busca inicial |
| Campo | Tipo | Descrição |
|---|---|---|
data | T[] | Dados da página atual |
total | number | Total de itens |
page | number | Página atual |
totalPages | number | Total de páginas |
search | string | Busca atual |
isLoading | boolean | Estado de carregamento |
setPage | (page: number) => void | Navegar para página |
setSearch | (search: string) => void | Alterar busca (reseta page=1) |
refresh | () => void | Recarregar página atual |
useCursorPáginatedQuery<T>
Seção intitulada “useCursorPáginatedQuery<T>”Arquivo: src/hooks/use-cursor-páginated-query.ts
Hook para queries com paginação cursor-based (infinite scroll).
| Param | Tipo | Default | Descrição |
|---|---|---|---|
baseUrl | string | required | URL base da API |
options.limit | number | 20 | Itens por página |
options.enabled | boolean | true | Se a query deve ser executada |
| Campo | Tipo | Descrição |
|---|---|---|
data | T[] | Todos os dados carregados (acumulados) |
isLoading | boolean | Loading da primeira página |
isLoadingMore | boolean | Loading de páginas adicionais |
hasMore | boolean | Se existem mais itens |
loadMore | () => void | Carregar proxima página |
refetch | () => void | Recarregar desde o início |
Comportamento
Seção intitulada “Comportamento”- Acumula dados (append) ao fazer loadMore
refetch()reseta cursor e recarrega do zeroAbortControllerpara cancelar requests pendentes- Response esperado:
{ data: T[], nextCursor: string | null, hasMore: boolean }
ContactsPage: lista de contatos com infinite scroll
useRealtimeConversations
Seção intitulada “useRealtimeConversations”Arquivo: src/hooks/use-realtime-conversations.ts
Hook para escutar mudancas em tempo real na tabela conversations via Supabase Realtime.
| Param | Tipo | Descrição |
|---|---|---|
accountId | string | null | ID da conta (filter) |
onInsert | (conversation) => void | Callback para nova conversa |
onUpdate | (conversation) => void | Callback para conversa atualizada |
Comportamento
Seção intitulada “Comportamento”- Cria channel Supabase:
conversations:{accountId} - Escuta
postgres_changes(INSERT + UPDATE) na tabelaconversations - Filtra por
account_id=eq.{accountId} - Cleanup: remove channel no unmount
ChatPage: refetch conversas em INSERT e UPDATE
useRealtimeMessages
Seção intitulada “useRealtimeMessages”Arquivo: src/hooks/use-realtime-messages.ts
Hook para escutar mudancas em tempo real na tabela messages via Supabase Realtime.
| Param | Tipo | Descrição |
|---|---|---|
conversationId | string | null | ID da conversa ativa |
Comportamento
Seção intitulada “Comportamento”- Cria channel Supabase:
messages:{conversationId} - Escuta
postgres_changes(INSERT + UPDATE) na tabelamessages - INSERT:
addMessageno chat store - UPDATE:
updateMessageStatusno chat store - Cleanup: remove channel no unmount
ChatPage: adiciona mensagens em tempo real e atualiza status
useOnboarding
Seção intitulada “useOnboarding”Arquivo: src/hooks/use-onboarding.ts
Hook para gerenciar checklist de onboarding no dashboard.
| Param | Tipo | Descrição |
|---|---|---|
stats | OnboardingStats | null | Stats do dashboard |
profiles | OnboardingProfile[] | WhatsApp profiles |
accountId | string | null | ID da conta |
| Campo | Tipo | Descrição |
|---|---|---|
isDismissed | boolean | Se usuário dismissou o checklist |
steps | OnboardingStep[] | 5 steps com id, label, href, completed |
progress | number | Quantos steps completos (0-5) |
isComplete | boolean | Se todos os 5 steps estão completos |
dismiss | () => void | Função para dismissar |
- Conta criada — sempre true
- WhatsApp conectado — profile com status “connected”
- Primeiro template criado — kpi.templates > 0
- Contatos importados — kpi.contacts > 0
- Primeira campanha enviada — alguma campanha com status != “draft”
Persistência
Seção intitulada “Persistência”- Dismiss salvo em
localStoragecom keyx17-onboarding-dismissed-{accountId}
useUndoRedo
Seção intitulada “useUndoRedo”Arquivo: src/hooks/use-undo-redo.ts
Hook para undo/redo no editor de automações.
| Param | Tipo | Descrição |
|---|---|---|
setNodes | (updater) => void | Setter de nodes do ReactFlow |
setEdges | (updater) => void | Setter de edges do ReactFlow |
| Campo | Tipo | Descrição |
|---|---|---|
takeSnapshot | (nodes, edges) => void | Salva estado atual no histórico |
undo | () => void | Desfaz última ação |
redo | () => void | Refaz última ação desfeita |
canUndo | boolean | Se pode desfazer |
canRedo | boolean | Se pode refazer |
Comportamento
Seção intitulada “Comportamento”- Usa
useRefpara histórico (past + future stacks) MAX_HISTORY = 50snapshotstakeSnapshot: push no past, limpa futureundo: pop do past, push no future, aplica estadoredo: pop do future, push no past, aplica estado- Usa
structuredClonepara deep copy
AutomationEditorPage: Ctrl+Z / Ctrl+Shift+Z / Ctrl+Y- Chamado antes de cada operação destrutiva (add node, delete node, drop, connect)