Pular para conteúdo

MENU - Menu Interativo WhatsApp

O que é este Node?

O MENU é o node responsável por criar menus interativos nativos do WhatsApp com múltiplas seções e opções, permitindo que usuários selecionem entre até 10 opções organizadas em categorias. É a forma mais elegante e profissional de oferecer escolhas complexas em conversas WhatsApp.

Por que este Node existe?

Quando você precisa apresentar múltiplas opções ao usuário de forma organizada e profissional, botões simples não são suficientes. O MENU existe para:

  1. Organização Visual: Agrupar opções relacionadas em seções nomeadas, criando uma hierarquia clara de informações
  2. Suporte a Múltiplas Opções: Permitir até 10 opções (versus 3 botões), ideal para catálogos, categorias e escolhas complexas
  3. Descrições Detalhadas: Cada opção pode ter uma descrição adicional, ajudando o usuário a entender melhor cada escolha
  4. Experiência Nativa WhatsApp: Usa a interface interativa oficial do WhatsApp, garantindo familiaridade e confiança do usuário

Como funciona internamente?

Quando o MENU é executado, o sistema:

  1. Valida Seções: Verifica se há pelo menos uma seção com opções configuradas
  2. Conta Total de Opções: Soma todas as opções de todas as seções (limite: 10 opções no total)
  3. Gera IDs Únicos: Cria IDs automáticos para opções sem ID definido
  4. Constrói Estrutura WhatsApp: Monta o payload no formato interactive esperado pela API WhatsApp
  5. Adiciona Elementos Opcionais: Inclui header e footer se fornecidos
  6. Retorna Menu Pronto: Envia estrutura completa aguardando seleção do usuário
  7. Aguarda Resposta: Sistema espera que usuário selecione uma opção para continuar

Código interno (whatsapp-ui-executor.service.ts:42-98):

private async executeMenu(parameters: any, context: any): Promise<any> {
  const { header, body, footer, sections, buttonText } = parameters;

  this.logger.log(`📱 MENU - Creating WhatsApp menu with ${sections?.length || 0} sections`);

  // Validate sections
  if (!sections || sections.length === 0) {
    throw new Error('Menu requires at least one section with options');
  }

  // Validate total options limit (WhatsApp limit: 10 options per menu)
  const totalOptions = sections.reduce((total, section) => total + (section.rows?.length || 0), 0);
  if (totalOptions > 10) {
    throw new Error(`WhatsApp menu supports maximum 10 options, got ${totalOptions}`);
  }

  // Build WhatsApp menu structure
  const whatsappMenu = {
    type: 'interactive',
    body: {
      text: body || 'Please select an option:'
    },
    action: {
      button: buttonText || 'Select',
      sections: sections.map(section => ({
        title: section.title || 'Options',
        rows: section.rows?.map(row => ({
          id: row.id || `option_${Math.random().toString(36).substr(2, 9)}`,
          title: row.title || row.text || 'Option',
          description: row.description || ''
        })) || []
      }))
    }
  };

  if (header) {
    whatsappMenu['header'] = {
      type: 'text',
      text: header
    };
  }

  if (footer) {
    whatsappMenu['footer'] = {
      text: footer
    };
  }

  return {
    success: true,
    action: 'whatsapp_menu_created',
    messageType: 'interactive_menu',
    payload: whatsappMenu,
    awaitingUserSelection: true,
    timestamp: new Date().toISOString()
  };
}

Quando você DEVE usar este Node?

Use MENU sempre que precisar de apresentar 4 ou mais opções organizadas em categorias:

Casos de uso

  1. Catálogo de Produtos: "Selecione uma categoria: Eletrônicos, Roupas, Alimentos, etc."
  2. Menu de Serviços: "Escolha um departamento: Vendas, Suporte, Financeiro, RH"
  3. Opções de Agendamento: "Selecione um horário disponível" com múltiplos dias/horários
  4. Seleção de Especialidade: "Qual especialidade médica você precisa?" com descrições de cada uma
  5. Configurações de Conta: Múltiplas opções de configuração agrupadas por tipo

