import { useState, useEffect, useRef, type FormEvent } from 'react'; import { Loader2, Send } from 'lucide-react'; type MessageType = 'text' | 'audio' | 'image' | 'video' | 'embed'; interface MessageConfig { text: string; delay?: number; type?: MessageType; } interface OptionConfig { text: string; nextId?: string; actionLink?: string; } interface FunnelNode { id: string; messages: MessageConfig[]; options?: OptionConfig[]; requireEmail?: boolean; } interface RenderedMessage { id: string; sender: 'bot' | 'user'; type: MessageType; content: string; } const funnelData: FunnelNode[] = [ { id: "start", messages: [ { text: "Oi! 👋 Tudo bem? Sou do atendimento da Festa MĂĄgica IA.", delay: 1000, type: "text" }, { text: "Posso te mostrar rapidinho como criar a festa do seu filho gastando muito menos?", delay: 1500, type: "text" } ], options: [ { text: "Pode!", nextId: "step2" }, { text: "Como assim?", nextId: "step2" } ] }, { id: "step2", messages: [ { text: "Mandar fazer personalizados Ă© caro e demora, nĂ©?", delay: 1800, type: "text" }, { text: "Nossa InteligĂȘncia Artificial permite que vocĂȘ mesmo faça tudo na hora, do celular.", delay: 2000, type: "text" }, { text: "Assiste esse vĂ­deo aqui embaixo que mostra a ferramenta funcionando e como Ă© fĂĄcil criar as imagens e os kits👇", delay: 1500, type: "text" }, { text: "https://s3.seureview.com.br/festamagica/0510(2).mp4", delay: 2000, type: "video" } ], options: [ { text: "Que legal!", nextId: "step3" } ] }, { id: "step3", messages: [ { text: "Legal nĂ©? A IA cria um personagem 3D super realista tipo Disney/Pixar com o rostinho dele(a)!", delay: 1800, type: "text" }, { text: "Ela jĂĄ gera todos os arquivos em PDF prontinhos. Olha esses exemplos:", delay: 1500, type: "text" }, { text: "https://s3.seureview.com.br/festamagica/6a591904-cf2a-4a51-8581-1891373eea29/805441e0-925e-4674-b7b3-ba640431eeb1/adesivos-redondos.webp", delay: 1500, type: "image" }, { text: "https://s3.seureview.com.br/festamagica/6a591904-cf2a-4a51-8581-1891373eea29/805441e0-925e-4674-b7b3-ba640431eeb1/convite-digital.webp", delay: 1500, type: "image" }, { text: "DĂĄ para fazer topo de bolo, painel, convite, adesivo... tudo no tema.", delay: 1800, type: "text" } ], options: [ { text: "Amei! Quanto custa?", nextId: "step4" } ] }, { id: "step4", messages: [ { text: "Bem menos que vocĂȘ imagina! đŸ„°", delay: 1200, type: "text" }, { text: "Liberamos um Pacote Inicial promocional por apenas R$ 9,99 (pagamento Ășnico).", delay: 1500, type: "text" }, { text: "VocĂȘ jĂĄ entra com 10 crĂ©ditos para usar como quiser na nossa plataforma.", delay: 1500, type: "text" }, { text: "Quer garantir agora antes que o lote acabe?", delay: 1200, type: "text" } ], options: [ { text: "Eu quero!", nextId: "checkout_step" } ] }, { id: "checkout_step", messages: [ { text: "Ótimo! Pra gente gerar o seu acesso seguro, qual Ă© o seu melhor e-mail?", delay: 1000, type: "text" } ], requireEmail: true } ]; let sharedAudioCtx: AudioContext | null = null; function getAudioContext() { if (!sharedAudioCtx) { const AudioContextClass = window.AudioContext || (window as any).webkitAudioContext; if (AudioContextClass) { sharedAudioCtx = new AudioContextClass(); } } return sharedAudioCtx; } function getCookie(name: string) { const match = document.cookie.match( new RegExp('(^| )' + name + '=([^;]+)') ); return match ? match[2] : ''; } function playMessageSound() { try { const ctx = getAudioContext(); if (!ctx) return; if (ctx.state === 'suspended') ctx.resume(); const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.connect(gain); gain.connect(ctx.destination); osc.type = 'sine'; osc.frequency.setValueAtTime(800, ctx.currentTime); osc.frequency.exponentialRampToValueAtTime(300, ctx.currentTime + 0.1); gain.gain.setValueAtTime(0.2, ctx.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + 0.1); osc.start(ctx.currentTime); osc.stop(ctx.currentTime + 0.1); } catch (e) {} } function playTypingSound() { try { const ctx = getAudioContext(); if (!ctx) return; if (ctx.state === 'suspended') ctx.resume(); const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.connect(gain); gain.connect(ctx.destination); osc.type = 'triangle'; osc.frequency.setValueAtTime(200, ctx.currentTime); gain.gain.setValueAtTime(0.01, ctx.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.05); osc.start(ctx.currentTime); osc.stop(ctx.currentTime + 0.05); } catch (e) {} } export default function WhatsAppFunnel() { const [messages, setMessages] = useState([]); const [isTyping, setIsTyping] = useState(false); const [currentOptions, setCurrentOptions] = useState([]); const [currentRequireEmail, setCurrentRequireEmail] = useState(false); const [emailInput, setEmailInput] = useState(''); const [isLoadingCheckout, setIsLoadingCheckout] = useState(false); const chatEndRef = useRef(null); const scrollToBottom = () => { setTimeout(() => { chatEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, 100); }; const playNode = async (nodeId: string) => { setCurrentOptions([]); setCurrentRequireEmail(false); const node = funnelData.find((n) => n.id === nodeId); if (!node) return; for (let i = 0; i < node.messages.length; i++) { const msg = node.messages[i]; const delayBefore = msg.delay ? msg.delay : ((msg.type && msg.type !== 'text') ? 1500 : Math.min(400 + (msg.text.length * 30), 3000)); setIsTyping(true); scrollToBottom(); const typingInterval = setInterval(() => { if (Math.random() > 0.3) playTypingSound(); }, 150); await new Promise((r) => setTimeout(r, delayBefore)); clearInterval(typingInterval); setIsTyping(false); playMessageSound(); setMessages((prev) => [ ...prev, { id: Math.random().toString(), sender: 'bot', type: msg.type || 'text', content: msg.text, }, ]); scrollToBottom(); await new Promise((r) => setTimeout(r, 400)); } if (node.options && node.options.length > 0) { setCurrentOptions(node.options); scrollToBottom(); } if (node.requireEmail) { setCurrentRequireEmail(true); scrollToBottom(); } }; const initialized = useRef(false); useEffect(() => { if (!initialized.current) { initialized.current = true; getAudioContext(); playNode('start'); } }, []); const handleOptionClick = (opt: OptionConfig) => { const ctx = getAudioContext(); if (ctx && ctx.state === 'suspended') { ctx.resume(); } setMessages((prev) => [ ...prev, { id: Math.random().toString(), sender: 'user', type: 'text', content: opt.text, }, ]); setCurrentOptions([]); scrollToBottom(); if (opt.actionLink) { setTimeout(() => { window.location.href = opt.actionLink!; }, 800); } else if (opt.nextId) { setTimeout(() => { playNode(opt.nextId!); }, 600); } }; const handleEmailSubmit = async (e: FormEvent) => { e.preventDefault(); if (!emailInput) return; // Add user email message and a bot "loading" message setMessages((prev) => [ ...prev, { id: Math.random().toString(), sender: 'user', type: 'text', content: emailInput, }, { id: 'loading-checkout', sender: 'bot', type: 'text', content: 'Processando seu e-mail e gerando o link de pagamento ⏳...', } ]); setCurrentRequireEmail(false); setIsLoadingCheckout(true); scrollToBottom(); // Fire Meta Pixel event if (typeof window !== 'undefined' && 'fbq' in window) { (window as any).fbq('track', 'InitiateCheckout'); } const fbp = getCookie('_fbp'); const fbc = getCookie('_fbc'); console.log('FBP:', fbp); console.log('FBC:', fbc); try { const res = await fetch('https://n8n.seureview.com.br/webhook/festa-magica-stripe', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ source: 'landing', // Usando 'landing' para aproveitar a mesma configuração do n8n userEmail: emailInput, fbp, fbc }), }); const data = await res.json(); if (data.success && data.url) { // Redireciona para o checkout do stripe window.location.href = data.url; } else { setIsLoadingCheckout(false); setCurrentRequireEmail(true); // Remove loading message setMessages((prev) => prev.filter(m => m.id !== 'loading-checkout')); alert('Ocorreu um erro ao gerar o checkout. Tente novamente.'); } } catch (err) { setIsLoadingCheckout(false); setCurrentRequireEmail(true); // Remove loading message setMessages((prev) => prev.filter(m => m.id !== 'loading-checkout')); alert('Erro de conexĂŁo. Verifique sua internet e tente novamente.'); } }; const renderMessageContent = (m: RenderedMessage) => { if (m.type === 'image') { return ( Media ); } else if (m.type === 'video') { return (