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.
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.
| 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 |
localStorage (se rememberMe) ou sessionStorageaccessToken é injetado automaticamente no cliente HTTP via setAccessToken()/login automaticamenteimport { 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.
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.
| 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 |
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).
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);
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.
| 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 |
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();
Arquivo: src/composables/useSearch.js
Padrão: Instância por componente
Busca semântica nos documentos da base de conhecimento.
| 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 |
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 }]
Arquivo: src/composables/useToast.js
Padrão: Instância por componente (wrapper de vue-toastification)
Exibe notificações toast no canto da tela.
| 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 |
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.");
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).
| 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 |
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);