composables.md 8.6 KB

Composables

Lógica reutilizável em src/composables/. useAuth e useChat são singletons — o estado é compartilhado entre todos os componentes que os importam. Visão geral de onde cada composable entra na aplicação em architecture.md.


useAuth

Arquivo: src/composables/useAuth.js Padrão: Singleton (estado no escopo do módulo)

Gerencia a sessão do usuário: login, logout, persistência de token e refresh proativo. Reflete os níveis de acesso definidos em backend/docs/auth.md.

O que expõe

Nome Tipo Descrição
session Readonly<Ref> Sessão completa (usuario, accessToken, refreshToken, rememberMe)
user ComputedRef Objeto do usuário logado (null se não autenticado)
nivel ComputedRef<Number> Nível do usuário como número (NaN se ausente/inválido, o que nega acesso em qualquer comparação)
isAdmin ComputedRef<Boolean> true se nivel >= NIVEL_ADMIN (3). Use este, não reimplemente a checagem na view
isAuthenticated ComputedRef<Boolean> true se há usuário com Id na sessão
login(params) Function Faz login; params: { login, senha, rememberMe? }
logout() Function Revoga o token e limpa a sessão

Comportamento

  • A sessão é salva em localStorage (se rememberMe) ou sessionStorage
  • O accessToken é injetado automaticamente no cliente HTTP via setAccessToken()
  • O refresh proativo agenda a renovação 60s antes do accessToken expirar
  • Se o refresh falhar, o usuário é redirecionado para /login automaticamente

Exemplo

import { useAuth } from "@/composables/useAuth.js";

const { user, isAdmin, isAuthenticated, login, logout } = useAuth();

// Login
await login({ login: "usuario@empresa.com", senha: "123456", rememberMe: true });

// Verificar nível
if (isAdmin.value) { /* admin */ }

// Logout
await logout();

O router usa o mesmo nivel para autorizar: uma tela restrita se declara com meta: { nivelMinimo: NIVEL_ADMIN } e o guard global cuida do resto — não há lista de rotas protegidas espalhada pelo beforeEach.


useListaAvaliacoes

Arquivo: src/composables/useListaAvaliacoes.js Padrão: Instância por componente

Estado compartilhado pelas listas de avaliações de atendimento (AvaliacoesView e NaoResolvidosView): paginação, busca com debounce de 400 ms, ordenação, sincronização com a query string e o item expandido — incluindo a rolagem de volta até ele quando se volta da tela de conversa completa. Usa useAsyncState por baixo, então respostas atrasadas de filtros antigos são descartadas.

O que difere entre as duas telas (filtros próprios, formato dos stats, ações em lote) fica na view; só entra aqui o que é idêntico nas duas.

Opções

Nome Tipo Descrição
montarQueryExtra Function Chaves de query específicas da view (só as preenchidas)
montarFiltrosApi Function Filtros específicos repassados a listarAvaliacoes()
aoAplicarFiltros Function? Chamado quando os filtros mudam — normalmente o carregarStats da view
prefixoElemento String Prefixo do id no DOM, usado no scroll de retorno
mensagemErroLista String Mensagem de fallback quando a listagem falha
pageSize Number Padrão 20

O que expõe

busca, ordenacao, page, expandido, setores, avaliacoes, total, totalPaginas, carregando, erro, carregarLista, carregarSetores, aplicarFiltros, alternarOrdenacao, onBuscaInput, onBuscaEnter, irParaPagina, alternarExpandido, verConversa, sincronizarQuery, inicializar.

Exporta também queryTexto(route, chave, padrao), para ler um filtro da query string ignorando arrays (?x=1&x=2).

Exemplo

const { avaliacoes, carregando, aplicarFiltros, inicializar } = useListaAvaliacoes({
  montarQueryExtra: () => (filtroSetor.value ? { setor: filtroSetor.value } : {}),
  montarFiltrosApi: () => ({ setor: filtroSetor.value || undefined }),
  aoAplicarFiltros: carregarStats,
  prefixoElemento: "avaliacao",
  mensagemErroLista: "Falha ao carregar avaliações"
});

