"use client"; import { useState, useEffect } from 'react'; import { FunnelIcon, PlusIcon, TrashIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline'; import { useRouter } from 'next/navigation'; import { useToast } from '@/components/layout/ToastContext'; import Modal from '@/components/layout/Modal'; import ConfirmDialog from '@/components/layout/ConfirmDialog'; interface Funnel { id: string; name: string; description: string; is_default: boolean; } const FUNNEL_TEMPLATES = [ { name: 'Vendas Padrão', description: 'Funil clássico para prospecção e fechamento de negócios.', stages: [ { name: 'Novo Lead', color: '#3b82f6' }, { name: 'Qualificado', color: '#10b981' }, { name: 'Reunião Agendada', color: '#f59e0b' }, { name: 'Proposta Enviada', color: '#6366f1' }, { name: 'Negociação', color: '#8b5cf6' }, { name: 'Fechado / Ganho', color: '#22c55e' }, { name: 'Perdido', color: '#ef4444' } ] }, { name: 'Onboarding de Clientes', description: 'Acompanhamento após a venda até o sucesso do cliente.', stages: [ { name: 'Contrato Assinado', color: '#10b981' }, { name: 'Briefing', color: '#3b82f6' }, { name: 'Setup Inicial', color: '#6366f1' }, { name: 'Treinamento', color: '#f59e0b' }, { name: 'Lançamento', color: '#8b5cf6' }, { name: 'Sucesso', color: '#22c55e' } ] }, { name: 'Suporte / Atendimento', description: 'Gestão de chamados e solicitações de clientes.', stages: [ { name: 'Aberto', color: '#ef4444' }, { name: 'Em Atendimento', color: '#f59e0b' }, { name: 'Aguardando Cliente', color: '#3b82f6' }, { name: 'Resolvido', color: '#10b981' }, { name: 'Fechado', color: '#71717a' } ] } ]; export default function FunisPage() { const router = useRouter(); const [funnels, setFunnels] = useState([]); const [campaigns, setCampaigns] = useState([]); const [loading, setLoading] = useState(true); const [isFunnelModalOpen, setIsFunnelModalOpen] = useState(false); const [isSaving, setIsSaving] = useState(false); const [searchTerm, setSearchTerm] = useState(''); const [confirmOpen, setConfirmOpen] = useState(false); const [funnelToDelete, setFunnelToDelete] = useState(null); const [funnelForm, setFunnelForm] = useState({ name: '', description: '', template_index: -1, campaign_id: '' }); const toast = useToast(); useEffect(() => { fetchFunnels(); fetchCampaigns(); }, []); const fetchCampaigns = async () => { try { const response = await fetch('/api/crm/lists', { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); if (response.ok) { const data = await response.json(); setCampaigns(data.lists || []); } } catch (error) { console.error('Erro ao buscar campanhas:', error); } }; const fetchFunnels = async () => { try { const response = await fetch('/api/crm/funnels', { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); if (response.ok) { const data = await response.json(); setFunnels(data.funnels || []); } } catch (error) { console.error('Error fetching funnels:', error); toast.error('Erro ao carregar funis'); } finally { setLoading(false); } }; const handleCreateFunnel = async (e: React.FormEvent) => { e.preventDefault(); setIsSaving(true); try { const response = await fetch('/api/crm/funnels', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` }, body: JSON.stringify({ name: funnelForm.name, description: funnelForm.description, is_default: funnels.length === 0 }) }); if (response.ok) { const data = await response.json(); const newFunnelId = data.id; // Se selecionou uma campanha, vincular o funil a ela if (funnelForm.campaign_id) { const campaign = campaigns.find(c => c.id === funnelForm.campaign_id); if (campaign) { await fetch(`/api/crm/lists/${campaign.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` }, body: JSON.stringify({ ...campaign, funnel_id: newFunnelId }) }); } } // Se escolheu um template, criar as etapas if (funnelForm.template_index >= 0) { const template = FUNNEL_TEMPLATES[funnelForm.template_index]; for (let i = 0; i < template.stages.length; i++) { const s = template.stages[i]; await fetch(`/api/crm/funnels/${newFunnelId}/stages`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` }, body: JSON.stringify({ name: s.name, color: s.color, order_index: i }) }); } } toast.success('Funil criado com sucesso'); setIsFunnelModalOpen(false); setFunnelForm({ name: '', description: '', template_index: -1, campaign_id: '' }); fetchFunnels(); router.push(`/crm/funis/${newFunnelId}`); } } catch (error) { toast.error('Erro ao criar funil'); } finally { setIsSaving(false); } }; const handleDeleteFunnel = async () => { if (!funnelToDelete) return; try { const response = await fetch(`/api/crm/funnels/${funnelToDelete}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); if (response.ok) { toast.success('Funil excluído com sucesso'); setFunnels(funnels.filter(f => f.id !== funnelToDelete)); } else { toast.error('Erro ao excluir funil'); } } catch (error) { toast.error('Erro ao excluir funil'); } finally { setConfirmOpen(false); setFunnelToDelete(null); } }; const filteredFunnels = funnels.filter(f => f.name.toLowerCase().includes(searchTerm.toLowerCase()) || (f.description || '').toLowerCase().includes(searchTerm.toLowerCase()) ); return (
{/* Header */}

Funis de Vendas

Gerencie seus funis e acompanhe o progresso dos leads

{/* Search */}
setSearchTerm(e.target.value)} />
{/* Content */} {loading ? (
) : filteredFunnels.length === 0 ? (

Nenhum funil encontrado

{searchTerm ? 'Nenhum funil corresponde à sua busca.' : 'Comece criando seu primeiro funil de vendas.'}

) : (
{filteredFunnels.map((funnel) => ( router.push(`/crm/funis/${funnel.id}`)} className="group hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors cursor-pointer" > ))}
Funil Etapas Status Ações
{funnel.name} {funnel.is_default && ( PADRÃO )}
{funnel.description && (
{funnel.description}
)}
Clique para ver
Ativo
)} {/* Modal Criar Funil */} setIsFunnelModalOpen(false)} title="Criar Novo Funil" maxWidth="2xl" >
setFunnelForm({ ...funnelForm, name: e.target.value })} />