"use client"; import { useState, useEffect } from 'react'; import { useParams, useRouter } from 'next/navigation'; import { FunnelIcon, Cog6ToothIcon, TrashIcon, PencilIcon, CheckIcon, ChevronUpIcon, ChevronDownIcon, RectangleStackIcon, ArrowLeftIcon } from '@heroicons/react/24/outline'; import KanbanBoard from '@/components/crm/KanbanBoard'; import { useToast } from '@/components/layout/ToastContext'; import Modal from '@/components/layout/Modal'; import ConfirmDialog from '@/components/layout/ConfirmDialog'; interface Stage { id: string; name: string; color: string; order_index: number; } interface Funnel { id: string; name: string; description: string; is_default: boolean; } export default function FunnelDetailPage() { const params = useParams(); const router = useRouter(); const funnelId = params.id as string; const [funnel, setFunnel] = useState(null); const [stages, setStages] = useState([]); const [loading, setLoading] = useState(true); const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false); const [isSaving, setIsSaving] = useState(false); const [editingStageId, setEditingStageId] = useState(null); const [confirmStageOpen, setConfirmStageOpen] = useState(false); const [stageToDelete, setStageToDelete] = useState(null); const [newStageForm, setNewStageForm] = useState({ name: '', color: '#3b82f6' }); const [editStageForm, setEditStageForm] = useState<{ id: string; name: string; color: string }>({ id: '', name: '', color: '' }); const toast = useToast(); useEffect(() => { fetchFunnel(); fetchStages(); }, [funnelId]); const fetchFunnel = async () => { try { const response = await fetch(`/api/crm/funnels/${funnelId}`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); if (response.ok) { const data = await response.json(); setFunnel(data.funnel); } else { toast.error('Funil não encontrado'); router.push('/crm/funis'); } } catch (error) { console.error('Error fetching funnel:', error); toast.error('Erro ao carregar funil'); router.push('/crm/funis'); } finally { setLoading(false); } }; const fetchStages = async () => { try { const response = await fetch(`/api/crm/funnels/${funnelId}/stages`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); if (response.ok) { const data = await response.json(); setStages((data.stages || []).sort((a: Stage, b: Stage) => a.order_index - b.order_index)); } } catch (error) { console.error('Error fetching stages:', error); toast.error('Erro ao carregar etapas'); } }; const handleAddStage = async () => { if (!newStageForm.name.trim()) { toast.error('Digite o nome da etapa'); return; } try { const response = await fetch(`/api/crm/funnels/${funnelId}/stages`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` }, body: JSON.stringify({ name: newStageForm.name, color: newStageForm.color, order_index: stages.length }) }); if (response.ok) { toast.success('Etapa criada'); setNewStageForm({ name: '', color: '#3b82f6' }); fetchStages(); // Notificar o KanbanBoard para refetch window.dispatchEvent(new Event('kanban-refresh')); } } catch (error) { toast.error('Erro ao criar etapa'); } }; const handleUpdateStage = async () => { if (!editStageForm.name.trim()) { toast.error('Nome não pode estar vazio'); return; } try { const response = await fetch(`/api/crm/funnels/${funnelId}/stages/${editStageForm.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` }, body: JSON.stringify({ name: editStageForm.name, color: editStageForm.color, order_index: stages.find(s => s.id === editStageForm.id)?.order_index || 0 }) }); if (response.ok) { toast.success('Etapa atualizada'); setEditingStageId(null); fetchStages(); window.dispatchEvent(new Event('kanban-refresh')); } } catch (error) { toast.error('Erro ao atualizar etapa'); } }; const handleDeleteStage = async () => { if (!stageToDelete) return; try { const response = await fetch(`/api/crm/funnels/${funnelId}/stages/${stageToDelete}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); if (response.ok) { toast.success('Etapa excluída'); fetchStages(); window.dispatchEvent(new Event('kanban-refresh')); } else { toast.error('Erro ao excluir etapa'); } } catch (error) { toast.error('Erro ao excluir etapa'); } finally { setConfirmStageOpen(false); setStageToDelete(null); } }; const handleMoveStage = async (stageId: string, direction: 'up' | 'down') => { const idx = stages.findIndex(s => s.id === stageId); if (idx === -1) return; if (direction === 'up' && idx === 0) return; if (direction === 'down' && idx === stages.length - 1) return; const newStages = [...stages]; const targetIdx = direction === 'up' ? idx - 1 : idx + 1; [newStages[idx], newStages[targetIdx]] = [newStages[targetIdx], newStages[idx]]; try { await Promise.all( newStages.map((s, i) => fetch(`/api/crm/funnels/${funnelId}/stages/${s.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` }, body: JSON.stringify({ ...s, order_index: i }) }) ) ); fetchStages(); window.dispatchEvent(new Event('kanban-refresh')); } catch (error) { toast.error('Erro ao reordenar etapas'); } }; if (loading) { return (
); } if (!funnel) { return null; } return (
{/* Header */}

{funnel.name} {funnel.is_default && ( PADRÃO )}

{funnel.description && (

{funnel.description}

)}
{/* Kanban */} {stages.length === 0 ? (

Nenhuma etapa configurada

Configure as etapas do funil para começar a gerenciar seus leads.

) : ( )} {/* Modal Configurações */} setIsSettingsModalOpen(false)} title="Configurar Etapas do Funil" maxWidth="2xl" >
{/* Nova Etapa */}

Nova Etapa

setNewStageForm({ ...newStageForm, name: e.target.value })} onKeyPress={e => e.key === 'Enter' && handleAddStage()} />
setNewStageForm({ ...newStageForm, color: e.target.value })} className="w-12 h-10 rounded-lg cursor-pointer" />
{/* Lista de Etapas */}

Etapas Configuradas

{stages.length === 0 ? (
Nenhuma etapa configurada. Adicione a primeira etapa acima.
) : (
{stages.map((stage, idx) => (
{editingStageId === stage.id ? ( <> setEditStageForm({ ...editStageForm, name: e.target.value })} onKeyPress={e => e.key === 'Enter' && handleUpdateStage()} /> setEditStageForm({ ...editStageForm, color: e.target.value })} className="w-12 h-10 rounded-lg cursor-pointer" /> ) : ( <>
{stage.name} )}
))}
)}
{ setConfirmStageOpen(false); setStageToDelete(null); }} onConfirm={handleDeleteStage} title="Excluir Etapa" message="Tem certeza que deseja excluir esta etapa? Leads nesta etapa permanecerão no funil mas sem uma etapa definida." confirmText="Excluir" cancelText="Cancelar" />
); }