onMounted(inicializar);

useChat

Arquivo: src/composables/useChat.js Padrão: Singleton explícito

Gerencia todo o estado do chat: lista de conversas, mensagens ativas, envio de mensagens via stream SSE.

O que expõe

Nome Tipo Descrição
conversations Ref<Array> Lista de conversas do usuário
activeConversationId Ref<String\|null> ID da conversa ativa
messages Ref<Array> Mensagens da conversa ativa
loading Ref<Boolean> true enquanto uma resposta está sendo gerada
error Ref<String> Mensagem de erro do último envio
conversationsLoading Ref<Boolean> true enquanto carrega a lista de conversas
conversationsError Ref<String> Erro ao carregar conversas
conversationsHasMore Ref<Boolean> Há mais conversas para paginar
send(content) Function Envia mensagem; cria conversa se não houver ativa
newConversation() Function Limpa mensagens e define nova conversa (sem ID)
setActiveConversation(id) Function Carrega mensagens de uma conversa existente
renameConversation(id, title) Function Renomeia uma conversa
deleteConversation(id) Function Remove uma conversa e suas mensagens
exportConversation(id) Function Faz download da conversa em Markdown
searchConversations(query) Function Filtra conversas pelo título (client-side)
loadConversationsList() Function Recarrega a lista do início
loadMoreConversations() Function Carrega próxima página de conversas
clearError() Function Limpa error
cancelCurrentStream() Function Cancela o stream SSE em andamento

Exemplo

import { useChat } from "@/composables/useChat.js";

const { messages, loading, send, newConversation, setActiveConversation } = useChat();

// Enviar mensagem
await send("Qual é a política de férias da empresa?");

// Abrir conversa existente
await setActiveConversation(42);

// Nova conversa
newConversation();

useSearch

Arquivo: src/composables/useSearch.js Padrão: Instância por componente

Busca semântica nos documentos da base de conhecimento.

O que expõe

Nome Tipo Descrição
results Ref<Array> Resultados da busca ([{ content, source, score }])
loading Ref<Boolean> true durante a busca
error Ref<String> Mensagem de erro
run(query) Function Executa a busca com a query informada

Exemplo

import { useSearch } from "@/composables/useSearch.js";

const { results, loading, error, run } = useSearch();

await run("política de benefícios");
// results.value → [{ content: "...", source: "rh/beneficios.pdf", score: 0.92 }]

useToast

Arquivo: src/composables/useToast.js Padrão: Instância por componente (wrapper de vue-toastification)

Exibe notificações toast no canto da tela.

O que expõe

Método Descrição
sucesso(msg) Toast verde de sucesso
erro(msg) Toast vermelho de erro
info(msg) Toast azul informativo
aviso(msg) Toast âmbar de aviso

Exemplo

import { useToast } from "@/composables/useToast.js";

const toast = useToast();

toast.sucesso("Documento enviado com sucesso!");
toast.erro("Não foi possível excluir o documento.");
toast.info("Processando o arquivo...");
toast.aviso("A sessão expira em 5 minutos.");

useUsers

Arquivo: src/composables/useUsers.js Padrão: Estado compartilhado via refs no escopo do módulo

Gerencia a lista de usuários do sistema (apenas para administradores).

O que expõe

Nome Tipo Descrição
users Ref<Array> Lista de usuários carregados
loading Ref<Boolean> true durante carregamento
error Ref<String> Erro ao carregar
loadUsers() Function Busca a lista de usuários da API
createUser(data) Function Cria usuário; atualiza users automaticamente
updateUser(id, data) Function Atualiza usuário; atualiza users automaticamente
toggleStatus(id) Function Ativa/desativa usuário; atualiza users automaticamente

Exemplo

import { useUsers } from "@/composables/useUsers.js";

const { users, loading, loadUsers, createUser, toggleStatus } = useUsers();

await loadUsers();

await createUser({ nome: "Maria", login: "maria", senha: "abc123", nivel: "1" });

await toggleStatus(5);