Quando NÃO usar MENU

  • 3 ou menos opções: Use BUTTONS para escolhas rápidas (mais visual e direto)
  • Resposta Livre: Use INPUT quando o usuário precisa digitar algo (não escolher)
  • Confirmação Sim/Não: Use BUTTONS com apenas 2 botões
  • Lista Linear Simples: Use LIST se não precisa de seções/categorias

Parâmetros Detalhados

header (string, opcional)

O que é: Título principal exibido no topo do menu, destacado em negrito.

Padrão: Nenhum (menu sem header)

Flow completo para testar:

{
  "name": "Teste MENU - Header",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "menu_1",
      "type": "menu",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Menu com Header",
        "parameters": {
          "header": "🛍️ Catálogo de Produtos",
          "body": "Selecione a categoria desejada:",
          "buttonText": "Ver Categorias",
          "sections": [
            {
              "title": "Produtos",
              "rows": [
                { "id": "eletronicos", "title": "Eletrônicos", "description": "TVs, celulares, notebooks" },
                { "id": "roupas", "title": "Roupas", "description": "Moda masculina e feminina" }
              ]
            }
          ]
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Confirmar Seleção",
        "parameters": {
          "message": "Você selecionou: {{menu_selection}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "menu_1" },
    { "source": "menu_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: 1. Inicie o flow 2. Verá menu com header "🛍️ Catálogo de Produtos" em destaque 3. Clique em "Ver Categorias" 4. Selecione uma opção 5. Confirmação mostra o que foi selecionado


body (string, obrigatório)

O que é: Texto principal da mensagem, explicando o que o usuário deve fazer. É o conteúdo central do menu.

Padrão: "Please select an option:"

Flow completo para testar:

{
  "name": "Teste MENU - Body",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "menu_1",
      "type": "menu",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Menu Body Personalizado",
        "parameters": {
          "body": "👋 Olá! Para qual departamento você gostaria de falar?\n\nSelecione abaixo:",
          "buttonText": "Selecionar Departamento",
          "sections": [
            {
              "title": "Departamentos",
              "rows": [
                { "id": "vendas", "title": "Vendas", "description": "Informações sobre produtos" },
                { "id": "suporte", "title": "Suporte", "description": "Ajuda técnica" },
                { "id": "financeiro", "title": "Financeiro", "description": "Cobranças e pagamentos" }
              ]
            }
          ]
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "Conectando você ao departamento: {{menu_selection}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "menu_1" },
    { "source": "menu_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: 1. Inicie o flow 2. Verá mensagem personalizada com saudação e instruções 3. Texto body aceita múltiplas linhas e emojis 4. Selecione um departamento 5. Confirmação usa o ID selecionado


O que é: Texto adicional exibido abaixo do menu, ideal para informações complementares ou avisos.

Padrão: Nenhum (menu sem footer)

Flow completo para testar:

{
  "name": "Teste MENU - Footer",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "menu_1",
      "type": "menu",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Menu com Footer",
        "parameters": {
          "header": "📅 Agendamento",
          "body": "Selecione o melhor horário para sua consulta:",
          "footer": "⏰ Horário de Brasília | Consultas duram 30min",
          "buttonText": "Ver Horários",
          "sections": [
            {
              "title": "Manhã",
              "rows": [
                { "id": "09h", "title": "09:00", "description": "Disponível" },
                { "id": "10h", "title": "10:00", "description": "Disponível" }
              ]
            },
            {
              "title": "Tarde",
              "rows": [
                { "id": "14h", "title": "14:00", "description": "Disponível" },
                { "id": "15h", "title": "15:00", "description": "Disponível" }
              ]
            }
          ]
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Confirmar Horário",
        "parameters": {
          "message": "✅ Consulta agendada para {{menu_selection}}!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "menu_1" },
    { "source": "menu_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: 1. Inicie o flow 2. Menu mostra footer com informações sobre fuso horário 3. Footer aparece em cinza claro abaixo das opções 4. Selecione um horário 5. Confirmação usa o horário selecionado


sections (array, obrigatório)

O que é: Array de seções do menu. Cada seção tem um título e uma lista de opções (rows). É a estrutura principal do menu.

Estrutura de cada seção:

{
  title: string,        // Nome da seção
  rows: [               // Array de opções
    {
      id: string,       // ID único da opção
      title: string,    // Texto da opção (max 24 chars)
      description: string // Descrição opcional
    }
  ]
}

Limite: Máximo de 10 opções no total (somando todas as seções)

Flow completo para testar:

{
  "name": "Teste MENU - Sections Múltiplas",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "menu_1",
      "type": "menu",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Menu Multi-Seção",
        "parameters": {
          "header": "🏥 Clínica Médica",
          "body": "Selecione a especialidade que você precisa:",
          "buttonText": "Ver Especialidades",
          "sections": [
            {
              "title": "🩺 Clínica Geral",
              "rows": [
                { "id": "clinico", "title": "Clínico Geral", "description": "Consultas gerais e check-ups" },
                { "id": "pediatra", "title": "Pediatra", "description": "Especialista em crianças" }
              ]
            },
            {
              "title": "🦷 Odontologia",
              "rows": [
                { "id": "dentista", "title": "Dentista", "description": "Limpeza e tratamentos" },
                { "id": "ortodontia", "title": "Ortodontia", "description": "Aparelhos e alinhamento" }
              ]
            },
            {
              "title": "🧠 Especialidades",
              "rows": [
                { "id": "cardio", "title": "Cardiologista", "description": "Saúde do coração" },
                { "id": "dermato", "title": "Dermatologista", "description": "Problemas de pele" }
              ]
            }
          ]
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Confirmar Especialidade",
        "parameters": {
          "message": "Especialidade selecionada: {{menu_selection}}\n\nAgora vamos agendar sua consulta!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "menu_1" },
    { "source": "menu_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: 1. Inicie o flow 2. Menu mostra 3 seções bem organizadas com títulos com emojis 3. Cada seção agrupa opções relacionadas 4. Descrições ajudam usuário a entender cada opção 5. Selecione qualquer especialidade 6. ID da especialidade é capturado para próxima ação


buttonText (string, opcional)

O que é: Texto do botão que abre o menu. Usuário precisa clicar neste botão para ver as opções.

Padrão: "Select"

Flow completo para testar:

{
  "name": "Teste MENU - ButtonText Personalizado",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "menu_1",
      "type": "menu",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Menu ButtonText Custom",
        "parameters": {
          "header": "🎓 Cursos Online",
          "body": "Escolha a área de conhecimento que mais te interessa:",
          "buttonText": "📚 Ver Todos os Cursos",
          "sections": [
            {
              "title": "Tecnologia",
              "rows": [
                { "id": "programacao", "title": "Programação", "description": "Python, JavaScript, etc" },
                { "id": "design", "title": "Design", "description": "UI/UX, Figma, Adobe" }
              ]
            },
            {
              "title": "Negócios",
              "rows": [
                { "id": "marketing", "title": "Marketing Digital", "description": "SEO, ads, redes sociais" },
                { "id": "vendas", "title": "Vendas", "description": "Técnicas de vendas" }
              ]
            }
          ]
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Mostrar Curso",
        "parameters": {
          "message": "Ótima escolha! Você selecionou: {{menu_selection}}\n\n🎯 Vamos te mostrar os cursos disponíveis!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "menu_1" },
    { "source": "menu_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: 1. Inicie o flow 2. Veja botão com texto "📚 Ver Todos os Cursos" (personalizado) 3. Clique no botão para abrir menu 4. Selecione uma área 5. Mensagem confirma seleção

Parâmetros

Campo Tipo Obrigatório Descrição
header string Não Título principal destacado no topo
body string Sim Texto explicativo da mensagem (padrão: "Please select an option:")
footer string Não Texto adicional abaixo das opções
sections array Sim Array de seções com opções (máx 10 opções total)
buttonText string Não Texto do botão que abre menu (padrão: "Select")

Exemplo 1: Cardápio de Restaurante com Categorias

Objetivo: Criar menu organizado de restaurante com múltiplas categorias de pratos

JSON para Importar

{
  "name": "Cardápio de Restaurante - Menu Interativo",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Boas-vindas",
        "parameters": {
          "message": "🍽️ Bem-vindo ao Restaurante Sabor Brasileiro!\n\nVamos fazer seu pedido?"
        }
      }
    },
    {
      "id": "menu_1",
      "type": "menu",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Menu Cardápio",
        "parameters": {
          "header": "🍽️ Cardápio Completo",
          "body": "Selecione o prato que deseja pedir:\n\nTodos os pratos acompanham arroz, feijão e salada.",
          "footer": "🚚 Entrega em 40-50 minutos | Pedido mínimo: R$ 25",
          "buttonText": "Ver Cardápio Completo",
          "sections": [
            {
              "title": "🥩 Carnes",
              "rows": [
                {
                  "id": "picanha",
                  "title": "Picanha Grelhada",
                  "description": "300g - R$ 45,90"
                },
                {
                  "id": "frango",
                  "title": "Frango à Parmegiana",
                  "description": "Com molho e queijo - R$ 32,90"
                }
              ]
            },
            {
              "title": "🐟 Peixes",
              "rows": [
                {
                  "id": "salmao",
                  "title": "Salmão Grelhado",
                  "description": "Com legumes - R$ 52,90"
                },
                {
                  "id": "tilapia",
                  "title": "Tilápia na Manteiga",
                  "description": "Com molho de ervas - R$ 38,90"
                }
              ]
            },
            {
              "title": "🥗 Vegetarianos",
              "rows": [
                {
                  "id": "lasanha_veg",
                  "title": "Lasanha Vegetariana",
                  "description": "Camadas de legumes - R$ 29,90"
                },
                {
                  "id": "risoto",
                  "title": "Risoto de Cogumelos",
                  "description": "Cremoso e saboroso - R$ 34,90"
                }
              ]
            }
          ]
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmar Pedido",
        "parameters": {
          "message": "🎉 Excelente escolha!\n\nVocê pediu: {{menu_selection}}\n\n✅ Pedido confirmado!\n🚚 Tempo estimado: 40-50 minutos\n📱 Você receberá atualizações via WhatsApp"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "menu_1" },
    { "source": "menu_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: 🍽️ Bem-vindo ao Restaurante Sabor Brasileiro!

Vamos fazer seu pedido?

[Menu interativo aparece]
Header: 🍽️ Cardápio Completo
Body: Selecione o prato que deseja pedir:

Todos os pratos acompanham arroz, feijão e salada.

Botão: [Ver Cardápio Completo]

Usuário: [Clica no botão, abre menu com 3 seções]
- 🥩 Carnes (Picanha, Frango)
- 🐟 Peixes (Salmão, Tilápia)
- 🥗 Vegetarianos (Lasanha, Risoto)

Usuário: [Seleciona "Salmão Grelhado"]

Sistema: 🎉 Excelente escolha!

Você pediu: salmao

✅ Pedido confirmado!
🚚 Tempo estimado: 40-50 minutos
📱 Você receberá atualizações via WhatsApp

Exemplo 2: Sistema de Suporte Técnico Multi-Nível

Objetivo: Menu de atendimento com diferentes departamentos e tipos de suporte

JSON para Importar

{
  "name": "Suporte Técnico - Menu Departamentos",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "menu_1",
      "type": "menu",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Menu Suporte",
        "parameters": {
          "header": "🛠️ Central de Suporte",
          "body": "Olá! 👋\n\nPara melhor atendê-lo, selecione o tipo de suporte que você precisa:",
          "footer": "⏰ Atendimento 24/7 | Tempo médio de resposta: 5min",
          "buttonText": "🎯 Selecionar Área",
          "sections": [
            {
              "title": "💻 Técnico",
              "rows": [
                {
                  "id": "bug",
                  "title": "Reportar Bug",
                  "description": "Algo não está funcionando"
                },
                {
                  "id": "lentidao",
                  "title": "Sistema Lento",
                  "description": "Problemas de performance"
                },
                {
                  "id": "erro",
                  "title": "Mensagem de Erro",
                  "description": "Recebeu um erro específico"
                }
              ]
            },
            {
              "title": "💳 Financeiro",
              "rows": [
                {
                  "id": "cobranca",
                  "title": "Dúvida sobre Cobrança",
                  "description": "Valores e faturas"
                },
                {
                  "id": "pagamento",
                  "title": "Problema no Pagamento",
                  "description": "Pagamento não processado"
                }
              ]
            },
            {
              "title": "📚 Dúvidas Gerais",
              "rows": [
                {
                  "id": "como_usar",
                  "title": "Como usar o Sistema",
                  "description": "Tutorial e documentação"
                },
                {
                  "id": "novidade",
                  "title": "Novidades",
                  "description": "Novas funcionalidades"
                }
              ]
            }
          ]
        }
      }
    },
    {
      "id": "switch_1",
      "type": "switch",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Direcionar Atendimento",
        "parameters": {
          "variable": "{{menu_selection}}",
          "cases": [
            { "value": "bug", "label": "Bug" },
            { "value": "lentidao", "label": "Lentidão" },
            { "value": "erro", "label": "Erro" },
            { "value": "cobranca", "label": "Cobrança" },
            { "value": "pagamento", "label": "Pagamento" },
            { "value": "como_usar", "label": "Tutorial" },
            { "value": "novidade", "label": "Novidades" }
          ]
        }
      }
    },
    {
      "id": "message_bug",
      "type": "message",
      "position": { "x": 700, "y": 0 },
      "data": {
        "label": "Resposta Bug",
        "parameters": {
          "message": "🐛 Entendido! Vamos resolver esse bug.\n\nPor favor, descreva detalhadamente o problema:\n- O que você estava fazendo?\n- O que aconteceu?\n- Já tentou reiniciar o sistema?"
        }
      }
    },
    {
      "id": "message_financeiro",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Resposta Financeiro",
        "parameters": {
          "message": "💳 Equipe financeira!\n\nVou te conectar com nosso time financeiro.\n\nPor favor, tenha em mãos:\n- CPF/CNPJ\n- Número do pedido\n- Data da transação"
        }
      }
    },
    {
      "id": "message_tutorial",
      "type": "message",
      "position": { "x": 700, "y": 200 },
      "data": {
        "label": "Resposta Tutorial",
        "parameters": {
          "message": "📚 Ótimo! Vou te ajudar.\n\n📖 Documentação: https://docs.exemplo.com\n🎥 Vídeos: https://youtube.com/exemplo\n💬 Comunidade: https://forum.exemplo.com\n\nQual desses recursos prefere?"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "menu_1" },
    { "source": "menu_1", "target": "switch_1" },
    { "source": "switch_1", "target": "message_bug", "label": "Bug/Lentidão/Erro" },
    { "source": "switch_1", "target": "message_financeiro", "label": "Cobrança/Pagamento" },
    { "source": "switch_1", "target": "message_tutorial", "label": "Tutorial/Novidades" },
    { "source": "message_bug", "target": "end_1" },
    { "source": "message_financeiro", "target": "end_1" },
    { "source": "message_tutorial", "target": "end_1" }
  ]
}

Saída esperada:

[Menu aparece automaticamente]
Header: 🛠️ Central de Suporte
Body: Olá! 👋

Para melhor atendê-lo, selecione o tipo de suporte que você precisa:

Footer: ⏰ Atendimento 24/7 | Tempo médio de resposta: 5min

Usuário: [Clica em "🎯 Selecionar Área"]
[Vê 3 seções organizadas]

Usuário: [Seleciona "Reportar Bug" da seção Técnico]

Sistema: 🐛 Entendido! Vamos resolver esse bug.

Por favor, descreva detalhadamente o problema:
- O que você estava fazendo?
- O que aconteceu?
- Já tentou reiniciar o sistema?

[Flow continua com coleta de informações do bug]

Exemplo 3: Agendamento de Consultas com Múltiplos Horários

Objetivo: Sistema completo de agendamento usando menu para selecionar dia e horário

JSON para Importar

{
  "name": "Agendamento Médico - Menu Horários",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Boas-vindas Clínica",
        "parameters": {
          "message": "🏥 Clínica Saúde Total\n\nOlá! Vamos agendar sua consulta com Dr. Silva.\n\n📋 Consulta: Cardiologia\n⏱️ Duração: 30 minutos\n💰 Valor: R$ 250,00"
        }
      }
    },
    {
      "id": "menu_1",
      "type": "menu",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Menu Horários",
        "parameters": {
          "header": "📅 Horários Disponíveis",
          "body": "Selecione o melhor dia e horário para sua consulta:\n\n✅ = Disponível\n⏰ = Últimas vagas",
          "footer": "🕐 Horário de Brasília | Confirme com 24h de antecedência",
          "buttonText": "Ver Horários",
          "sections": [
            {
              "title": "Segunda-feira 15/01",
              "rows": [
                { "id": "seg_09", "title": "09:00", "description": "✅ Disponível" },
                { "id": "seg_14", "title": "14:00", "description": "⏰ Última vaga" }
              ]
            },
            {
              "title": "Terça-feira 16/01",
              "rows": [
                { "id": "ter_10", "title": "10:00", "description": "✅ Disponível" },
                { "id": "ter_15", "title": "15:00", "description": "✅ Disponível" }
              ]
            },
            {
              "title": "Quarta-feira 17/01",
              "rows": [
                { "id": "qua_09", "title": "09:00", "description": "✅ Disponível" },
                { "id": "qua_11", "title": "11:00", "description": "✅ Disponível" },
                { "id": "qua_16", "title": "16:00", "description": "⏰ Última vaga" }
              ]
            }
          ]
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmar Dados",
        "parameters": {
          "message": "📋 Confirme os dados do agendamento:\n\n👤 Paciente: {{patient_name}}\n🏥 Médico: Dr. Silva - Cardiologia\n📅 Data/Hora: {{menu_selection}}\n💰 Valor: R$ 250,00\n\nOs dados estão corretos?"
        }
      }
    },
    {
      "id": "buttons_1",
      "type": "buttons",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Confirmar Agendamento",
        "parameters": {
          "body": "Confirmar agendamento?",
          "buttons": [
            { "id": "confirmar", "text": "✅ Sim, confirmar" },
            { "id": "alterar", "text": "📝 Alterar horário" },
            { "id": "cancelar", "text": "❌ Cancelar" }
          ]
        }
      }
    },
    {
      "id": "message_3",
      "type": "message",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Confirmação Final",
        "parameters": {
          "message": "✅ Consulta agendada com sucesso!\n\n📅 Horário: {{menu_selection}}\n🏥 Local: Clínica Saúde Total\n📍 Endereço: Rua das Flores, 123\n\n📱 Você receberá um lembrete 24h antes.\n🚗 Reserve 10 minutos para estacionamento.\n\n🎉 Até lá! Cuide-se bem!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1300, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "menu_1" },
    { "source": "menu_1", "target": "message_2" },
    { "source": "message_2", "target": "buttons_1" },
    { "source": "buttons_1", "target": "message_3" },
    { "source": "message_3", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: 🏥 Clínica Saúde Total

Olá! Vamos agendar sua consulta com Dr. Silva.

📋 Consulta: Cardiologia
⏱️ Duração: 30 minutos
💰 Valor: R$ 250,00

[Menu aparece]
Header: 📅 Horários Disponíveis
Botão: [Ver Horários]

Usuário: [Clica e vê menu organizado por dias]
- Segunda-feira 15/01 (09:00, 14:00)
- Terça-feira 16/01 (10:00, 15:00)
- Quarta-feira 17/01 (09:00, 11:00, 16:00)

Usuário: [Seleciona "Terça-feira 16/01 - 10:00"]

Sistema: 📋 Confirme os dados do agendamento:

👤 Paciente: João Silva
🏥 Médico: Dr. Silva - Cardiologia
📅 Data/Hora: ter_10
💰 Valor: R$ 250,00

Os dados estão corretos?

[Botões aparecem: Sim/Alterar/Cancelar]

Usuário: [Clica "✅ Sim, confirmar"]

Sistema: ✅ Consulta agendada com sucesso!

📅 Horário: ter_10
🏥 Local: Clínica Saúde Total
📍 Endereço: Rua das Flores, 123

📱 Você receberá um lembrete 24h antes.
🚗 Reserve 10 minutos para estacionamento.

🎉 Até lá! Cuide-se bem!

Resposta do Node

{
  "success": true,
  "action": "whatsapp_menu_created",
  "messageType": "interactive_menu",
  "payload": {
    "type": "interactive",
    "header": {
      "type": "text",
      "text": "🛍️ Catálogo de Produtos"
    },
    "body": {
      "text": "Selecione a categoria desejada:"
    },
    "footer": {
      "text": "Todos os preços incluem frete"
    },
    "action": {
      "button": "Ver Categorias",
      "sections": [
        {
          "title": "Eletrônicos",
          "rows": [
            {
              "id": "smartphones",
              "title": "Smartphones",
              "description": "iPhones e Androids"
            },
            {
              "id": "notebooks",
              "title": "Notebooks",
              "description": "Dell, Lenovo, Apple"
            }
          ]
        }
      ]
    }
  },
  "awaitingUserSelection": true,
  "timestamp": "2025-01-15T10:30:00.000Z"
}

Boas Práticas

SIM:

  • Use seções bem nomeadas para agrupar opções relacionadas logicamente
  • Adicione descrições às opções para ajudar usuário a decidir (especialmente em escolhas complexas)
  • Mantenha títulos curtos e claros (máx 24 caracteres por opção)
  • Use emojis estrategicamente nos títulos das seções para identificação visual rápida
  • Personalize buttonText para ficar intuitivo ("Ver Produtos", "Selecionar Horário")
  • Use footer para informações importantes (limites, horários, condições)
  • Garanta que IDs sejam únicos e descritivos (facilita lógica posterior)
  • Organize opções por relevância (mais populares primeiro)

NÃO:

  • Não coloque mais de 10 opções no total (limite do WhatsApp)
  • Não use títulos muito longos que serão cortados
  • Não crie seções com apenas 1 opção (use LIST simples)
  • Não esqueça de validar se sections existe antes de acessar
  • Não use IDs com espaços ou caracteres especiais (dificulta processamento)
  • Não crie menus sem contexto (sempre explique o que usuário está escolhendo)
  • Não use linguagem ambígua nas descrições (seja claro e direto)

Dicas

💡 Organização por Contexto: Agrupe opções que fazem sentido juntas. Ex: "Manhã/Tarde/Noite" para horários, "Norte/Sul/Leste/Oeste" para localização.

💡 Descrições Informativas: Use descrições para diferenciar opções similares. Ex: "Básico - R$ 49/mês" vs "Premium - R$ 99/mês com mais recursos".

💡 Fallback Inteligente: Sempre capture a resposta do menu em uma variável para usar em SWITCH ou CONDITION posteriormente, direcionando o flow de acordo com a escolha.

💡 Validação de Limite: Sistema valida automaticamente o limite de 10 opções. Se precisar de mais, divida em múltiplos menus ou use estratégia de navegação hierárquica.

💡 IDs Estratégicos: Use IDs que façam sentido no código (ex: "seg_09h" para segunda 9h), facilitando debug e lógica condicional.

💡 Responsividade Visual: Header e Footer aparecem em destaque. Use header para contexto principal (ex: "📅 Agendamento") e footer para informações secundárias (ex: "Horário de Brasília").

💡 Testes de Usabilidade: Teste o menu com usuários reais. Títulos claros e descrições úteis reduzem confusão e melhoram conversão.

💡 Combinação com Outros Nodes: Menu funciona perfeitamente com SWITCH para rotear diferentes escolhas, e com VARIABLE para armazenar seleção e usar depois.

Próximo Node

BUTTONS - Botões rápidos de resposta (até 3 opções simples) → LIST - Lista de seleção alternativa (sem múltiplas seções) → SWITCH - Direcione flow baseado na seleção do menu → VARIABLE - Armazene a seleção do usuário para uso posterior