architecture.md 6.9 KB

Arquitetura — Frontend

Estrutura de pastas

frontend/src/
├── api/              Funções de chamada HTTP (uma por domínio)
├── components/       Componentes Vue reutilizáveis
│   ├── base/         Design system: BaseButton, BaseBadge, BaseModal
│   └── skeletons/    Skeletons de carregamento
├── composables/      Estado e lógica reutilizável (useAuth, useChat, etc.)
├── docs/             Documentação do frontend
├── layout/           Layouts de página (LayoutSistema.vue)
├── router/           Configuração do Vue Router
├── styles/           CSS global e variáveis de tema
├── utils/            Utilitários genéricos
└── views/            Páginas da aplicação
    ├── atendimentos/     AtendimentoView, AvaliacoesView, GoldenSetView, NaoResolvidosView, RankingAtendentesView
    ├── auth/             LoginView
    ├── configuracoes/
    ├── conversas/        ConversasHistoricoView, ConversasPesquisarView, ConversasWhatsappView
    ├── documentos/       DocumentosView, CarregarDocumentoView
    ├── pagina-inicial/
    └── usuarios/

Design system e componentes reutilizáveis em components.md.

Roteamento

O Vue Router está configurado em src/router/index.js. Todas as rotas autenticadas usam o meta requiresAuth: true, e a rota de login usa guestOnly: true.

Rota Nome Componente Acesso
/login login LoginView Apenas não autenticados
/ home PaginaInicialView Autenticados
/conversas/historico conversas-historico ConversasHistoricoView Autenticados
/conversas/pesquisar conversas-pesquisar ConversasPesquisarView Autenticados
/conversas-whatsapp conversas-whatsapp ConversasWhatsappView Autenticados
/configuracoes configuracoes ConfiguracoesView Autenticados
/usuarios usuarios UsuariosView Admin (nivelMinimo)
/atendimentos/avaliacoes avaliacoes AvaliacoesView Admin (nivelMinimo)
/atendimentos/nao-resolvidos atendimentos-nao-resolvidos NaoResolvidosView Admin (nivelMinimo)
/atendimentos/ranking-atendentes ranking-atendentes RankingAtendentesView Admin (nivelMinimo)
/atendimentos/:id atendimento AtendimentoView Admin (nivelMinimo)
/atendimentos/golden-set golden-set GoldenSetView Admin (nivelMinimo)
/documentos documentos DocumentosView Admin (nivelMinimo)
/documentos/carregar documentos-carregar CarregarDocumentoView Admin (nivelMinimo)

Todas as rotas usam lazy loading (() => import(...)) — nenhuma view é importada estaticamente no router.

Guard de rota (router.beforeEach):

  • Usuário não autenticado tentando rota requiresAuth → redirecionado para /login (com ?redirect= de volta)
  • Usuário autenticado tentando rota guestOnly (/login) → redirecionado para /
  • Usuário sem o nivelMinimo exigido pela rota → redirecionado para /configuracoes
  • Falha ao carregar um chunk lazy (deploy novo com o usuário na aba antiga) → tenta um reload automático da página uma vez; se falhar de novo, mostra um banner (chunkLoadError) em vez de loop

Layout do sistema

src/layout/LayoutSistema.vue é o layout padrão de todas as páginas autenticadas. Ele contém:

  • Barra de navegação lateral com lista de conversas
  • Área principal de conteúdo (slot padrão)
  • Integração com useChat para carregar e exibir as conversas na sidebar

Estado da aplicação

O frontend não usa Pinia. O estado é gerenciado por composables (src/composables/), a maioria com padrão singleton:

  • useAuth — singleton via closure (session é um ref no escopo do módulo)
  • useChat — singleton explícito (variável singleton no escopo do módulo)
  • useListaAvaliacoes — instância por componente; estado compartilhado por AvaliacoesView e NaoResolvidosView (paginação, busca com debounce, sincronização com a query string)
  • useConversas, useConversaEdicao, useWhatsappConexao, useDocumentos — estado do chat de atendente (WhatsApp) e da tela de documentos, instância por componente
  • useSearch, useToast, useUsers, useMenuUsuario, useSidebar, useTheme, useRouteLoading, useValorDebounced, useAsyncState — instâncias por componente ou utilitários sem estado próprio compartilhado

Consulte composables.md para detalhes de cada um (documenta os principais; nem todos os listados acima têm entrada própria lá).

Camada de API

Os arquivos em src/api/ encapsulam as chamadas HTTP, um por domínio. Todos usam o client.js (que faz fetch com injeção de token e refresh automático). Referência de endpoints em backend/docs/api.md:

src/api/
├── client.js         Cliente HTTP com interceptor de auth e refresh automático (apiFetch, fetchAutenticado)
├── auth.js           loginRequest, logoutRequest, refreshTokenRequest, solicitarResetSenha
├── chat.js           sendChatStream, ingestDocuments, ingestFile, ingestUrl,
│                     search, listDocuments, deleteDocumentsBySource
├── chatConversas.js  CRUD de conversas do chat: listConversations, createConversation,
│                     getConversationMessages, updateConversationTitle, deleteConversation, exportConversation
├── atendimentos.js   sincronização, avaliação, golden set, ranking de atendentes e relatórios PDF
├── conversas.js      chat de atendente via WhatsApp: listarConversas, responderConversa, gerarSugestaoResposta, ...
├── whatsappConexao.js statusWhatsapp
└── users.js          listUsers, createUser, updateUser, toggleUserStatus, reset de senha

Chat, busca, ingest e documentos vivem em chat.js — não há documents.js/ingest.js separados. conversations.js não existe: o CRUD de conversas do chat é chatConversas.js, para não colidir com conversas.js (chat de atendente via WhatsApp, domínio diferente).

Fluxo de autenticação no frontend

1. Ao montar o app, useAuth lê o token salvo em localStorage ou sessionStorage
2. O token é injetado no client.js via setAccessToken()
3. O wrapper de `fetch` em `client.js` captura respostas 401 e tenta refresh automático
4. Se o refresh falha, setAuthErrorCallback() é chamado → sessão limpa → redirect /login
5. O refresh proativo (scheduleProactiveRefresh) renova o token 60s antes de expirar

Detalhes do composable em composables.md; fluxo e níveis de acesso do lado backend em backend/docs/auth.md.

Tema (light/dark)

O tema é controlado pela classe .dark no elemento <html>. O componente BotaoAlterarTema.vue alterna entre os dois modos. Consulte style.md para o sistema de cores.