# Análise da Codebase e Contrato Backend → Frontend ## Objetivo Este documento resume a análise da codebase do projeto e define **o que o backend precisa entregar para o frontend**. Hoje o backend tem apenas as rotas: - `POST /login` - `POST /register` Mas o frontend já possui diversas telas prontas. Portanto, este arquivo serve como **mapa de implementação do backend**, indicando: - o estado atual do projeto; - o que cada tela do frontend precisa receber; - quais endpoints precisam existir; - quais formatos de payload e resposta são recomendados; - quais partes da modelagem atual já suportam isso e quais ainda não suportam. --- ## 1. Estrutura da codebase ## Frontend Pasta: `nettown_frontend` Stack identificada: - `SvelteKit` - `adapter-static` - `Svelte 5` - `Tailwind` - `layerchart` - `lucide-svelte` ### Achados principais do frontend - O frontend está **visualmente completo** para várias áreas do produto. - O frontend está **quase 100% mockado**. - **Não existe client HTTP real** no frontend hoje. - **Não há `fetch`, `axios`, `Authorization` ou persistência de JWT** implementados nas telas principais. - A tela de login ainda usa validação mockada: - e-mail: `admin@nettown.com` - senha: `admin` - Várias telas consomem dados de: - `src/lib/core/models/mock-data.js` - `src/lib/features/sentiment/data/sentiment-dashboard.mock.js` - Existem rotas duplicadas em PT/EN para algumas telas: - `profile` e `perfil` - `subscription` e `assinatura` - `help` e `ajuda` ### Conclusão sobre o frontend O frontend está pronto como **produto visual e funcional local**, mas **não está integrado ao backend**. Ou seja: - a parte de layout/componentes está pronta; - a parte de contratos de API ainda precisa ser implementada. --- ## Backend Pasta: `php_api` Stack identificada: - `PHP` - `FrameworkX` - `Firebase JWT` - `PostgreSQL` - `PDO` ### Rotas atuais do backend - `POST /login` - `POST /register` - `GET /jwthelloworld` protegido por JWT ### Padrão de resposta atual do backend O backend hoje responde com envelope padrão: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": {} } ``` Em erro: ```json { "status": "failed", "msg": "mensagem de erro", "code": "E_VALIDATE", "data": {} } ``` ### Autenticação atual - Login usa `email` + `password`. - JWT contém: - `sub` - `email` - `company_id` - `role` - Middleware JWT valida usuário ativo por `user_deleted_at = 'infinity'`. ### Conclusão sobre o backend O backend já está preparado para: - autenticação com JWT; - conexão PostgreSQL; - leitura do banco novo. Mas **a camada de API de produto ainda não foi construída**. --- ## 2. Banco atual vs necessidade do frontend ## Tabelas que já suportam bem o frontend - `company` - `user` - `operator` - `operator_channel` - `sla_config` - `integration` - `client` - `conversation` - `message` - `message_attachment` - `message_reaction` - `conversation_participant` - `webhook_event` - `conversation_analysis` - `aspect_feedback` - `emotion_snapshot` - `public_opinion` - `alert` - `ai_action` - `persona` - `client_persona` - `best_action` - `volume_snapshot` - `sentiment_evolution` - `playbooks_monitor` - `operator_daily_stats` - `kpi_snapshot` ## Gaps entre frontend e schema atual Estas são as principais lacunas identificadas: - **Filtro de unidade** - O frontend usa filtro de `unidade` em várias telas. - O schema atual **não tem tabela explícita de unidade/loja/filial**. - **Configuração de alerta de SLA por percentual** - A tela de SLA usa `alertPct`. - A tabela `sla_config` hoje guarda apenas: - `sla_config_response_hours` - `sla_config_resolution_hours` - **Não existe coluna de percentual de alerta**. - **Configurações / notificações** - O frontend de configurações mostra preferências e integrações. - O schema atual **não tem tabela dedicada para preferências/notificações**. - **Assinatura / billing** - O frontend possui telas de assinatura e planos. - O schema atual **não tem modelagem de assinatura/plano/cobrança**. - **Ajuda / FAQ / suporte** - O frontend tem tela pronta. - Isso pode ser estático, mas **não existe modelagem específica** hoje. --- ## 3. Mapa de telas do frontend ## Públicas - `/` - landing page institucional - não depende de backend para funcionar - `/login` - hoje mockada - deve passar a consumir `POST /login` ## Privadas - `/dashboard` - `/dashboard/interactions` - `/dashboard/analytics` - `/dashboard/personas` - `/dashboard/evolucao` - `/dashboard/executive` - `/dashboard/agents` - `/dashboard/sla` - `/dashboard/settings` - `/dashboard/profile` - `/dashboard/subscription` - `/dashboard/help` Rotas duplicadas equivalentes: - `/dashboard/perfil` - `/dashboard/assinatura` - `/dashboard/ajuda` --- ## 4. Situação real por tela ## 4.1 Login ### Estado atual - tela pronta; - autenticação ainda fake; - não salva token; - não consulta `GET /me`; - não protege navegação real por sessão. ### Backend precisa entregar - `POST /login` - `GET /me` ### Contrato recomendado #### `POST /login` Request: ```json { "email": "admin@empresa.com", "password": "12345678" } ``` Response: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "token": "jwt-token", "user": { "user_id": 1, "company_id": 1, "user_name": "Admin", "user_phone": "5511999999999", "user_email": "admin@empresa.com", "user_role": "admin", "user_created_at": "2026-05-25T10:00:00Z" } } } ``` #### `GET /me` Objetivo: - reidratar sessão no refresh da página; - preencher header do app; - popular perfil. Response: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "user_id": 1, "company_id": 1, "user_name": "Admin", "user_phone": "5511999999999", "user_email": "admin@empresa.com", "user_role": "admin", "company": { "company_id": 1, "company_name": "Empresa X", "company_cnpj": "12345678000199", "company_logo": "https://..." } } } ``` --- ## 4.2 Dashboard principal (`/dashboard`) ### Estado atual Hoje a tela usa mocks para: - KPIs do topo; - fila priorizada; - radar emocional; - volume por canal; - distribuição por aspectos; - drilldown por aspecto. ### Backend precisa entregar #### `GET /dashboard/overview` Query params sugeridos: - `period=today|yesterday|week` - `unit=all|flagship|franquias|pop-up|digital` - `area=all|atendimento|produto|logistica|marketing` - `sentiment=all|positive|neutral|negative` - `volume_view=hour|day` ### Response recomendada ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "kpis": { "registeredUsers": 55, "activeAgents": 4, "totalConversations": 418, "generalSentimentScore": 0.1, "unregisteredUsers": 149682 }, "priorityQueue": [ { "id": 1, "customerName": "Carolina Ribeiro", "segment": "Elegante Estratégica", "status": "VENDEDORA NÃO RESPONDEU", "slaStatus": "SLA 12h estourado", "timeAgo": "há 18h", "sellerName": "Maria", "lastMessage": "Não tem no meu tamanho 40?", "motive": "Pediu tamanho indisponível — reservar/repor", "impact": 8639, "ticket": 879, "chance": 82, "optimumWindow": "6h", "score": 7084, "conversationId": 101, "clientId": 51, "operatorId": 7 } ], "radarData": [ { "name": "Confiança", "value": 45 }, { "name": "Alegria", "value": 100 }, { "name": "Antecipação", "value": 41 }, { "name": "Medo", "value": 18 }, { "name": "Tristeza", "value": 3 }, { "name": "Raiva", "value": 13 } ], "volumeData": [ { "date": "2026-05-02T11:00:00Z", "whatsapp": 10 }, { "date": "2026-05-02T12:00:00Z", "whatsapp": 230 } ], "aspectsData": [ { "aspect": "Atendimento", "positive": 350, "neutral": 50, "negative": 20 }, { "aspect": "Produto", "positive": 130, "neutral": 30, "negative": 40 } ], "aspectsDrilldown": { "Atendimento": { "positive": [ { "label": "Satisfação com atendimento", "value": 285 } ], "neutral": [], "negative": [] } } } } ``` ### Fontes no banco - `kpi_snapshot` - `alert` - `conversation` - `client` - `operator` - `emotion_snapshot` - `volume_snapshot` - `conversation_analysis` --- ## 4.3 Interações (`/dashboard/interactions`) ### Estado atual Hoje a tela mostra: - listagem de conversas analisadas; - filtros rápidos; - modal com chat; - mini relatório lateral. ### Backend precisa entregar - `GET /interactions` - `GET /interactions/details` #### `GET /interactions` Query params sugeridos: - `page` - `per_page` - `search` - `filter=all|my_clients|new|unfinished` - `sentiment` - `operator_id` - `company_id` Response: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "items": [ { "conversationId": 201, "client": "554196690452", "agent": "Leticia", "sentiment": "CONTENTAMENTO", "score": 0.5, "aspect": "Atendimento", "subaspect": "Informativo", "datetime": "2026-05-02T19:59:00Z" } ], "pagination": { "page": 1, "per_page": 20, "total": 120, "total_pages": 6 } } } ``` #### `GET /interactions/details` Query params sugeridos: - `conversation_id` Response: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "conversation": { "conversationId": 201, "client": "554196690452", "channel": "WhatsApp", "agent": "Leticia" }, "thread": [ { "id": "m1", "isAgent": false, "text": "Oi, queria saber se esse look chega na loja física.", "time": "19:58", "date": "2026-05-02" }, { "id": "m2", "isAgent": true, "text": "Chega sim, posso te mostrar opções.", "time": "19:59", "date": "2026-05-02" } ], "report": { "avgResponse": "04:03", "totalDuration": "08:28", "avgAgent": "00:00", "avgClient": "08:05", "mainAspect": "Atendimento", "subAspect": "Informativo", "lastMessageAuthor": "Cliente", "consecutiveMessages": false, "sentiment": "CONTENTAMENTO", "score": 0.5 } } } ``` ### Fontes no banco - `conversation` - `message` - `conversation_analysis` - `client` - `operator` --- ## 4.4 Análise de sentimento (`/dashboard/analytics`) ### Estado atual Hoje a tela trabalha com um view model único contendo: - cards-resumo; - alertas; - linha temporal de ganhos/perdas; - lista de aspectos com frases reais. ### Backend precisa entregar #### `GET /analytics/sentiment/dashboard` Query params sugeridos: - `timeframe=day|week|month` - `company_id` - `aspect` - `sentiment` Response: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "summaryCards": [ { "id": "atRiskClients", "label": "Clientes em risco", "value": 23, "image": "/images/sentiment/risk.svg" }, { "id": "opportunities", "label": "Oportunidades", "value": 41, "image": "/images/sentiment/opportunity.svg" } ], "alerts": [ { "id": "alert-1", "clientId": 12, "clientName": "Grupo Horizonte", "title": "Grupo Horizonte com alta chance de churn", "description": "Queda de engajamento nas últimas 2 semanas.", "priority": "high", "priorityLabel": "Alta prioridade", "category": "churn_risk" } ], "timelineViews": { "day": [ { "period": "Dia 1", "gains": 28, "losses": 12 } ], "week": [ { "period": "Sem 1", "gains": 38, "losses": 16 } ], "month": [ { "period": "Jan", "gains": 180, "losses": 75 } ] }, "aspects": [ { "id": "atendimento", "name": "Atendimento", "volume": 14, "positive": [ { "text": "Fui respondida super rápido.", "client": "Maria Silva" } ], "neutral": [], "negative": [] } ] } } ``` ### Fontes no banco - `alert` - `public_opinion` - `aspect_feedback` - `conversation_analysis` - `client` - `conversation` --- ## 4.5 Personas (`/dashboard/personas`) ### Estado atual A tela precisa de: - KPIs de personas; - estatísticas gerais; - cards de personas; - detalhes da persona selecionada; - next best action. ### Backend precisa entregar #### `GET /personas/overview` Query params sugeridos: - `period=week|month|quarter` - `unit` - `area` - `sentiment=all|positive|neutral|negative` Response: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "kpis": { "active": 5, "churn": 60.1, "loss": 7521.27, "potentialLabel": "Neutro" }, "stats": { "identified": 28, "messages": 1840, "aspects": 18, "subaspects": 56 }, "personas": [ { "id": "1", "nome": "Cliente Tristeza Invisível", "tipo": "O PERFIL", "descricao": "Sem conexão com CRM", "detalhes": "Cliente antigo, compras esporádicas.", "expansao": "Oferecer atendimento personalizado.", "engajamento": "Acionar contato humano imediato.", "risco": "Alto" } ] } } ``` ### Fontes no banco - `persona` - `client_persona` - `best_action` - `conversation_analysis` - `message` --- ## 4.6 Evolução (`/dashboard/evolucao`) ### Estado atual A tela precisa de: - KPIs de evolução; - série de evolução dos sentimentos; - série de monitoramento de playbooks; - totais do período. ### Backend precisa entregar #### `GET /evolution/overview` Response: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "kpis": { "churnEvitado": 85000, "roiUpsell": 3.1, "scoreMedio": 74, "taxaEvolucao": 21.0, "conversaoEmocao": 47 }, "sentimentSeries": [ { "date": "2024-04-19", "value": 0.05 }, { "date": "2024-04-20", "value": 0.08 } ], "playbooksSeries": [ { "date": "2024-04-19", "novos": 5, "convertidos": 1 }, { "date": "2024-04-20", "novos": 15, "convertidos": 3 } ], "playbooksTotals": { "novos": 20, "convertidos": 4 } } } ``` ### Fontes no banco - `sentiment_evolution` - `playbooks_monitor` - `kpi_snapshot` --- ## 4.7 Executive Dashboard (`/dashboard/executive`) ### Estado atual A tela precisa de: - KPIs executivos; - distribuição de churn; - LTV em risco; - status de SLA; - emoção geral da base; - acessos rápidos. ### Backend precisa entregar #### `GET /executive/dashboard` Response: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "topKpis": [ { "title": "Venda Atual", "value": "R$ 879", "trendLabel": "↑ +12% vs ontem", "danger": false } ], "churnDistribution": [ { "label": "Baixo", "value": 45, "color": "#10b981" }, { "label": "Crítico", "value": 10, "color": "#ef4444" } ], "ltvRisk": { "ltvTotal": 285000, "ltvAtRisk": 34556, "ltvRiskPct": 12, "criticalClients": 34, "avgTicket": 1016, "trendText": "+3 clientes entraram em risco crítico desde ontem" }, "sla": { "withinPct": 78, "breachPct": 22, "byDepartment": [ { "department": "SAC", "value": 72 }, { "department": "Vendas", "value": 85 }, { "department": "Suporte", "value": 91 } ] }, "emotions": { "items": [ { "label": "Alegria", "value": 38, "count": 1524, "color": "#10b981" } ], "avgSentimentScore": 0.28 }, "quickAccess": { "conversationsToday": 418, "activePersonas": 5, "activeAgents": 12, "activePlaybooks": 3, "pendingSettings": 2, "evolutionDelta": "+12%" } } } ``` ### Fontes no banco - `kpi_snapshot` - `emotion_snapshot` - `operator_daily_stats` - `alert` - `sla_config` --- ## 4.8 Agentes (`/dashboard/agents`) ### Estado atual A tela precisa de: - listagem de agentes; - filtros; - KPIs resumidos; - criação de agente; - edição; - ativação/desativação; - toggle de escalonamento. ### Backend precisa entregar - `GET /agents` - `POST /agents` - `POST /agents/status` - `POST /agents/escalation` #### `GET /agents` Response: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "items": [ { "id": 1, "name": "Maria Santos", "email": "maria@empresa.com", "initials": "MS", "department": "SAC", "channels": ["whatsapp"], "status": "Ativo", "availableForEscalation": true, "todayAttendances": 24, "avgResponseTime": "3m 12s", "responseTimeTrend": "down", "slaPct": 94 } ], "stats": { "total": 8, "active": 6, "inAttendance": 2, "availableForEscalation": 5 } } } ``` #### `POST /agents` Request: ```json { "name": "Carolina Ribeiro", "email": "carolina@empresa.com", "department": "SAC", "channels": ["whatsapp", "instagram"], "status": "Ativo", "availableForEscalation": true } ``` Para editar um agente existente, usar `POST /agents` novamente enviando o `id` no payload. Para alterar status, usar `POST /agents/status` enviando o `id` no payload. Para alterar escalonamento, usar `POST /agents/escalation` enviando o `id` no payload. ### Fontes no banco - `operator` - `operator_channel` - `operator_daily_stats` --- ## 4.9 SLA (`/dashboard/sla`) ### Estado atual A tela precisa de: - lista de departamentos configurados; - edição inline; - criação de departamento/configuração; - status em tempo real por departamento. ### Backend precisa entregar - `GET /sla/configs` - `POST /sla/configs` - `GET /sla/live-status` #### `GET /sla/configs` Response: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "items": [ { "id": "sac", "name": "SAC", "firstResponseH": 1, "firstResponseM": 30, "resolutionH": 24, "alertPct": 80, "liveStatus": "breach", "liveDetail": "14h estourado", "lastUpdated": "há 8 minutos" } ] } } ``` Para editar uma configuração existente, usar `POST /sla/configs` novamente enviando o `id` no payload. ### Observação importante O banco atual **não possui `alertPct` na tabela `sla_config`**. Então existem duas opções: - **Opção A**: adicionar uma coluna nova na tabela `sla_config`; - **Opção B**: manter esse percentual em configuração de aplicação. ### Fontes no banco - `sla_config` - `conversation` - `operator` --- ## 4.10 Configurações (`/dashboard/settings`) ### Estado atual A tela é estática e mostra: - integrações; - notificações; - suporte. ### Backend precisa entregar #### `GET /settings/overview` Response: ```json { "status": "ok", "msg": "[100] Request ok.", "code": "S_OK", "data": { "integrations": [ { "title": "WhatsApp Business", "description": "Configure sua conta do WhatsApp Business para comunicação", "status": "connected", "action": "gerenciar" }, { "title": "WhatsApp dos Vendedores", "description": "Adicione os números de WhatsApp da equipe de vendas", "status": "partial", "action": "configurar", "count": "3 de 5 configurados" } ], "notifications": [ { "title": "Alertas de Sentimento", "description": "Receba alertas sobre mudanças no sentimento dos clientes", "status": "enabled", "action": "configurar" } ], "support": [ { "title": "Central de Ajuda", "description": "Acesse nossa documentação e tutoriais", "status": "available", "action": "acessar" } ] } } ``` ### Observação importante Esta parte do produto **não está coberta pelo schema atual** de forma completa. Existe suporte parcial em: - `integration` - `operator_channel` Mas **não há modelagem explícita** para preferências de notificação e configurações gerais. --- ## 4.11 Perfil (`/dashboard/profile` e `/dashboard/perfil`) ### Backend precisa entregar - `POST /me/change-password` #### `POST /me/change-password` Request: ```json { "currentPassword": "senha-atual", "newPassword": "senha-nova", "confirmPassword": "senha-nova" } ``` ### Fontes no banco - `user` - `company` --- ## 4.13 Ajuda (`/dashboard/help` e `/dashboard/ajuda`) ### Backend precisa entregar Opcionalmente: - `GET /support/faq` - `GET /support/channels` ### Observação Essa tela pode continuar **100% estática** no frontend, se preferir. --- ## 5. Rotas recomendadas para o backend ## Prioridade 0 — obrigatórias para integrar o app - `POST /login` X - `POST /me/change-password` ## Prioridade 1 — telas mais centrais do produto - `GET /dashboard/overview` - `GET /interactions` - `GET /interactions/details` - `GET /analytics/sentiment/dashboard` ## Prioridade 2 — gestão e inteligência - `GET /personas/overview` - `GET /evolution/overview` - `GET /executive/dashboard` - `GET /agents` - `POST /agents` - `POST /agents/status` - `POST /agents/escalation` - `GET /sla/configs` - `POST /sla/configs` - `GET /sla/live-status` ## Prioridade 3 — configurações e módulos acessórios - `GET /settings/overview` - `GET /billing/subscription` - `GET /billing/plans` - `POST /billing/change-plan` - `POST /billing/cancel` - `GET /support/faq` - `GET /support/channels` --- ## 6. Padrão de implementação recomendado ## Envelope de resposta Manter o padrão já existente no backend: ```json { "status": "ok|failed", "msg": "mensagem", "code": "S_OK|E_VALIDATE|...", "data": {} } ``` ## Autorização Todas as rotas privadas devem exigir: ```http Authorization: Bearer ``` ## Convenção prática para o frontend Como o frontend atual está em Svelte e usa muitos objetos de tela prontos, o caminho mais simples é: - backend responder com objetos **já próximos do formato consumido pelas telas**; - frontend fazer apenas adaptação leve, se necessário. --- ## 7. Observações importantes da análise - O frontend **não está chamando API nenhuma hoje**. - Portanto, além de criar as rotas do backend, será necessário integrar o frontend com: - `fetch`/client HTTP; - persistência de token; - carregamento inicial a partir do JWT já recebido no login; - tratamento de `401`. - Como o frontend usa `adapter-static`, o consumo da API será **client-side**. - Isso significa que o backend provavelmente precisará de: - **CORS habilitado**; - URL pública configurável por ambiente. --- ## 8. Resumo executivo ## O que já existe - frontend pronto visualmente; - banco PostgreSQL bem modelado para analytics/atendimento; - login e registro no backend; - JWT funcionando; - migration pronta. ## O que falta - praticamente toda a API de produto; - integração real do frontend com backend; - endpoints agregadores para dashboards; - CRUD de agentes; - endpoints de SLA; - endpoint de perfil; - eventualmente modelagem extra para billing/settings. ## Melhor ordem de implementação 1. autenticação real no frontend; 2. dashboard principal; 3. interações; 4. analytics/sentiment; 6. agentes; 7. SLA; 8. personas/evolução/executivo; 9. settings/billing/help. --- ## 9. Conclusão O projeto está em um ponto muito bom para integração: - o frontend já mostra claramente o produto final; - o banco já cobre boa parte do domínio; - o backend já tem base de auth pronta. O principal trabalho agora é transformar os mocks do frontend em contratos reais de API. Este arquivo pode ser usado como backlog técnico para construir o backend na ordem correta.