import React, { useState } from 'react'; import { Search, Plus, DollarSign, CheckCircle2, TrendingUp, Trash2, X, Calendar, Pencil, RefreshCw, Sparkles, ChevronDown } from 'lucide-react'; import { Receivable } from '../types'; import { useToast } from '../contexts/ToastContext'; import { useComFi } from '../contexts/ComFiContext'; import { CustomSelect } from './CustomSelect'; interface AccountsReceivableViewProps { receivables: Receivable[]; setReceivables: React.Dispatch>; } export const AccountsReceivableView: React.FC = ({ receivables, setReceivables }) => { const { addToast } = useToast(); const { companies } = useComFi(); // Acesso ao CRM para gerar recorrência const [isModalOpen, setIsModalOpen] = useState(false); const [filterStatus, setFilterStatus] = useState<'all' | 'paid' | 'pending'>('all'); const [newReceivable, setNewReceivable] = useState>({ type: 'one-time', status: 'pending', dueDate: new Date().toISOString().split('T')[0] }); const [editingId, setEditingId] = useState(null); // KPI Calculations const totalReceivable = receivables.reduce((acc, curr) => acc + curr.value, 0); const totalReceived = receivables.filter(r => r.status === 'paid').reduce((acc, curr) => acc + curr.value, 0); const totalPending = receivables.filter(r => r.status === 'pending' || r.status === 'overdue').reduce((acc, curr) => acc + curr.value, 0); const filteredList = receivables.filter(r => filterStatus === 'all' ? true : r.status === (filterStatus === 'paid' ? 'paid' : 'pending')); // --- ACTIONS --- const handleGenerateRecurring = () => { const currentMonth = new Date().toISOString().slice(0, 7); // YYYY-MM const today = new Date().toISOString().split('T')[0]; let generatedCount = 0; const newReceivables: Receivable[] = []; companies.forEach(company => { if (company.status !== 'active') return; company.activeServices.forEach(service => { if (service.billingType === 'recurring') { // Check duplicates for this month const exists = receivables.find(r => r.companyName === (company.fantasyName || company.name) && r.description === service.name && r.dueDate.startsWith(currentMonth) ); if (!exists) { newReceivables.push({ id: Math.random().toString(36).substr(2, 9), description: service.name, companyName: company.fantasyName || company.name, category: service.category, value: service.price, dueDate: today, // Simplificação: gera para hoje ou data padrão de vencimento status: 'pending', type: 'recurring' }); generatedCount++; } } }); }); if (generatedCount > 0) { setReceivables(prev => [...prev, ...newReceivables]); addToast({ type: 'success', title: 'Processamento Concluído', message: `${generatedCount} faturas recorrentes foram geradas.` }); } else { addToast({ type: 'info', title: 'Tudo em dia', message: 'Todas as cobranças recorrentes deste mês já foram geradas.' }); } }; const handleSave = () => { if (!newReceivable.description || !newReceivable.value) { addToast({ type: 'warning', title: 'Dados Incompletos', message: 'Preencha a descrição e o valor.' }); return; } if (editingId) { setReceivables(receivables.map(r => r.id === editingId ? { ...newReceivable, id: editingId, value: Number(newReceivable.value), category: newReceivable.category || 'Outros', companyName: newReceivable.companyName || 'Avulso' } as Receivable : r)); addToast({ type: 'success', title: 'Atualizado', message: 'Recebimento atualizado com sucesso.' }); } else { const item: Receivable = { ...newReceivable, id: Math.random().toString(36).substr(2, 9), value: Number(newReceivable.value), category: newReceivable.category || 'Outros', companyName: newReceivable.companyName || 'Avulso' } as Receivable; setReceivables([...receivables, item]); addToast({ type: 'success', title: 'Criado', message: 'Novo recebimento registrado.' }); } setIsModalOpen(false); setEditingId(null); setNewReceivable({ type: 'one-time', status: 'pending', dueDate: new Date().toISOString().split('T')[0] }); }; const handleDelete = (id: string) => { if(window.confirm("Excluir recebimento?")) { setReceivables(receivables.filter(r => r.id !== id)); addToast({ type: 'info', title: 'Excluído', message: 'Registro removido.' }); } } const toggleStatus = (id: string) => { setReceivables(receivables.map(r => { if(r.id === id) { const newStatus = r.status === 'paid' ? 'pending' : 'paid'; if (newStatus === 'paid') addToast({ type: 'success', title: 'Recebido!', message: `Valor de R$ ${r.value} confirmado.` }); return { ...r, status: newStatus }; } return r; })); } const openEditModal = (item: Receivable) => { setNewReceivable(item); setEditingId(item.id); setIsModalOpen(true); }; const openCreateModal = () => { setNewReceivable({ type: 'one-time', status: 'pending', dueDate: new Date().toISOString().split('T')[0] }); setEditingId(null); setIsModalOpen(true); } const inputClass = "w-full p-3 bg-white border border-slate-200 rounded-xl focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none text-slate-800"; return (
{/* KPI Cards */}

Receita Total Prevista

R$ {totalReceivable.toLocaleString('pt-BR')}

Recebido

R$ {totalReceived.toLocaleString('pt-BR')}

A Receber

R$ {totalPending.toLocaleString('pt-BR')}

Contas a Receber

Gestão de faturas, contratos e recebimentos avulsos.

{/* Toolbar */}
{/* Table */}
{filteredList.map(item => ( ))}
Descrição / Cliente Categoria Vencimento Valor Tipo Status
{item.description}
{item.companyName}
{item.category}
{new Date(item.dueDate).toLocaleDateString('pt-BR')}
R$ {item.value.toLocaleString('pt-BR')} {item.type === 'recurring' ? 'Mensal' : 'Avulso'}
{filteredList.length === 0 && (

Nenhum lançamento encontrado.

)}
{/* Modal */} {isModalOpen && (
setIsModalOpen(false)}>

{editingId ? 'Editar Recebimento' : 'Novo Recebimento'}

setNewReceivable({...newReceivable, description: e.target.value})} />
setNewReceivable({...newReceivable, companyName: e.target.value})} />
setNewReceivable({...newReceivable, value: Number(e.target.value)})} />
setNewReceivable({...newReceivable, dueDate: e.target.value})} />
setNewReceivable({...newReceivable, category: val})} options={[ { value: 'Serviços', label: 'Serviços' }, { value: 'Produtos', label: 'Produtos' }, { value: 'Reembolso', label: 'Reembolso' }, { value: 'Outros', label: 'Outros' } ]} />
setNewReceivable({...newReceivable, type: val as 'one-time' | 'recurring'})} options={[ { value: 'one-time', label: 'Avulso' }, { value: 'recurring', label: 'Recorrente' } ]} />
)}
); };