89 lines
6.2 KiB
Markdown
89 lines
6.2 KiB
Markdown
|
|
# Modulo de Chat WhatsApp (Frontend)
|
||
|
|
|
||
|
|
## Visao geral
|
||
|
|
|
||
|
|
O modulo de Chat no frontend integra as conversas em tempo real do WhatsApp diretamente na tela de atendimento do operador.
|
||
|
|
|
||
|
|
A interface e altamente responsiva, provendo feedback instantaneo de envio (zero latencia) e sincronizando com o backend via WebSockets (Socket.io) para atualizar estados de de-duplicacao, novas mensagens, midias e controle de posse do atendimento.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Componentes Principais
|
||
|
|
|
||
|
|
### 1. Hook de Negocio (`useChat.js`)
|
||
|
|
Centraliza todo o estado das conversas, conexao WebSocket e operacoes de rede:
|
||
|
|
* **`contacts`**: Lista de chats ativos sincronizados. Cada contato possui um objeto `assignment` (atribuicao) normalizado.
|
||
|
|
* **`messagesByContact`**: Map de historico de mensagens por JID/contato.
|
||
|
|
* **`takeChat()`**: Dispara a requisicao de rede `/whatsapp/assign` enviando o ID do atendente e o ID numerico da area do usuario logado (convertido com seguranca para inteiro).
|
||
|
|
* **`sendMessage()`**: Trata a de-duplicacao de mensagens em milissegundos e gerencia a concorrência (race condition).
|
||
|
|
|
||
|
|
### 2. Painel de Atendimento (`ChatWindow.jsx`)
|
||
|
|
O container principal da conversa selecionada. Ele renderiza:
|
||
|
|
* **Header**: Mostra o nome resolvido do cliente, canal (WhatsApp) e o indicador de quem esta atendendo.
|
||
|
|
* **Historico**: Area de scroll contendo as bolhas de mensagens do atendente (`agent`) e do cliente (`customer`), incluindo visualizadores para imagens, audios e links de arquivos.
|
||
|
|
* **Footer de Input**: Caixa de texto com suporte a tecla Enter e icone de anexo de midia (com validacao automatica de tamanho).
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Mecanismos de UX e Estabilidade
|
||
|
|
|
||
|
|
### 1. Insercao Instantanea (UX Zero-Latency)
|
||
|
|
Para evitar que o atendente perceba qualquer latencia de rede, o envio e dividido em duas etapas:
|
||
|
|
1. **Fase Local**: A bolha de mensagem e inserida na tela imediatamente com um ID temporario (`temp-` + timestamp) e o texto digitado. O input de texto e arquivos e limpo na mesma hora.
|
||
|
|
2. **Fase de Disparo**: A requisicao HTTP POST e disparada para o backend em segundo plano.
|
||
|
|
|
||
|
|
### 2. De-duplicacao de Mensagens (Prevecao de Race Condition)
|
||
|
|
Como o backend envia a mensagem recebida via WebSocket assim que o Puppeteer a dispara, a bolha poderia aparecer duplicada na tela se a requisição de envio original ainda estivesse processando.
|
||
|
|
* **A Solucao**: O hook de WebSocket compara as mensagens recebidas em tempo real. Se o texto bater e a diferenca temporal de timestamp for inferior a 4 segundos, ele identifica a bolha `temp-...` local, remove o prefixo temporario e atualiza-a com o ID oficial do WhatsApp gerado no servidor. **Zero duplicacoes, zero flashes na tela.**
|
||
|
|
|
||
|
|
### 3. Validação de Posse (Type-Safe User IDs)
|
||
|
|
Para evitar conflitos na exibicao do banner *"⚠️ Atendido por outro colaborador"*, realizamos casting explicito dos IDs dos usuarios envolvidos:
|
||
|
|
```javascript
|
||
|
|
const isAssignedToMe = activeContact?.assignment?.userId && String(activeContact.assignment.userId) === String(currentUser.id);
|
||
|
|
const isAssignedToOthers = activeContact?.assignment && String(activeContact.assignment.userId) !== String(currentUser.id);
|
||
|
|
```
|
||
|
|
Isso impede que comparacoes como `4 === "4"` (inteiro vindo do banco relacional vs string vindo do localStorage/JWT) avaliem incorretamente como falso, mantendo a tela bloqueada ou liberada com precisao.
|
||
|
|
|
||
|
|
### 4. Layout e Rolagem Estrita (680px Scroll)
|
||
|
|
A interface de mensagens possui limitacoes verticais restritas para evitar que a tela se alongue infinitamente para baixo.
|
||
|
|
* A bolha de historico e fixada com altura proporcional (`height: 680px` ou `calc`) e controle de transbordo `overflow-y: auto`.
|
||
|
|
* O hook de chat escuta mudancas na lista de mensagens e realiza rolagem automatica suave (`smooth`) para o fim da tela sempre que uma nova bolha e adicionada.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Novos Fluxos Homologados (WhatsApp / Meta)
|
||
|
|
|
||
|
|
### 1. Novo Atendimento Inteligente (`NewAttendancePage.jsx`)
|
||
|
|
* **Remoção do Seletor de Área**: O seletor manual foi removido da tela para simplificar a operação. O sistema resolve a área dinamicamente a partir do atendente logado (`currentUser.areaPrincipal` ou `areas[0]`).
|
||
|
|
* **Bloqueio de Campo**: Ao escolher um contato dos recentes ou da busca lateral, o input do telefone e do nome do cliente ficam bloqueados para escrita.
|
||
|
|
* **Modo "Novo Número"**: Ao clicar no botão, o operador habilita os inputs de nome e telefone. Caso inicie o chat sem digitar um nome personalizado, o sistema aplica um fallback limpo no formato `Contato Novo (+55...)`.
|
||
|
|
|
||
|
|
### 2. Bloqueio e Envio de Templates Meta (`ChatWindow.jsx`)
|
||
|
|
Como a API oficial do WhatsApp/Meta exige uma mensagem pré-aprovada para iniciar conversas ativas (sem histórico prévio), a interface aplica travas estritas:
|
||
|
|
* **Travamento do Input**: Se a conversa selecionada possuir histórico de envio vazio (`!hasAgentMessages`), a caixa de texto principal e o botão "Enviar" ficam bloqueados.
|
||
|
|
* **Painel de Templates**: Logo acima do rodapé de digitação, renderiza-se um seletor horizontal com os templates oficiais Meta ativos no banco (buscados de `GET /whatsapp/templates`).
|
||
|
|
* **Substituição Dinâmica**: Ao clicar em um template, as variáveis `|NOME|`, `|DATA|` ou `|PROTOCOLO|` são interpoladas em tempo real com os dados do cliente, populando o input principal e liberando o fluxo de envio da primeira mensagem.
|
||
|
|
|
||
|
|
### 3. Gerenciamento de Templates para Supervisores (`SupervisorPage.jsx`)
|
||
|
|
Supervisores possuem controle administrativo total sobre as mensagens homologadas:
|
||
|
|
* **CRUD de Modelos**: Exibe todos os templates de WhatsApp em formato de cards visuais.
|
||
|
|
* **Painel de Edição**: Permite criar novos templates ou editar identificadores/conteúdos de templates existentes. As alterações persistem imediatamente no banco PostgreSQL por meio dos endpoints `/whatsapp/templates`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Como Integrar e Rodar
|
||
|
|
|
||
|
|
### Variaveis de Ambiente
|
||
|
|
O frontend conecta no WebSocket e na API do backend usando a porta padrao do NestJS:
|
||
|
|
```env
|
||
|
|
VITE_API_URL=http://localhost:3001
|
||
|
|
VITE_WS_URL=http://localhost:3001
|
||
|
|
```
|
||
|
|
|
||
|
|
### Compilando e Rodando localmente
|
||
|
|
```bash
|
||
|
|
cd frontend
|
||
|
|
npm run dev
|
||
|
|
```
|
||
|
|
Ao selecionar uma conversa de canal "WhatsApp" que esteja livre, basta digitar uma mensagem e pressionar Enter. O chat sera automaticamente assumido por voce em tempo real, gravando no PostgreSQL e desbloqueando a janela de chat de forma instantanea.
|