Pular para conteúdo

Controles do board (filtros, ordenação, colunas virtuais, tempo real)

O que é

Os recursos do board do kanban-comercial em si — não de um card específico: como encontrar, ordenar e acompanhar negócios em tempo real através de filtros server-side, ordenação, colunas virtuais, paginação por coluna e sincronização ao vivo. Compartilhado pelos três boards (Comercial, Mesa F1, Mesa F2), já que todos usam o mesmo KanbanBoard genérico.

Como funciona

Filtros (server-side, persistidos por board)

  • Busca por nome/CPF, com debounce de 350ms.
  • Data de criação: presets Hoje/Ontem/7 dias/30 dias + intervalo custom — sem default ("Qualquer data").
  • Origem do lead.
  • Popover "Filtros" (agrupa os menos usados, com badge de contagem): banco, produto, tempo parado (+24h / +72h), responsável (combobox com busca).
  • Toggles de atalho fora do popover: Apenas urgentes (prioridade P0 — ver abaixo), Apenas clientes (contato com proposta aceita) e Meus negócios (responsável = eu).
  • Cada board (storageKey: comercial, mesa-f1, mesa-f2) persiste seus próprios filtros separadamente no localStorage.

Ordenação

Select com 5 opções: Mais parados (default), Urgentes primeiro, Mais recentes, Mais antigos, Nome A-Z.

Prioridade "Urgente" (P0)

  • Toggle no próprio card (chama de fundo) e no menu de ordenação/filtro do board.
  • POST /v2/comercial/negocios/:id/prioridade — grava P0 ou null (o schema aceita P0..P3, mas a UI atual é binária: só "Urgente" ou "sem urgência").
  • Optimistic: ao contrário de quase toda outra ação do card, definirPrioridade não invalida o board no settle — ela atualiza o card no cache na hora (flip local) e deixa o Supabase Realtime reconciliar depois. Invalidar aqui refazia o fetch de todas as colunas (~3s de latência perceptível); o realtime cobre operações concorrentes de outros usuários.

Colunas virtuais

Colunas que agrupam negócios por uma condição transversal, não por uma etapa própria de (pipe, etapa) — ver pipe-e-etapa:

  • Pendências/Bloqueados — só no board Comercial, mas cross-pipe: mostra negócios pendenciados de qualquer pipe (Comercial ou Mesa). Ver pendencia para a teoria.
  • Em formalização (Mesa) — só no board Comercial: cards-fantasma de negócios que pertencem ao fluxo comercial mas estão fisicamente em Mesa F2. Existe para o dono não perder o negócio de vista enquanto ele é bancarizado — sem isso o card simplesmente sumiria do board Comercial durante a formalização. Sempre sem prioridade e sem mover de etapa (não arrasta).

    ⚠️ Antes (até PR #90): também sem menu — zero ações, só visibilidade. Desde PR #90: tem menu ⋮ em modo enxuto (Reatribuir/Desatribuir + Arquivar; "Mover para…"/"Pendenciar…" continuam ocultos), visível só quando o card está ativo. Ver kanban-comercial e atribuicao-de-negocio/arquivar-negocio.

  • Arquivado/Reprovado — nos boards Comercial e Mesa F1; ausente no board Mesa F2 (mostrarArquivados={false} — negócios não se arquivam a partir da formalização).

Paginação + contagem/Total

  • Cada coluna pagina sozinha (infinite query, botão "Carregar mais (N restantes)"): 25/página, ou 15/página nas colunas "fechadas" (Arquivado e Concluído).
  • Cabeçalho da coluna mostra a contagem e o Total (Σ do Valor do Negócio) — vem de um endpoint de contagem à parte (GET .../kanban/contagem), não da soma dos cards carregados na tela (por causa da paginação).
  • Linha fixa do board soma tudo: "Exibindo N negócios · Total R$…".

Tempo real (Realtime)

  • useRealtimeNegocios assina mudanças na tabela negocio via Supabase Realtime.
  • Coalescing: agrupa vários eventos em ~500ms numa única invalidação por board (evita refetch em rajada quando várias movimentações acontecem juntas).
  • Filtro por pipe no cliente (não no filter da subscription): o board Comercial precisa reagir também a eventos do pipe Mesa, por causa da coluna-fantasma "Em formalização" — um filtro server-side por pipe excluiria justamente esses eventos.
  • Invalidação cirúrgica: nunca a raiz da query key (isso derrubaria diálogos de propostas abertos por outro usuário) — só as colunas+contagem do(s) pipe(s) relevante(s).

Tempo parado (semáforo)

TempoParadoBadge — calcula horas desde entrouEtapaEm: verde/discreto abaixo de 24h, amarelo entre 24–72h, pill vermelho com ícone de alerta acima de 72h ("SLA estourado"). É o indicador visual que dá origem ao filtro "Tempo parado" e à ordenação "Mais parados" (default do board).

Regras de negócio

⚠️ A documentar. Esta tela ainda não tem as regras de negócio levantadas do código.

O que entra aqui: invariante (o que nunca pode acontecer), permissão (quem pode fazer o quê), bloqueio (o que impede a ação e a mensagem que o usuário vê), cálculo (fórmula e arredondamento) e efeito colateral (o que mais muda quando isso acontece).

Regra só entra aqui com origem no código — arquivo e linha. Regra que alguém "acha que é assim" é pior que seção vazia, porque vira decisão de produto baseada em memória.

Onde vive no código

  • apps/crm-menos-juros/client/src/pages/comercial/kanban/KanbanBoard.tsx (composição geral, colunas virtuais por pipe).
  • pages/comercial/kanban/components/{KanbanFiltros,OrdenacaoSelect,KanbanColumn, TempoParadoBadge,GhostCardFormalizacao}.tsx.
  • domains/comercial/negocios/hooks/{use-filtros-kanban,use-realtime-negocios, use-kanban-negocios,use-contagem-kanban,use-coluna-kanban}.ts.
  • API: GET /v2/comercial/negocios/kanban, GET .../kanban/contagem, GET .../filtros/opcoes, POST .../:id/prioridade.

Relacionado

kanban-comercial · pipe-e-etapa · pendencia · negocio · board-read-only-orientado-a-eventos · comercial · mesa

Histórico

  • 2026-07-10: primeira ingestão, a partir do código atual (componentes do board + hooks de filtro/realtime/paginação).
  • 2026-07-14 (PR #90): a coluna virtual "Em formalização (Mesa)" deixou de ser 100% read-only — ganhou menu ⋮ enxuto (Reatribuir/Desatribuir + Arquivar). Antes/depois marcado.