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.
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):
requiresAuth → redirecionado para /login (com ?redirect= de volta)guestOnly (/login) → redirecionado para /nivelMinimo exigido pela rota → redirecionado para /configuracoeschunkLoadError) em vez de loopsrc/layout/LayoutSistema.vue é o layout padrão de todas as páginas autenticadas. Ele contém:
useChat para carregar e exibir as conversas na sidebarO 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 componenteuseSearch, useToast, useUsers, useMenuUsuario, useSidebar, useTheme, useRouteLoading, useValorDebounced, useAsyncState — instâncias por componente ou utilitários sem estado próprio compartilhadoConsulte composables.md para detalhes de cada um (documenta os principais; nem todos os listados acima têm entrada própria lá).
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.jsseparados.conversations.jsnão existe: o CRUD de conversas do chat échatConversas.js, para não colidir comconversas.js(chat de atendente via WhatsApp, domínio diferente).
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.
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.