"use client"; import { Fragment, useEffect, useState } from 'react'; import { Menu, Transition } from '@headlessui/react'; import ConfirmDialog from '@/components/layout/ConfirmDialog'; import { useToast } from '@/components/layout/ToastContext'; import { UserIcon, TrashIcon, PencilIcon, EllipsisVerticalIcon, MagnifyingGlassIcon, PlusIcon, XMarkIcon, PhoneIcon, EnvelopeIcon, MapPinIcon, TagIcon, } from '@heroicons/react/24/outline'; interface Customer { id: string; tenant_id: string; name: string; email: string; phone: string; company: string; position: string; address: string; city: string; state: string; zip_code: string; country: string; tags: string[]; notes: string; created_at: string; updated_at: string; } export default function CustomersPage() { const toast = useToast(); const [customers, setCustomers] = useState([]); const [loading, setLoading] = useState(true); const [isModalOpen, setIsModalOpen] = useState(false); const [editingCustomer, setEditingCustomer] = useState(null); const [confirmOpen, setConfirmOpen] = useState(false); const [customerToDelete, setCustomerToDelete] = useState(null); const [searchTerm, setSearchTerm] = useState(''); const [formData, setFormData] = useState({ name: '', email: '', phone: '', company: '', position: '', address: '', city: '', state: '', zip_code: '', country: 'Brasil', tags: '', notes: '', }); useEffect(() => { fetchCustomers(); }, []); const fetchCustomers = async () => { try { const response = await fetch('/api/crm/customers', { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, }, }); if (response.ok) { const data = await response.json(); setCustomers(data.customers || []); } } catch (error) { console.error('Error fetching customers:', error); } finally { setLoading(false); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const url = editingCustomer ? `/api/crm/customers/${editingCustomer.id}` : '/api/crm/customers'; const method = editingCustomer ? 'PUT' : 'POST'; const payload = { ...formData, tags: formData.tags.split(',').map(t => t.trim()).filter(t => t.length > 0), }; try { const response = await fetch(url, { method, headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }); if (response.ok) { toast.success( editingCustomer ? 'Cliente atualizado' : 'Cliente criado', editingCustomer ? 'O cliente foi atualizado com sucesso.' : 'O novo cliente foi criado com sucesso.' ); fetchCustomers(); handleCloseModal(); } else { const error = await response.json(); toast.error('Erro', error.message || 'Não foi possível salvar o cliente.'); } } catch (error) { console.error('Error saving customer:', error); toast.error('Erro', 'Ocorreu um erro ao salvar o cliente.'); } }; const handleEdit = (customer: Customer) => { setEditingCustomer(customer); setFormData({ name: customer.name, email: customer.email, phone: customer.phone, company: customer.company, position: customer.position, address: customer.address, city: customer.city, state: customer.state, zip_code: customer.zip_code, country: customer.country, tags: customer.tags?.join(', ') || '', notes: customer.notes, }); setIsModalOpen(true); }; const handleDeleteClick = (id: string) => { setCustomerToDelete(id); setConfirmOpen(true); }; const handleConfirmDelete = async () => { if (!customerToDelete) return; try { const response = await fetch(`/api/crm/customers/${customerToDelete}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, }, }); if (response.ok) { setCustomers(customers.filter(c => c.id !== customerToDelete)); toast.success('Cliente excluído', 'O cliente foi excluído com sucesso.'); } else { toast.error('Erro ao excluir', 'Não foi possível excluir o cliente.'); } } catch (error) { console.error('Error deleting customer:', error); toast.error('Erro ao excluir', 'Ocorreu um erro ao excluir o cliente.'); } finally { setConfirmOpen(false); setCustomerToDelete(null); } }; const handleCloseModal = () => { setIsModalOpen(false); setEditingCustomer(null); setFormData({ name: '', email: '', phone: '', company: '', position: '', address: '', city: '', state: '', zip_code: '', country: 'Brasil', tags: '', notes: '', }); }; const filteredCustomers = customers.filter((customer) => { const searchLower = searchTerm.toLowerCase(); return ( (customer.name?.toLowerCase() || '').includes(searchLower) || (customer.email?.toLowerCase() || '').includes(searchLower) || (customer.company?.toLowerCase() || '').includes(searchLower) || (customer.phone?.toLowerCase() || '').includes(searchLower) ); }); return (
{/* Header */}

Clientes

Gerencie seus clientes e contatos

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

Nenhum cliente encontrado

{searchTerm ? 'Nenhum cliente corresponde à sua busca.' : 'Comece adicionando seu primeiro cliente.'}

) : (
{filteredCustomers.map((customer) => ( ))}
Cliente Empresa Contato Tags Ações
{customer.name.substring(0, 2).toUpperCase()}
{customer.name}
{customer.position && (
{customer.position}
)}
{customer.company || '-'}
{customer.email && (
{customer.email}
)} {customer.phone && (
{customer.phone}
)}
{customer.tags && customer.tags.length > 0 ? ( customer.tags.slice(0, 3).map((tag, idx) => ( {tag} )) ) : ( - )} {customer.tags && customer.tags.length > 3 && ( +{customer.tags.length - 3} )}
{({ active }) => ( )}
{({ active }) => ( )}
)} {/* Modal */} {isModalOpen && (

{editingCustomer ? 'Editar Cliente' : 'Novo Cliente'}

{editingCustomer ? 'Atualize as informações do cliente.' : 'Adicione um novo cliente ao seu CRM.'}

setFormData({ ...formData, name: e.target.value })} required className="w-full px-3 py-2.5 border border-zinc-200 dark:border-zinc-700 rounded-lg bg-white dark:bg-zinc-900 text-zinc-900 dark:text-white placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-[var(--brand-color)] focus:border-transparent transition-all" />
setFormData({ ...formData, email: e.target.value })} className="w-full px-3 py-2.5 border border-zinc-200 dark:border-zinc-700 rounded-lg bg-white dark:bg-zinc-900 text-zinc-900 dark:text-white placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-[var(--brand-color)] focus:border-transparent transition-all" />
setFormData({ ...formData, phone: e.target.value })} className="w-full px-3 py-2.5 border border-zinc-200 dark:border-zinc-700 rounded-lg bg-white dark:bg-zinc-900 text-zinc-900 dark:text-white placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-[var(--brand-color)] focus:border-transparent transition-all" />
setFormData({ ...formData, company: e.target.value })} className="w-full px-3 py-2.5 border border-zinc-200 dark:border-zinc-700 rounded-lg bg-white dark:bg-zinc-900 text-zinc-900 dark:text-white placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-[var(--brand-color)] focus:border-transparent transition-all" />
setFormData({ ...formData, position: e.target.value })} className="w-full px-3 py-2.5 border border-zinc-200 dark:border-zinc-700 rounded-lg bg-white dark:bg-zinc-900 text-zinc-900 dark:text-white placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-[var(--brand-color)] focus:border-transparent transition-all" />
setFormData({ ...formData, tags: e.target.value })} placeholder="vip, premium, lead-quente" className="w-full px-3 py-2.5 border border-zinc-200 dark:border-zinc-700 rounded-lg bg-white dark:bg-zinc-900 text-zinc-900 dark:text-white placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-[var(--brand-color)] focus:border-transparent transition-all" />