ACCEPTANCE CRITERIA (63/63)
☑ AC1.1: Mensagens do CLIENTE (`sender_type = 'customer'` ou `is_from_customer = true`) aparecem na DIREITA com fundo CINZA (`var(--bg-elevated)` ou `#e5e5e5`)
☑ AC1.2: Mensagens do BOT (`sender_type = 'bot'`) aparecem na ESQUERDA com fundo VERMELHO Propek (`var(--propek-red)`) e texto branco
☑ AC1.3: Mensagens do ATENDENTE (`sender_type = 'human'`) aparecem na ESQUERDA com fundo distinto (sugestao: `var(--propek-red-light)` ou `#4A4A4A`) e texto branco
☑ AC1.4: Label de identificacao visivel em cada mensagem: "Bot", "Atendente", "Cliente"
☑ AC1.5: Logica atual de `isInbound` invertida: `isInbound = true` para mensagens da Propek (bot + atendente), `isInbound = false` para cliente
☑ AC2.1: Investigar payload enviado pelo frontend no "Salvar Alteracoes" do painel lateral (quais campos, tipos, formato)
☑ AC2.2: Investigar o que o backend PATCH /api/crm/customers/:id espera (campos aceitos, validacoes)
☑ AC2.3: Corrigir divergencia frontend/backend para que o save funcione sem erro
☑ AC2.4: Apos salvar, mostrar feedback visual de sucesso (toast ou indicador)
☑ AC2.5: Campos que nao mudaram NAO devem ser enviados no payload (enviar apenas dirty fields)
☑ AC3.1: Campo CPF aplica mascara automatica ao digitar: `000.000.000-00`
☑ AC3.2: Campo CNPJ aplica mascara automatica ao digitar: `00.000.000/0000-00`
☑ AC3.3: Deteccao automatica CPF vs CNPJ baseada em `customer_type` (B2C = CPF, B2B = CNPJ)
☑ AC3.4: Validacao de digitos verificadores ao sair do campo (blur)
☑ AC3.5: Feedback visual de erro se CPF/CNPJ invalido (borda vermelha + mensagem)
☑ AC3.6: Funcoes de validacao criadas em `apps/crm/src/lib/api.ts` como helpers reutilizaveis
☑ AC3.7: Mascara funciona em AMBOS os formularios: painel lateral Conversas e form Editar da Ficha 360
☑ AC4.1: Campo CEP aplica mascara: `00000-000`
☑ AC4.2: Ao completar 8 digitos, buscar automaticamente em `https://viacep.com.br/ws/{cep}/json/`
☑ AC4.3: Preencher campos automaticamente: rua (logradouro), bairro, cidade (localidade), estado (uf)
☑ AC4.4: Campo numero fica vazio para preenchimento manual
☑ AC4.5: Loading indicator enquanto busca CEP
☑ AC4.6: Se CEP nao encontrado, mostrar mensagem "CEP nao encontrado"
☑ AC4.7: Funciona em AMBOS os formularios: painel lateral Conversas e form Editar da Ficha 360
☑ AC4.8: Chamada ViaCEP e client-side (nao precisa passar pelo proxy backend)
☑ AC5.1: Confirmar que painel lateral de Conversas e form Editar de Ficha 360 usam o mesmo endpoint PATCH `/api/crm/customers/:id`
☑ AC5.2: Apos salvar no painel lateral, o dado atualizado reflete em Clientes, Ficha 360, e vice-versa
☑ AC5.3: Se ambos formularios estiverem abertos, revalidar dados ao voltar para a pagina (usar `router.refresh()` ou refetch)
☑ AC5.4: Nao ha conflito entre edicoes — ultimo save ganha (acceptable para CRM de 1-2 usuarios)
☑ AC6.1: Investigar se notas sao criadas automaticamente ao carregar a ficha (bug no useEffect ou fetch)
☑ AC6.2: Investigar se o estado local acumula notas ao revisitar (falta cleanup no unmount ou falta de dedup)
☑ AC6.3: Corrigir para que notas aparecam exatamente 1 vez, independente de quantas vezes visitar a ficha
☑ AC6.4: Ao adicionar nova nota, ela aparece na lista sem duplicar as existentes
☑ AC7.1: Textos de "Primeiro Contato", "Ultimo Contato", email, telefone, CNPJ visiveis com bom contraste no tema escuro
☑ AC7.2: Cor minima: `var(--text-secondary)` ou `#b0b0b0` (nao usar `var(--text-tertiary)` que e muito claro)
☑ AC7.3: Labels (titulos) em `var(--text-secondary)`, valores em `var(--text-primary)` ou branco
☑ AC7.4: Icones no cabecalho da ficha com opacidade minima 0.7
☑ AC8.1: Telefone, CPF/CNPJ e email visiveis no TOPO do cabecalho (abaixo do nome)
☑ AC8.2: Evitar repeticao: se telefone ja aparece no cabecalho, nao repetir na secao de detalhes (ou repetir com contexto diferente)
☑ AC8.3: Ordem logica no cabecalho: Nome → Telefone → Email → CPF/CNPJ → Tipo (B2B/B2C)
☑ AC8.4: Secao de detalhes foca em: endereco completo, dados comerciais, metadata Kommo
☑ AC9.1: Ao clicar no card do pipeline, navegar para `/conversas?customer_id={customer_id}`
☑ AC9.2: Se o cliente tem conversa ativa, a pagina Conversas abre com essa conversa selecionada
☑ AC9.3: Se o cliente NAO tem conversa, navegar para a Ficha 360 (`/clientes/{customer_id}`)
☑ AC9.4: Remover ou manter popup atual como opcao secundaria (ex: hover mostra popup, click navega)
☑ AC9.5: Pagina Conversas deve aceitar query param `customer_id` e auto-selecionar a conversa correspondente
☑ AC10.1: `days_in_stage` formatado como tempo legivel: "2h", "1d", "5d", "2sem" (para valores decimais pequenos = horas)
☑ AC10.2: Funcao de formatacao: se < 1 dia, mostrar em horas; se >= 1 dia, mostrar em dias; se >= 14 dias, mostrar em semanas
☑ AC10.3: `assigned_to` removido do card (ID numerico do Kommo nao e util — mostrar apenas se mapeado para nome)
☑ AC10.4: Remover texto redundante "no stage" (a coluna ja indica o stage)
☑ AC10.5: Card mostra: nome cliente (formatado), valor do deal (formatado), tempo no stage (formatado)
☑ AC11.1: Identificar logica que exibe badge "SLA" vermelho nos cards
☑ AC11.2: Documentar: o que calcula o SLA, quais valores de referencia, fonte dos dados
☑ AC11.3: Se SLA nao esta configurado corretamente (valores placeholder), remover o badge
☑ AC11.4: Se SLA esta funcional, manter badge mas garantir que o calculo e correto
☑ AC12.1: Carregar clientes em lotes de 50 (LIMIT 50, OFFSET n)
☑ AC12.2: Scroll infinito: ao chegar perto do final da pagina, carregar proximo lote automaticamente
☑ AC12.3: Indicador de loading durante carregamento de novos lotes
☑ AC12.4: Manter busca por nome/telefone funcional com paginacao
☑ AC12.5: Filtros no topo: "Todos", "B2B", "B2C" (filtrar por `customer_type`)
☑ AC12.6: Filtro ativo muda estilo visual (destaque no botao selecionado)
☑ AC12.7: Total de clientes exibido: "Mostrando X de Y clientes"
☑ AC12.8: Backend ja suporta `?limit=N&offset=M` — confirmar e usar