/** * Supera Glia - Tab Financeiro (Módulo Completo) * @module tabs/financeiro/FinanceiroTab * @version 2.1 - Adicionado controle de contratos */ (function() { 'use strict'; SuperaGlia.initFinanceiroTab = function() { const { useState, useEffect, useMemo } = SuperaGlia.hooks; const { API_BASE } = SuperaGlia.config; const { Icon, perfilColors } = SuperaGlia; const { formatMoney, formatDate } = SuperaGlia.utils; // Cores para gráficos const CORES_GRAFICO = ['#f97316', '#3b82f6', '#22c55e', '#ef4444', '#a855f7', '#ec4899', '#14b8a6', '#f59e0b', '#6366f1', '#84cc16']; // Funções auxiliares de data const getToday = () => new Date().toISOString().split('T')[0]; const getDateDaysAgo = (days) => { const d = new Date(); d.setDate(d.getDate() - days); return d.toISOString().split('T')[0]; }; const getDateDaysAhead = (days) => { const d = new Date(); d.setDate(d.getDate() + days); return d.toISOString().split('T')[0]; }; const getMonthName = (mesRef) => { if (!mesRef) return '-'; const meses = ['', 'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez']; const [ano, mes] = mesRef.split('-'); return `${meses[parseInt(mes)]}/${ano}`; }; // Função para calcular dias até vencimento do contrato const diasParaVencimento = (terminoContrato) => { if (!terminoContrato) return null; const hoje = new Date(); hoje.setHours(0, 0, 0, 0); const termino = new Date(terminoContrato); termino.setHours(0, 0, 0, 0); const diffTime = termino - hoje; const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); return diffDays; }; // Função para calcular quantidade de renovações baseado na duração do contrato const calcularRenovacoes = (inicioContrato, terminoContrato, diasNoSupera) => { if (!inicioContrato || !terminoContrato || !diasNoSupera) return 0; // Duração típica de um contrato é 6 meses (180 dias) ou 12 meses (365 dias) // Se o aluno está há mais tempo que a duração do contrato atual, teve renovações const inicio = new Date(inicioContrato); const termino = new Date(terminoContrato); const duracaoContratoAtual = Math.ceil((termino - inicio) / (1000 * 60 * 60 * 24)); if (duracaoContratoAtual <= 0) return 0; // Se dias_no_supera > duração do contrato atual, houve renovação(ões) const renovacoes = Math.floor(diasNoSupera / duracaoContratoAtual); return Math.max(0, renovacoes); }; SuperaGlia.FinanceiroTab = ({ dados }) => { // Extrair alunos com fallback seguro const alunos = dados?.alunos || []; // ========== ESTADOS GERAIS ========== const [subTab, setSubTab] = useState('resumo'); const [saldos, setSaldos] = useState([]); const [titulos, setTitulos] = useState([]); const [extrato, setExtrato] = useState([]); const [carregando, setCarregando] = useState(true); const [carregandoExtrato, setCarregandoExtrato] = useState(false); const [erro, setErro] = useState(null); // ========== ESTADOS TÍTULOS ========== const [filtroFaixa, setFiltroFaixa] = useState('todos'); const [filtroPago, setFiltroPago] = useState('todos'); const [buscaTitulos, setBuscaTitulos] = useState(''); // ========== ESTADOS EXTRATO ========== const [filtroBanco, setFiltroBanco] = useState('todos'); const [filtroTipo, setFiltroTipo] = useState('todos'); const [filtroCategoria, setFiltroCategoria] = useState('todos'); const [dataInicio, setDataInicio] = useState(() => getDateDaysAgo(7)); const [dataFim, setDataFim] = useState(() => getToday()); const [buscaExtrato, setBuscaExtrato] = useState(''); // ========== ESTADOS CLIENTES ========== const [buscaCliente, setBuscaCliente] = useState(''); const [filtroSituacaoCliente, setFiltroSituacaoCliente] = useState(''); const [filtroPerfilCliente, setFiltroPerfilCliente] = useState(''); const [filtroContratoInicio, setFiltroContratoInicio] = useState(''); const [filtroContratoFim, setFiltroContratoFim] = useState(''); const [filtroVencimentoInicio, setFiltroVencimentoInicio] = useState(''); const [filtroVencimentoFim, setFiltroVencimentoFim] = useState(''); const [selectedCliente, setSelectedCliente] = useState(null); const [abaDetalhe, setAbaDetalhe] = useState('dados'); const [clienteBoletos, setClienteBoletos] = useState([]); const [clienteNfse, setClienteNfse] = useState([]); const [clienteEnvios, setClienteEnvios] = useState([]); const [carregandoBoletos, setCarregandoBoletos] = useState(false); const [carregandoNfse, setCarregandoNfse] = useState(false); const [carregandoEnvios, setCarregandoEnvios] = useState(false); // ========== ESTADOS CONTAS A PAGAR ========== const [contasAPagar, setContasAPagar] = useState([]); const [carregandoContasPagar, setCarregandoContasPagar] = useState(false); const [dataInicioContas, setDataInicioContas] = useState(() => getDateDaysAgo(90)); const [dataFimContas, setDataFimContas] = useState(() => getToday()); const [filtroStatusContas, setFiltroStatusContas] = useState(''); const [filtroClassificacao, setFiltroClassificacao] = useState(''); const [buscaContaPagar, setBuscaContaPagar] = useState(''); // ========== ESTADOS VENDAS ========== const [vendas, setVendas] = useState([]); const [carregandoVendas, setCarregandoVendas] = useState(false); const [dataInicioVendas, setDataInicioVendas] = useState(() => getDateDaysAgo(30)); const [dataFimVendas, setDataFimVendas] = useState(() => getToday()); const [filtroProduto, setFiltroProduto] = useState(''); const [filtroVendedor, setFiltroVendedor] = useState(''); const [buscaVenda, setBuscaVenda] = useState(''); // ========== ESTADOS ESTOQUE ========== const [estoque, setEstoque] = useState({ inventario: [], entregas: [], adquirir: [], kitsEntregues: [] }); const [carregandoEstoque, setCarregandoEstoque] = useState(false); const [abaEstoque, setAbaEstoque] = useState('inventario'); const [buscaEstoque, setBuscaEstoque] = useState(''); // ========== ESTADOS CARTÕES (MAQUININHA) ========== const [cartoesResumo, setCartoesResumo] = useState(null); const [cartoesVendas, setCartoesVendas] = useState([]); const [cartoesAReceber, setCartoesAReceber] = useState([]); const [carregandoCartoes, setCarregandoCartoes] = useState(false); const [carregandoCartoesVendas, setCarregandoCartoesVendas] = useState(false); const [carregandoCartoesReceber, setCarregandoCartoesReceber] = useState(false); const [abaCartoes, setAbaCartoes] = useState('resumo'); const [dataInicioCartoes, setDataInicioCartoes] = useState(() => { const d = new Date(); return new Date(d.getFullYear(), d.getMonth(), 1).toISOString().split('T')[0]; }); const [dataFimCartoes, setDataFimCartoes] = useState(() => getToday()); const [filtroBandeiraCartoes, setFiltroBandeiraCartoes] = useState('todos'); const [filtroFormaPagCartoes, setFiltroFormaPagCartoes] = useState('todos'); const [buscaCartoes, setBuscaCartoes] = useState(''); // ========== ESTADOS RESUMO DASHBOARD ========== const getMesAtual = () => { const d = new Date(); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`; }; const [mesResumoTitulos, setMesResumoTitulos] = useState(getMesAtual); const [mesResumoContas, setMesResumoContas] = useState(getMesAtual); const [mesResumoVendas, setMesResumoVendas] = useState(getMesAtual); const [mesResumoCartoes, setMesResumoCartoes] = useState(getMesAtual); const [contasResumo, setContasResumo] = useState([]); const [carregandoContasResumo, setCarregandoContasResumo] = useState(false); const [vendasResumo, setVendasResumo] = useState([]); const [carregandoVendasResumo, setCarregandoVendasResumo] = useState(false); const [cartoesVendasResumo, setCartoesVendasResumo] = useState([]); const [carregandoCartoesVendasResumo, setCarregandoCartoesVendasResumo] = useState(false); // Cores por bandeira const CORES_BANDEIRA = { 'Mastercard': '#eb001b', 'Visa': '#1a1f71', 'Elo': '#00a4e0', 'Hipercard': '#b3131b', 'American Express': '#006fcf', 'Amex': '#006fcf' }; // ========== EFEITOS ========== useEffect(() => { carregarDadosIniciais(); }, []); useEffect(() => { if (subTab === 'extrato' && extrato.length === 0) carregarExtrato(); }, [subTab]); useEffect(() => { if (subTab === 'contasapagar' && contasAPagar.length === 0) carregarContasPagar(); }, [subTab]); useEffect(() => { if (subTab === 'vendas' && vendas.length === 0) carregarVendas(); }, [subTab]); useEffect(() => { if (subTab === 'estoque' && estoque.inventario.length === 0) carregarEstoque(); }, [subTab]); useEffect(() => { if (subTab === 'cartoes' && !cartoesResumo) carregarCartoesResumo(); }, [subTab]); // Efeitos para carregar dados do Resumo Dashboard useEffect(() => { if (subTab === 'resumo') { carregarContasResumo(mesResumoContas); carregarVendasResumo(mesResumoVendas); carregarCartoesVendasResumo(mesResumoCartoes); } }, [subTab]); useEffect(() => { if (subTab === 'resumo') carregarContasResumo(mesResumoContas); }, [mesResumoContas]); useEffect(() => { if (subTab === 'resumo') carregarVendasResumo(mesResumoVendas); }, [mesResumoVendas]); useEffect(() => { if (subTab === 'resumo') carregarCartoesVendasResumo(mesResumoCartoes); }, [mesResumoCartoes]); // ========== FUNÇÕES DE CARREGAMENTO ========== const carregarDadosIniciais = async () => { setCarregando(true); setErro(null); try { const [saldosRes, titulosRes] = await Promise.all([ fetch(`${API_BASE}/financeiro/saldos`).then(r => r.json()).catch(() => ({ saldos: [] })), fetch(`${API_BASE}/financeiro/aberto`).then(r => r.json()).catch(() => ({ titulos: [] })) ]); setSaldos(saldosRes?.saldos || []); setTitulos(titulosRes?.titulos || titulosRes?.alunosEmAberto || []); } catch (e) { setErro('Erro ao carregar dados financeiros'); } finally { setCarregando(false); } }; const carregarExtrato = async () => { setCarregandoExtrato(true); try { const params = new URLSearchParams({ dataInicio, dataFim }); if (filtroBanco !== 'todos') params.append('banco', filtroBanco); if (filtroTipo !== 'todos') params.append('tipo', filtroTipo); if (filtroCategoria !== 'todos') params.append('categoria', filtroCategoria); const res = await fetch(`${API_BASE}/financeiro/extrato?${params}`).then(r => r.json()).catch(() => ({ extrato: [] })); setExtrato(res?.extrato || []); } catch (e) { console.error('Erro ao carregar extrato:', e); } finally { setCarregandoExtrato(false); } }; const carregarContasPagar = async () => { setCarregandoContasPagar(true); try { const params = new URLSearchParams({ dataInicio: dataInicioContas, dataFim: dataFimContas }); if (filtroStatusContas) params.append('status', filtroStatusContas); if (filtroClassificacao) params.append('classificacao', filtroClassificacao); const res = await fetch(`${API_BASE}/financeiro/contas-a-pagar?${params}`).then(r => r.json()).catch(() => ({ contas: [] })); setContasAPagar(res?.contas || []); } catch (e) { console.error('Erro ao carregar contas:', e); } finally { setCarregandoContasPagar(false); } }; const carregarVendas = async () => { setCarregandoVendas(true); try { const params = new URLSearchParams({ dataInicio: dataInicioVendas, dataFim: dataFimVendas }); const res = await fetch(`${API_BASE}/financeiro/vendas?${params}`).then(r => r.json()).catch(() => ({ vendas: [] })); setVendas(res?.vendas || []); } catch (e) { console.error('Erro ao carregar vendas:', e); } finally { setCarregandoVendas(false); } }; const carregarEstoque = async () => { setCarregandoEstoque(true); try { const res = await fetch(`${API_BASE}/financeiro/estoque`).then(r => r.json()).catch(() => ({})); setEstoque({ inventario: res?.inventario || [], entregas: res?.entregas || [], adquirir: res?.adquirir || [], kitsEntregues: res?.kitsEntregues || [] }); } catch (e) { console.error('Erro ao carregar estoque:', e); } finally { setCarregandoEstoque(false); } }; // ========== FUNÇÕES CARTÕES ========== const carregarCartoesResumo = async () => { setCarregandoCartoes(true); try { const res = await fetch(`${API_BASE}/cartoes/resumo`).then(r => r.json()).catch(() => ({})); setCartoesResumo(res); } catch (e) { console.error('Erro ao carregar resumo de cartões:', e); } finally { setCarregandoCartoes(false); } }; const carregarCartoesVendas = async () => { setCarregandoCartoesVendas(true); try { const params = new URLSearchParams({ dataInicio: dataInicioCartoes, dataFim: dataFimCartoes }); if (filtroBandeiraCartoes !== 'todos') params.append('bandeira', filtroBandeiraCartoes); if (filtroFormaPagCartoes !== 'todos') params.append('formaPagamento', filtroFormaPagCartoes); const res = await fetch(`${API_BASE}/cartoes/vendas?${params}`).then(r => r.json()).catch(() => ({ vendas: [] })); setCartoesVendas(res?.vendas || []); } catch (e) { console.error('Erro ao carregar vendas de cartões:', e); } finally { setCarregandoCartoesVendas(false); } }; const carregarCartoesAReceber = async () => { setCarregandoCartoesReceber(true); try { const params = new URLSearchParams({ dataInicio: getToday(), dataFim: getDateDaysAhead(30) }); const res = await fetch(`${API_BASE}/cartoes/a-receber?${params}`).then(r => r.json()).catch(() => ({ recebimentos: [] })); setCartoesAReceber(res?.recebimentos || []); } catch (e) { console.error('Erro ao carregar a receber:', e); } finally { setCarregandoCartoesReceber(false); } }; // ========== FUNÇÕES RESUMO DASHBOARD ========== const carregarContasResumo = async (mes) => { setCarregandoContasResumo(true); try { const [ano, mesNum] = mes.split('-'); const dataInicio = `${ano}-${mesNum}-01`; const ultimoDia = new Date(parseInt(ano), parseInt(mesNum), 0).getDate(); const dataFim = `${ano}-${mesNum}-${String(ultimoDia).padStart(2, '0')}`; const params = new URLSearchParams({ dataInicio, dataFim }); const res = await fetch(`${API_BASE}/financeiro/contas-a-pagar?${params}`).then(r => r.json()).catch(() => ({ contas: [] })); setContasResumo(res?.contas || []); } catch (e) { console.error('Erro ao carregar contas resumo:', e); } finally { setCarregandoContasResumo(false); } }; const carregarVendasResumo = async (mes) => { setCarregandoVendasResumo(true); try { const [ano, mesNum] = mes.split('-'); const dataInicio = `${ano}-${mesNum}-01`; const ultimoDia = new Date(parseInt(ano), parseInt(mesNum), 0).getDate(); const dataFim = `${ano}-${mesNum}-${String(ultimoDia).padStart(2, '0')}`; const params = new URLSearchParams({ dataInicio, dataFim }); const res = await fetch(`${API_BASE}/financeiro/vendas?${params}`).then(r => r.json()).catch(() => ({ vendas: [] })); setVendasResumo(res?.vendas || []); } catch (e) { console.error('Erro ao carregar vendas resumo:', e); } finally { setCarregandoVendasResumo(false); } }; const carregarCartoesVendasResumo = async (mes) => { setCarregandoCartoesVendasResumo(true); try { const [ano, mesNum] = mes.split('-'); const dataInicio = `${ano}-${mesNum}-01`; const ultimoDia = new Date(parseInt(ano), parseInt(mesNum), 0).getDate(); const dataFim = `${ano}-${mesNum}-${String(ultimoDia).padStart(2, '0')}`; const params = new URLSearchParams({ dataInicio, dataFim }); const res = await fetch(`${API_BASE}/cartoes/vendas?${params}`).then(r => r.json()).catch(() => ({ vendas: [] })); setCartoesVendasResumo(res?.vendas || []); } catch (e) { console.error('Erro ao carregar cartões resumo:', e); } finally { setCarregandoCartoesVendasResumo(false); } }; const carregarBoletosCliente = async (codAluno) => { setCarregandoBoletos(true); try { const res = await fetch(`${API_BASE}/clientes/boletos?codAluno=${codAluno}`); const data = await res.json(); setClienteBoletos(data.boletos || []); } catch (e) { setClienteBoletos([]); } finally { setCarregandoBoletos(false); } }; const carregarNfseCliente = async (codAluno) => { setCarregandoNfse(true); try { const res = await fetch(`${API_BASE}/clientes/nfse?codAluno=${codAluno}`); const data = await res.json(); setClienteNfse(data.notas || []); } catch (e) { setClienteNfse([]); } finally { setCarregandoNfse(false); } }; const carregarEnviosCliente = async (codAluno) => { setCarregandoEnvios(true); try { const res = await fetch(`${API_BASE}/clientes/envios-cobranca?codAluno=${codAluno}`); const data = await res.json(); setClienteEnvios(data.envios || []); } catch (e) { setClienteEnvios([]); } finally { setCarregandoEnvios(false); } }; // ========== SELEÇÃO DE CLIENTE ========== const selecionarCliente = (cliente) => { setSelectedCliente(cliente); setAbaDetalhe('dados'); setClienteBoletos([]); setClienteNfse([]); setClienteEnvios([]); }; const trocarAbaDetalhe = (aba) => { setAbaDetalhe(aba); if (aba === 'boletos' && clienteBoletos.length === 0 && selectedCliente) carregarBoletosCliente(selectedCliente.cod_aluno); if (aba === 'nfse' && clienteNfse.length === 0 && selectedCliente) carregarNfseCliente(selectedCliente.cod_aluno); if (aba === 'envios' && clienteEnvios.length === 0 && selectedCliente) carregarEnviosCliente(selectedCliente.cod_aluno); }; // ========== FILTROS E CÁLCULOS ========== const faixas = useMemo(() => { return [...new Set(titulos.map(t => t.faixa_atraso).filter(Boolean))]; }, [titulos]); const titulosFiltrados = useMemo(() => { return titulos.filter(t => { if (filtroFaixa !== 'todos' && t.faixa_atraso !== filtroFaixa) return false; if (filtroPago === 'pago' && !t.alerta?.includes('PAGO')) return false; if (filtroPago === 'pendente' && t.alerta?.includes('PAGO')) return false; if (buscaTitulos) { const busca = buscaTitulos.toLowerCase(); if (!t.nome_aluno?.toLowerCase().includes(busca) && !t.aluno?.toLowerCase().includes(busca) && !t.resp_financeiro_nome?.toLowerCase().includes(busca)) return false; } return true; }); }, [titulos, filtroFaixa, filtroPago, buscaTitulos]); const categoriasExtrato = useMemo(() => { return [...new Set(extrato.map(e => e.categoria).filter(Boolean))].sort(); }, [extrato]); const extratoFiltrado = useMemo(() => { return extrato.filter(e => { if (buscaExtrato) { const busca = buscaExtrato.toLowerCase(); if (!e.descricao?.toLowerCase().includes(busca) && !e.documento?.toLowerCase().includes(busca)) return false; } return true; }); }, [extrato, buscaExtrato]); const totaisExtrato = useMemo(() => ({ entradas: extratoFiltrado.filter(e => e.tipo === 'CREDITO').reduce((s, e) => s + (parseFloat(e.entrada) || parseFloat(e.valor) || 0), 0), saidas: extratoFiltrado.filter(e => e.tipo === 'DEBITO').reduce((s, e) => s + (parseFloat(e.saida) || parseFloat(e.valor) || 0), 0) }), [extratoFiltrado]); const totalAberto = useMemo(() => { return titulos.filter(t => !t.alerta?.includes('PAGO')).reduce((s, t) => s + (parseFloat(t.valor_previsto) || parseFloat(t.valor_sophia) || 0), 0); }, [titulos]); const totalSaldos = useMemo(() => { return saldos.reduce((s, b) => s + (parseFloat(b.saldo_disponivel) || parseFloat(b.saldo) || 0), 0); }, [saldos]); // Resumo de títulos const resumoTitulos = useMemo(() => ({ total: titulos.length, pagos: titulos.filter(t => t.alerta?.includes('PAGO')).length, vencidos: titulos.filter(t => !t.alerta?.includes('PAGO') && t.dias_atraso > 0).length, aVencer: titulos.filter(t => !t.alerta?.includes('PAGO') && t.dias_atraso <= 0).length }), [titulos]); // ========== RESUMO DASHBOARD - MEMOS ========== // Títulos filtrados por mês selecionado const titulosPorMes = useMemo(() => { return titulos.filter(t => { if (!t.data_vencimento || !mesResumoTitulos) return true; return t.data_vencimento.startsWith(mesResumoTitulos); }); }, [titulos, mesResumoTitulos]); const resumoTitulosMes = useMemo(() => { const vencidos = titulosPorMes.filter(t => !t.alerta?.includes('PAGO') && t.dias_atraso > 0); const pagos = titulosPorMes.filter(t => t.alerta?.includes('PAGO')); const aVencer = titulosPorMes.filter(t => !t.alerta?.includes('PAGO') && t.dias_atraso <= 0); return { vencidosQtd: vencidos.length, vencidosValor: vencidos.reduce((s, t) => s + (parseFloat(t.valor_previsto) || parseFloat(t.valor_sophia) || 0), 0), pagosQtd: pagos.length, pagosValor: pagos.reduce((s, t) => s + (parseFloat(t.valor_previsto) || parseFloat(t.valor_sophia) || 0), 0), aVencerQtd: aVencer.length, aVencerValor: aVencer.reduce((s, t) => s + (parseFloat(t.valor_previsto) || parseFloat(t.valor_sophia) || 0), 0) }; }, [titulosPorMes]); // Resumo de Alunos const resumoAlunos = useMemo(() => { const vigentes = alunos.filter(a => a.situacao_matricula === 'Vigente'); const titulosVigentes = titulos.filter(t => { return vigentes.some(a => t.nome_aluno?.toLowerCase() === a.nome?.toLowerCase() || t.aluno?.toLowerCase() === a.nome?.toLowerCase() ); }); const mediaMensalidade = titulosVigentes.length > 0 ? titulosVigentes.reduce((s, t) => s + (parseFloat(t.valor_previsto) || parseFloat(t.valor_sophia) || 0), 0) / titulosVigentes.length : 0; return { qtdVigentes: vigentes.length, mediaMensalidade }; }, [alunos, titulos]); // Contas a Pagar por Classificação const contasPorClassificacao = useMemo(() => { const agrupado = {}; contasResumo.forEach(c => { const cls = c.classificacao_desc || 'Outros'; if (!agrupado[cls]) agrupado[cls] = { pago: 0, aPagar: 0 }; if (c.status === 'pago') { agrupado[cls].pago += parseFloat(c.valor) || 0; } else { agrupado[cls].aPagar += parseFloat(c.valor) || 0; } }); return Object.entries(agrupado) .map(([classificacao, valores]) => ({ classificacao, ...valores })) .sort((a, b) => (b.pago + b.aPagar) - (a.pago + a.aPagar)); }, [contasResumo]); // Totais de Vendas do Resumo const totaisVendasResumo = useMemo(() => ({ quantidade: vendasResumo.length, totalEntrada: vendasResumo.reduce((s, v) => s + (parseFloat(v.valor_entrada) || 0), 0) }), [vendasResumo]); // Cartões por tipo de pagamento const resumoCartoesPorTipo = useMemo(() => { const debito = cartoesVendasResumo.filter(v => v.forma_pagamento?.toLowerCase().includes('débito') || v.forma_pagamento?.toLowerCase().includes('debito') ); const creditoAVista = cartoesVendasResumo.filter(v => (v.forma_pagamento?.toLowerCase().includes('crédito') || v.forma_pagamento?.toLowerCase().includes('credito')) && (!v.total_parcelas || v.total_parcelas <= 1) ); const creditoParcelado = cartoesVendasResumo.filter(v => (v.forma_pagamento?.toLowerCase().includes('crédito') || v.forma_pagamento?.toLowerCase().includes('credito')) && v.total_parcelas > 1 ); const cancelados = cartoesVendasResumo.filter(v => v.indicador_credito_debito === 'D' ); const calcular = (arr) => ({ qtd: arr.length, valor: arr.reduce((s, v) => s + (parseFloat(v.valor_parcela_bruto) || 0), 0) }); return { debito: calcular(debito), creditoAVista: calcular(creditoAVista), creditoParcelado: calcular(creditoParcelado), cancelados: calcular(cancelados) }; }, [cartoesVendasResumo]); // ========== CONTRATOS A VENCER ========== const contratosAVencer = useMemo(() => { const hoje = new Date(); hoje.setHours(0, 0, 0, 0); const em30dias = new Date(); em30dias.setDate(em30dias.getDate() + 30); return alunos.filter(a => { if (!a.termino_contrato || a.situacao_matricula !== 'Vigente') return false; const termino = new Date(a.termino_contrato); termino.setHours(0, 0, 0, 0); // Contratos que vencem nos próximos 30 dias ou já vencidos (mas aluno ainda ativo) return termino <= em30dias; }).map(a => ({ ...a, diasParaVencer: diasParaVencimento(a.termino_contrato) })).sort((a, b) => (a.diasParaVencer || 0) - (b.diasParaVencer || 0)); }, [alunos]); const resumoContratos = useMemo(() => { const vencidos = contratosAVencer.filter(c => c.diasParaVencer !== null && c.diasParaVencer < 0).length; const venceHoje = contratosAVencer.filter(c => c.diasParaVencer === 0).length; const vence7dias = contratosAVencer.filter(c => c.diasParaVencer !== null && c.diasParaVencer > 0 && c.diasParaVencer <= 7).length; const vence30dias = contratosAVencer.filter(c => c.diasParaVencer !== null && c.diasParaVencer > 7 && c.diasParaVencer <= 30).length; return { vencidos, venceHoje, vence7dias, vence30dias, total: contratosAVencer.length }; }, [contratosAVencer]); // Clientes const situacoesCliente = useMemo(() => { return [...new Set(alunos.map(a => a.situacao_matricula).filter(Boolean))].sort(); }, [alunos]); const perfisCliente = useMemo(() => { return [...new Set(alunos.map(a => a.perfil).filter(Boolean))].sort(); }, [alunos]); const clientesFiltrados = useMemo(() => { return alunos.filter(a => { const matchSearch = !buscaCliente || a.nome?.toLowerCase().includes(buscaCliente.toLowerCase()) || a.cpf_aluno?.includes(buscaCliente) || a.resp_financeiro_nome?.toLowerCase().includes(buscaCliente.toLowerCase()); const matchSituacao = !filtroSituacaoCliente || a.situacao_matricula === filtroSituacaoCliente; const matchPerfil = !filtroPerfilCliente || a.perfil === filtroPerfilCliente; // Filtro por data de início do contrato let matchContratoInicio = true; if (filtroContratoInicio && a.inicio_contrato) { matchContratoInicio = a.inicio_contrato >= filtroContratoInicio; } let matchContratoFim = true; if (filtroContratoFim && a.inicio_contrato) { matchContratoFim = a.inicio_contrato <= filtroContratoFim; } // Filtro por data de vencimento do contrato let matchVencimentoInicio = true; if (filtroVencimentoInicio && a.termino_contrato) { matchVencimentoInicio = a.termino_contrato >= filtroVencimentoInicio; } let matchVencimentoFim = true; if (filtroVencimentoFim && a.termino_contrato) { matchVencimentoFim = a.termino_contrato <= filtroVencimentoFim; } return matchSearch && matchSituacao && matchPerfil && matchContratoInicio && matchContratoFim && matchVencimentoInicio && matchVencimentoFim; }); }, [alunos, buscaCliente, filtroSituacaoCliente, filtroPerfilCliente, filtroContratoInicio, filtroContratoFim, filtroVencimentoInicio, filtroVencimentoFim]); // Contas a Pagar const classificacoesContas = useMemo(() => { return [...new Set(contasAPagar.map(c => c.classificacao_desc).filter(Boolean))].sort(); }, [contasAPagar]); const contasFiltradas = useMemo(() => { return contasAPagar.filter(c => { if (buscaContaPagar) { const busca = buscaContaPagar.toLowerCase(); if (!c.nome?.toLowerCase().includes(busca) && !c.descricao?.toLowerCase().includes(busca)) return false; } return true; }); }, [contasAPagar, buscaContaPagar]); const totaisContas = useMemo(() => ({ total: contasFiltradas.reduce((s, c) => s + (parseFloat(c.valor) || 0), 0), pagos: contasFiltradas.filter(c => c.status === 'pago').reduce((s, c) => s + (parseFloat(c.valor) || 0), 0), pendente: contasFiltradas.filter(c => c.status !== 'pago').reduce((s, c) => s + (parseFloat(c.valor) || 0), 0) }), [contasFiltradas]); // Vendas const produtosUnicos = useMemo(() => [...new Set(vendas.map(v => v.produto).filter(Boolean))].sort(), [vendas]); const vendedoresUnicos = useMemo(() => [...new Set(vendas.map(v => v.vendedor).filter(Boolean))].sort(), [vendas]); const vendasFiltradas = useMemo(() => { return vendas.filter(v => { if (filtroProduto && v.produto !== filtroProduto) return false; if (filtroVendedor && v.vendedor !== filtroVendedor) return false; if (buscaVenda && !v.nome?.toLowerCase().includes(buscaVenda.toLowerCase()) && !v.produto?.toLowerCase().includes(buscaVenda.toLowerCase())) return false; return true; }); }, [vendas, filtroProduto, filtroVendedor, buscaVenda]); const totaisVendas = useMemo(() => ({ totalBruto: vendasFiltradas.reduce((s, v) => s + (parseFloat(v.valor_bruto) || 0), 0), totalDesconto: vendasFiltradas.reduce((s, v) => s + (parseFloat(v.valor_desconto) || 0), 0), totalEntrada: vendasFiltradas.reduce((s, v) => s + (parseFloat(v.valor_entrada) || 0), 0) }), [vendasFiltradas]); // Funções auxiliares para gráficos const calcularDadosGraficoTempo = (contas) => { const porMes = {}; contas.forEach(c => { const data = new Date(c.data_vencimento); const mes = `${data.toLocaleString('pt-BR', { month: 'short' })}. de ${String(data.getFullYear()).slice(-2)}`; if (!porMes[mes]) porMes[mes] = { mes, pago: 0, pendente: 0 }; if (c.status === 'pago') porMes[mes].pago += parseFloat(c.valor) || 0; else porMes[mes].pendente += parseFloat(c.valor) || 0; }); return Object.values(porMes).slice(-4); }; const calcularDadosGraficoClassificacao = (contas) => { const porClass = {}; contas.forEach(c => { const cls = c.classificacao_desc || 'Outros'; if (!porClass[cls]) porClass[cls] = 0; porClass[cls] += parseFloat(c.valor) || 0; }); return Object.entries(porClass) .sort((a, b) => b[1] - a[1]) .slice(0, 10) .map(([name, value]) => ({ name, value })); }; // ========== HELPERS ========== const subTabs = [ { id: 'resumo', label: 'Resumo', icon: 'layout-dashboard' }, { id: 'titulos', label: 'Títulos em Aberto', icon: 'file-text' }, { id: 'extrato', label: 'Extrato Consolidado', icon: 'list' }, { id: 'clientes', label: 'Clientes', icon: 'users' }, { id: 'contasapagar', label: 'Contas a Pagar', icon: 'receipt' }, { id: 'vendas', label: 'Vendas', icon: 'shopping-cart' }, { id: 'cartoes', label: 'Cartões', icon: 'credit-card' }, { id: 'estoque', label: 'Estoque', icon: 'package' } ]; const getBancoStyle = (banco) => { const b = (banco || '').toLowerCase(); if (b.includes('cora')) return { name: 'Cora', bg: 'bg-pink-100', text: 'text-pink-700', icon: 'C', iconBg: 'bg-pink-500' }; if (b.includes('sicoob')) return { name: 'Sicoob', bg: 'bg-green-100', text: 'text-green-700', icon: 'S', iconBg: 'bg-green-500' }; if (b.includes('inter')) return { name: 'Inter', bg: 'bg-orange-100', text: 'text-orange-700', icon: 'I', iconBg: 'bg-orange-500' }; return { name: banco || '-', bg: 'bg-gray-100', text: 'text-gray-700', icon: '?', iconBg: 'bg-gray-500' }; }; const getStatusClass = (status) => { switch(status) { case 'PAID': return 'bg-green-100 text-green-700'; case 'OVERDUE': return 'bg-red-100 text-red-700'; default: return 'bg-orange-100 text-orange-700'; } }; const getStatusLabel = (status) => { switch(status) { case 'PAID': return 'Pago'; case 'OVERDUE': return 'Vencido'; case 'PENDING': return 'Aberto'; default: return status || 'Aberto'; } }; const getContratoStatusStyle = (dias) => { if (dias === null) return { bg: 'bg-gray-100', text: 'text-gray-600', label: 'Sem data' }; if (dias < 0) return { bg: 'bg-red-100', text: 'text-red-700', label: `Vencido há ${Math.abs(dias)} dias` }; if (dias === 0) return { bg: 'bg-red-100', text: 'text-red-700', label: 'Vence hoje!' }; if (dias <= 7) return { bg: 'bg-orange-100', text: 'text-orange-700', label: `Vence em ${dias} dias` }; if (dias <= 30) return { bg: 'bg-yellow-100', text: 'text-yellow-700', label: `Vence em ${dias} dias` }; return { bg: 'bg-green-100', text: 'text-green-700', label: `Vence em ${dias} dias` }; }; const abas = [ { id: 'dados', label: 'Dados', icon: 'user' }, { id: 'contrato', label: 'Contrato', icon: 'file-signature' }, { id: 'boletos', label: 'Boletos', icon: 'file-text' }, { id: 'nfse', label: 'Notas Fiscais', icon: 'receipt' }, { id: 'envios', label: 'Envios de Alerta', icon: 'send' } ]; // Limpar filtros de contrato const limparFiltrosContrato = () => { setFiltroContratoInicio(''); setFiltroContratoFim(''); setFiltroVencimentoInicio(''); setFiltroVencimentoFim(''); }; // Loading inicial if (carregando) { return React.createElement('div', { className: 'flex items-center justify-center h-64' }, React.createElement('div', { className: 'text-center' }, React.createElement('div', { className: 'w-10 h-10 border-4 border-orange-200 border-t-orange-500 rounded-full animate-spin mx-auto mb-4' }), React.createElement('p', { className: 'text-gray-500' }, 'Carregando dados financeiros...') ) ); } // ========== RENDER PRINCIPAL ========== return React.createElement('div', { className: 'space-y-4' }, // Sub-navegação React.createElement('div', { className: 'flex gap-2 bg-white rounded-xl p-2 shadow-sm border overflow-x-auto' }, subTabs.map(tab => React.createElement('button', { key: tab.id, onClick: () => setSubTab(tab.id), className: `flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-medium transition-all whitespace-nowrap ${ subTab === tab.id ? 'bg-orange-500 text-white shadow-md' : 'text-gray-600 hover:bg-gray-100' }` }, React.createElement(Icon, { name: tab.icon, className: 'w-4 h-4' }), tab.label )) ), // ========== RESUMO ========== subTab === 'resumo' && React.createElement('div', { className: 'space-y-6' }, // Seção: Saldos Bancários React.createElement('div', null, React.createElement('h3', { className: 'text-xs font-semibold text-gray-500 uppercase mb-3' }, 'Saldos Bancários'), React.createElement('div', { className: 'grid grid-cols-1 md:grid-cols-4 gap-4' }, saldos.map((s, i) => { const banco = getBancoStyle(s.banco); return React.createElement('div', { key: i, className: 'bg-white rounded-xl shadow-sm border p-5' }, React.createElement('div', { className: 'flex items-center gap-3 mb-3' }, React.createElement('div', { className: `w-10 h-10 ${banco.iconBg} rounded-xl flex items-center justify-center` }, React.createElement('span', { className: 'text-lg font-bold text-white' }, banco.icon) ), React.createElement('div', null, React.createElement('p', { className: 'text-sm text-gray-500' }, `${banco.name} - ${s.conta || 'Principal'}`), React.createElement('p', { className: 'text-xs text-gray-400' }, s.ultima_atualizacao || s.data_atualizacao || '-') ) ), React.createElement('p', { className: 'text-2xl font-bold text-gray-900' }, formatMoney(parseFloat(s.saldo_disponivel) || parseFloat(s.saldo) || 0)) ); }), saldos.length === 0 && React.createElement('div', { className: 'col-span-3 text-center text-gray-500 py-8' }, 'Nenhum saldo disponível'), React.createElement('div', { className: 'bg-gradient-to-br from-orange-500 to-orange-600 rounded-xl shadow-lg p-5 text-white' }, React.createElement('div', { className: 'flex items-center justify-between mb-3' }, React.createElement('span', { className: 'text-xs px-2 py-1 rounded-full bg-white/20' }, 'Total'), React.createElement(Icon, { name: 'trending-up', className: 'w-5 h-5' }) ), React.createElement('p', { className: 'text-2xl font-bold' }, formatMoney(totalSaldos)), React.createElement('p', { className: 'text-xs opacity-75 mt-1' }, 'Saldo total') ) ) ), // Seção: Títulos (com filtro mensal) React.createElement('div', null, React.createElement('div', { className: 'flex items-center justify-between mb-3' }, React.createElement('h3', { className: 'text-xs font-semibold text-gray-500 uppercase' }, 'Títulos'), React.createElement('input', { type: 'month', value: mesResumoTitulos, onChange: e => setMesResumoTitulos(e.target.value), className: 'px-3 py-1.5 border border-gray-200 rounded-lg text-sm bg-white' }) ), React.createElement('div', { className: 'grid grid-cols-1 md:grid-cols-3 gap-4' }, // Card Vencidos React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('div', { className: 'flex items-center gap-3 mb-2' }, React.createElement('div', { className: 'w-10 h-10 bg-red-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'alert-circle', className: 'w-5 h-5 text-white' }) ), React.createElement('span', { className: 'text-sm font-medium text-gray-700' }, 'Vencidos') ), React.createElement('div', { className: 'flex justify-between items-end' }, React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Quantidade'), React.createElement('p', { className: 'text-xl font-bold text-red-600' }, resumoTitulosMes.vencidosQtd) ), React.createElement('div', { className: 'text-right' }, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Valor'), React.createElement('p', { className: 'text-lg font-semibold text-red-600' }, formatMoney(resumoTitulosMes.vencidosValor)) ) ) ), // Card Pagos React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('div', { className: 'flex items-center gap-3 mb-2' }, React.createElement('div', { className: 'w-10 h-10 bg-green-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'check-circle', className: 'w-5 h-5 text-white' }) ), React.createElement('span', { className: 'text-sm font-medium text-gray-700' }, 'Pagos') ), React.createElement('div', { className: 'flex justify-between items-end' }, React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Quantidade'), React.createElement('p', { className: 'text-xl font-bold text-green-600' }, resumoTitulosMes.pagosQtd) ), React.createElement('div', { className: 'text-right' }, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Valor'), React.createElement('p', { className: 'text-lg font-semibold text-green-600' }, formatMoney(resumoTitulosMes.pagosValor)) ) ) ), // Card A Vencer React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('div', { className: 'flex items-center gap-3 mb-2' }, React.createElement('div', { className: 'w-10 h-10 bg-amber-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'clock', className: 'w-5 h-5 text-white' }) ), React.createElement('span', { className: 'text-sm font-medium text-gray-700' }, 'A Vencer') ), React.createElement('div', { className: 'flex justify-between items-end' }, React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Quantidade'), React.createElement('p', { className: 'text-xl font-bold text-amber-600' }, resumoTitulosMes.aVencerQtd) ), React.createElement('div', { className: 'text-right' }, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Valor'), React.createElement('p', { className: 'text-lg font-semibold text-amber-600' }, formatMoney(resumoTitulosMes.aVencerValor)) ) ) ) ) ), // Seção: Alunos React.createElement('div', null, React.createElement('h3', { className: 'text-xs font-semibold text-gray-500 uppercase mb-3' }, 'Alunos'), React.createElement('div', { className: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4 flex items-center gap-4' }, React.createElement('div', { className: 'w-12 h-12 bg-blue-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'users', className: 'w-6 h-6 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Alunos Vigentes'), React.createElement('p', { className: 'text-2xl font-bold text-gray-900' }, resumoAlunos.qtdVigentes) ) ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4 flex items-center gap-4' }, React.createElement('div', { className: 'w-12 h-12 bg-purple-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'calculator', className: 'w-6 h-6 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Média das Mensalidades'), React.createElement('p', { className: 'text-2xl font-bold text-gray-900' }, formatMoney(resumoAlunos.mediaMensalidade)) ) ) ) ), // Seção: Contas a Pagar (com filtro mensal) React.createElement('div', null, React.createElement('div', { className: 'flex items-center justify-between mb-3' }, React.createElement('h3', { className: 'text-xs font-semibold text-gray-500 uppercase' }, 'Contas a Pagar'), React.createElement('input', { type: 'month', value: mesResumoContas, onChange: e => setMesResumoContas(e.target.value), className: 'px-3 py-1.5 border border-gray-200 rounded-lg text-sm bg-white' }) ), carregandoContasResumo ? React.createElement('div', { className: 'flex items-center justify-center py-8' }, React.createElement('div', { className: 'w-6 h-6 border-4 border-orange-200 border-t-orange-500 rounded-full animate-spin' }) ) : contasPorClassificacao.length > 0 ? React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border overflow-hidden' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, React.createElement('th', { className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, 'Classificação'), React.createElement('th', { className: 'text-right px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, 'Valor Pago'), React.createElement('th', { className: 'text-right px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, 'Valor a Pagar') ) ), React.createElement('tbody', { className: 'divide-y' }, contasPorClassificacao.map((c, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-4 py-3 text-sm font-medium text-gray-900' }, c.classificacao), React.createElement('td', { className: 'px-4 py-3 text-sm text-right text-green-600 font-medium' }, formatMoney(c.pago)), React.createElement('td', { className: 'px-4 py-3 text-sm text-right text-red-600 font-medium' }, formatMoney(c.aPagar)) ) ) ) ) ) : React.createElement('div', { className: 'bg-gray-50 rounded-xl p-6 text-center text-gray-500' }, 'Nenhuma conta encontrada para o mês selecionado') ), // Seção: Vendas (com filtro mensal) React.createElement('div', null, React.createElement('div', { className: 'flex items-center justify-between mb-3' }, React.createElement('h3', { className: 'text-xs font-semibold text-gray-500 uppercase' }, 'Vendas'), React.createElement('input', { type: 'month', value: mesResumoVendas, onChange: e => setMesResumoVendas(e.target.value), className: 'px-3 py-1.5 border border-gray-200 rounded-lg text-sm bg-white' }) ), carregandoVendasResumo ? React.createElement('div', { className: 'flex items-center justify-center py-8' }, React.createElement('div', { className: 'w-6 h-6 border-4 border-orange-200 border-t-orange-500 rounded-full animate-spin' }) ) : React.createElement('div', { className: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4 flex items-center gap-4' }, React.createElement('div', { className: 'w-12 h-12 bg-indigo-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'shopping-cart', className: 'w-6 h-6 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Quantidade de Vendas'), React.createElement('p', { className: 'text-2xl font-bold text-gray-900' }, totaisVendasResumo.quantidade) ) ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4 flex items-center gap-4' }, React.createElement('div', { className: 'w-12 h-12 bg-emerald-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'banknote', className: 'w-6 h-6 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Soma Valor da Entrada'), React.createElement('p', { className: 'text-2xl font-bold text-gray-900' }, formatMoney(totaisVendasResumo.totalEntrada)) ) ) ) ), // Seção: Cartões (com filtro mensal) React.createElement('div', null, React.createElement('div', { className: 'flex items-center justify-between mb-3' }, React.createElement('h3', { className: 'text-xs font-semibold text-gray-500 uppercase' }, 'Cartões'), React.createElement('input', { type: 'month', value: mesResumoCartoes, onChange: e => setMesResumoCartoes(e.target.value), className: 'px-3 py-1.5 border border-gray-200 rounded-lg text-sm bg-white' }) ), carregandoCartoesVendasResumo ? React.createElement('div', { className: 'flex items-center justify-center py-8' }, React.createElement('div', { className: 'w-6 h-6 border-4 border-orange-200 border-t-orange-500 rounded-full animate-spin' }) ) : React.createElement('div', { className: 'grid grid-cols-2 md:grid-cols-4 gap-4' }, // Débito React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('div', { className: 'flex items-center gap-2 mb-2' }, React.createElement('div', { className: 'w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'credit-card', className: 'w-4 h-4 text-white' }) ), React.createElement('span', { className: 'text-sm font-medium text-gray-700' }, 'Débito') ), React.createElement('p', { className: 'text-xs text-gray-500' }, `${resumoCartoesPorTipo.debito.qtd} vendas`), React.createElement('p', { className: 'text-lg font-bold text-gray-900' }, formatMoney(resumoCartoesPorTipo.debito.valor)) ), // Crédito React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('div', { className: 'flex items-center gap-2 mb-2' }, React.createElement('div', { className: 'w-8 h-8 bg-green-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'credit-card', className: 'w-4 h-4 text-white' }) ), React.createElement('span', { className: 'text-sm font-medium text-gray-700' }, 'Crédito') ), React.createElement('p', { className: 'text-xs text-gray-500' }, `${resumoCartoesPorTipo.creditoAVista.qtd} vendas`), React.createElement('p', { className: 'text-lg font-bold text-gray-900' }, formatMoney(resumoCartoesPorTipo.creditoAVista.valor)) ), // Crédito Parcelado React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('div', { className: 'flex items-center gap-2 mb-2' }, React.createElement('div', { className: 'w-8 h-8 bg-purple-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'layers', className: 'w-4 h-4 text-white' }) ), React.createElement('span', { className: 'text-sm font-medium text-gray-700' }, 'Créd. Parcelado') ), React.createElement('p', { className: 'text-xs text-gray-500' }, `${resumoCartoesPorTipo.creditoParcelado.qtd} vendas`), React.createElement('p', { className: 'text-lg font-bold text-gray-900' }, formatMoney(resumoCartoesPorTipo.creditoParcelado.valor)) ), // Cancelados/Débitos React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('div', { className: 'flex items-center gap-2 mb-2' }, React.createElement('div', { className: 'w-8 h-8 bg-red-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'x-circle', className: 'w-4 h-4 text-white' }) ), React.createElement('span', { className: 'text-sm font-medium text-gray-700' }, 'Débitos') ), React.createElement('p', { className: 'text-xs text-gray-500' }, `${resumoCartoesPorTipo.cancelados.qtd} cancelados`), React.createElement('p', { className: 'text-lg font-bold text-red-600' }, formatMoney(resumoCartoesPorTipo.cancelados.valor)) ) ) ), // Seção: Contratos a Vencer React.createElement('div', null, React.createElement('div', { className: 'flex items-center justify-between mb-3' }, React.createElement('h3', { className: 'text-xs font-semibold text-gray-500 uppercase' }, 'Contratos a Vencer'), resumoContratos.total > 0 && React.createElement('span', { className: 'text-xs px-2 py-1 bg-orange-100 text-orange-700 rounded-full' }, `${resumoContratos.total} contratos`) ), React.createElement('div', { className: 'grid grid-cols-2 md:grid-cols-4 gap-4 mb-4' }, React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-red-500 rounded-lg flex items-center justify-center' }, React.createElement('span', { className: 'text-lg font-bold text-white' }, resumoContratos.vencidos) ), React.createElement('span', { className: 'text-sm text-gray-500' }, 'Vencidos') ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-red-400 rounded-lg flex items-center justify-center' }, React.createElement('span', { className: 'text-lg font-bold text-white' }, resumoContratos.venceHoje) ), React.createElement('span', { className: 'text-sm text-gray-500' }, 'Vencem Hoje') ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-orange-500 rounded-lg flex items-center justify-center' }, React.createElement('span', { className: 'text-lg font-bold text-white' }, resumoContratos.vence7dias) ), React.createElement('span', { className: 'text-sm text-gray-500' }, 'Próx. 7 dias') ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-yellow-500 rounded-lg flex items-center justify-center' }, React.createElement('span', { className: 'text-lg font-bold text-white' }, resumoContratos.vence30dias) ), React.createElement('span', { className: 'text-sm text-gray-500' }, 'Próx. 30 dias') ) ), // Lista de contratos a vencer contratosAVencer.length > 0 && React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border overflow-hidden' }, React.createElement('div', { className: 'p-4 border-b bg-gray-50' }, React.createElement('h4', { className: 'font-semibold text-gray-900 flex items-center gap-2' }, React.createElement(Icon, { name: 'alert-triangle', className: 'w-4 h-4 text-orange-500' }), 'Alunos com Contrato a Vencer' ) ), React.createElement('div', { className: 'divide-y max-h-64 overflow-y-auto' }, contratosAVencer.slice(0, 10).map((c, i) => { const status = getContratoStatusStyle(c.diasParaVencer); return React.createElement('div', { key: i, className: 'p-3 hover:bg-gray-50 cursor-pointer flex items-center justify-between', onClick: () => selecionarCliente(c) }, React.createElement('div', { className: 'flex items-center gap-3' }, React.createElement('div', { className: 'w-8 h-8 bg-orange-100 rounded-lg flex items-center justify-center' }, React.createElement('span', { className: 'text-sm font-bold text-orange-600' }, c.nome?.charAt(0)) ), React.createElement('div', null, React.createElement('p', { className: 'font-medium text-gray-900' }, c.nome), React.createElement('p', { className: 'text-xs text-gray-500' }, `Término: ${formatDate(c.termino_contrato)}`) ) ), React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${status.bg} ${status.text}` }, status.label) ); }) ), contratosAVencer.length > 10 && React.createElement('div', { className: 'p-3 bg-gray-50 border-t text-center' }, React.createElement('button', { onClick: () => setSubTab('clientes'), className: 'text-sm text-orange-600 hover:text-orange-700 font-medium' }, `Ver todos os ${contratosAVencer.length} contratos →`) ) ), contratosAVencer.length === 0 && React.createElement('div', { className: 'bg-green-50 border border-green-200 rounded-xl p-6 text-center' }, React.createElement(Icon, { name: 'check-circle', className: 'w-8 h-8 text-green-500 mx-auto mb-2' }), React.createElement('p', { className: 'text-green-700' }, 'Nenhum contrato vencendo nos próximos 30 dias!') ) ) ), // ========== TÍTULOS EM ABERTO ========== subTab === 'titulos' && React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden' }, React.createElement('div', { className: 'p-4 border-b border-gray-100 space-y-4' }, React.createElement('div', { className: 'flex items-center justify-between flex-wrap gap-4' }, React.createElement('div', null, React.createElement('h3', { className: 'font-semibold text-gray-900' }, 'Títulos em Aberto'), React.createElement('p', { className: 'text-sm text-gray-500' }, `${titulosFiltrados.length} de ${titulos.length} registros`) ), React.createElement('button', { onClick: carregarDadosIniciais, className: 'flex items-center gap-2 px-3 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm text-gray-700 transition-colors' }, React.createElement(Icon, { name: 'refresh-cw', className: 'w-4 h-4' }), 'Atualizar' ) ), React.createElement('div', { className: 'flex flex-wrap gap-3' }, React.createElement('input', { type: 'text', placeholder: 'Buscar aluno ou responsável...', value: buscaTitulos, onChange: e => setBuscaTitulos(e.target.value), className: 'flex-1 min-w-[200px] px-3 py-2 border border-gray-200 rounded-lg text-sm' }), React.createElement('select', { value: filtroFaixa, onChange: e => setFiltroFaixa(e.target.value), className: 'px-3 py-2 border border-gray-200 rounded-lg text-sm bg-white' }, React.createElement('option', { value: 'todos' }, 'Todas Faixas'), ['🔵 A vencer', '🟢 1-5 dias', '🟡 6-10 dias', '🟠 11-20 dias', '🔴 21-30 dias', '⚫ +30 dias'].map(f => React.createElement('option', { key: f, value: f }, f)) ), React.createElement('select', { value: filtroPago, onChange: e => setFiltroPago(e.target.value), className: 'px-3 py-2 border border-gray-200 rounded-lg text-sm bg-white' }, React.createElement('option', { value: 'todos' }, 'Todos Status'), React.createElement('option', { value: 'pago' }, '✅ Verificados Pagos'), React.createElement('option', { value: 'pendente' }, '⏳ Pendentes') ) ) ), React.createElement('div', { className: 'overflow-x-auto' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Alerta', 'Aluno', 'Matrícula', 'Faixa', 'Responsável', 'Vencimento', 'Valor', 'Dias'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase whitespace-nowrap' }, h) )) ), React.createElement('tbody', { className: 'divide-y divide-gray-50' }, titulosFiltrados.length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 8, className: 'px-4 py-8 text-center text-gray-500' }, 'Nenhum registro encontrado')) : titulosFiltrados.slice(0, 100).map((item, i) => React.createElement('tr', { key: i, className: `hover:bg-gray-50 ${item.alerta?.includes('PAGO') ? 'bg-green-50/50' : ''}` }, React.createElement('td', { className: 'px-4 py-3 text-sm' }, item.alerta ? React.createElement('span', { className: `text-xs px-2 py-1 rounded-full whitespace-nowrap ${item.alerta.includes('PAGO') ? 'bg-green-100 text-green-700' : item.alerta.includes('⚠️') ? 'bg-amber-100 text-amber-700' : 'bg-gray-100 text-gray-600'}` }, item.alerta) : '-'), React.createElement('td', { className: 'px-4 py-3 font-medium text-gray-900' }, item.nome_aluno || item.aluno || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm' }, React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${item.matricula?.includes('Ativo') ? 'bg-green-100 text-green-700' : item.matricula?.includes('Evadido') ? 'bg-red-100 text-red-700' : 'bg-gray-100 text-gray-600'}` }, item.matricula || '-') ), React.createElement('td', { className: 'px-4 py-3 text-sm whitespace-nowrap' }, item.faixa_atraso || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, item.resp_financeiro_nome || item.responsavel || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600 whitespace-nowrap' }, item.vencimento_fmt || formatDate(item.data_vencimento) || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, formatMoney(item.valor_previsto || item.valor_sophia)), React.createElement('td', { className: 'px-4 py-3 text-sm' }, React.createElement('span', { className: `font-medium ${item.dias_atraso > 0 ? 'text-red-600' : 'text-gray-600'}` }, item.dias_atraso || 0)) ) ) ) ) ), titulosFiltrados.length > 100 && React.createElement('div', { className: 'p-3 bg-gray-50 border-t text-center text-sm text-gray-500' }, `Mostrando 100 de ${titulosFiltrados.length} registros`) ), // ========== EXTRATO CONSOLIDADO ========== subTab === 'extrato' && React.createElement('div', { className: 'space-y-4' }, // Filtros React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border border-gray-100 p-4' }, React.createElement('div', { className: 'flex flex-wrap gap-3 items-end' }, React.createElement('div', { className: 'flex-1 min-w-[150px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Data Início'), React.createElement('input', { type: 'date', value: dataInicio, onChange: e => setDataInicio(e.target.value), className: 'w-full px-3 py-2 border border-gray-200 rounded-lg text-sm' }) ), React.createElement('div', { className: 'flex-1 min-w-[150px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Data Fim'), React.createElement('input', { type: 'date', value: dataFim, onChange: e => setDataFim(e.target.value), className: 'w-full px-3 py-2 border border-gray-200 rounded-lg text-sm' }) ), React.createElement('div', null, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Banco'), React.createElement('select', { value: filtroBanco, onChange: e => setFiltroBanco(e.target.value), className: 'px-3 py-2 border border-gray-200 rounded-lg text-sm bg-white' }, React.createElement('option', { value: 'todos' }, 'Todos'), React.createElement('option', { value: 'Cora' }, 'Cora'), React.createElement('option', { value: 'Sicoob' }, 'Sicoob'), React.createElement('option', { value: 'Inter' }, 'Inter') ) ), React.createElement('div', null, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Tipo'), React.createElement('select', { value: filtroTipo, onChange: e => setFiltroTipo(e.target.value), className: 'px-3 py-2 border border-gray-200 rounded-lg text-sm bg-white' }, React.createElement('option', { value: 'todos' }, 'Todos'), React.createElement('option', { value: 'CREDITO' }, '💰 Crédito'), React.createElement('option', { value: 'DEBITO' }, '💸 Débito') ) ), React.createElement('div', null, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Categoria'), React.createElement('select', { value: filtroCategoria, onChange: e => setFiltroCategoria(e.target.value), className: 'px-3 py-2 border border-gray-200 rounded-lg text-sm bg-white' }, React.createElement('option', { value: 'todos' }, 'Todas'), categoriasExtrato.map(c => React.createElement('option', { key: c, value: c }, c)) ) ), React.createElement('button', { onClick: carregarExtrato, className: 'px-4 py-2 bg-orange-500 hover:bg-orange-600 text-white rounded-lg text-sm font-medium transition-colors flex items-center gap-2' }, React.createElement(Icon, { name: 'search', className: 'w-4 h-4' }), 'Buscar' ) ), React.createElement('input', { type: 'text', placeholder: 'Filtrar por descrição ou CPF/CNPJ...', value: buscaExtrato, onChange: e => setBuscaExtrato(e.target.value), className: 'w-full mt-3 px-3 py-2 border border-gray-200 rounded-lg text-sm' }) ), // Totais React.createElement('div', { className: 'grid grid-cols-2 gap-4' }, React.createElement('div', { className: 'bg-green-50 border border-green-200 rounded-xl p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-green-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'trending-up', className: 'w-5 h-5 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-sm text-green-600' }, 'Total Entradas'), React.createElement('p', { className: 'text-xl font-bold text-green-700' }, formatMoney(totaisExtrato.entradas)) ) ), React.createElement('div', { className: 'bg-red-50 border border-red-200 rounded-xl p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-red-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'trending-down', className: 'w-5 h-5 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-sm text-red-600' }, 'Total Saídas'), React.createElement('p', { className: 'text-xl font-bold text-red-700' }, formatMoney(totaisExtrato.saidas)) ) ) ), // Tabela React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden' }, React.createElement('div', { className: 'p-4 border-b border-gray-100 flex items-center justify-between' }, React.createElement('div', null, React.createElement('h3', { className: 'font-semibold text-gray-900' }, 'Extrato Consolidado'), React.createElement('p', { className: 'text-sm text-gray-500' }, `${extratoFiltrado.length} transações`) ), carregandoExtrato && React.createElement('div', { className: 'w-5 h-5 border-2 border-orange-200 border-t-orange-500 rounded-full animate-spin' }) ), React.createElement('div', { className: 'overflow-x-auto' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Banco', 'Data', 'Tipo', 'Categoria', 'Descrição', 'CPF/CNPJ', 'Entrada', 'Saída'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase whitespace-nowrap' }, h) )) ), React.createElement('tbody', { className: 'divide-y divide-gray-50' }, extratoFiltrado.length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 8, className: 'px-4 py-8 text-center text-gray-500' }, carregandoExtrato ? 'Carregando...' : 'Clique em "Buscar" para carregar o extrato')) : extratoFiltrado.slice(0, 200).map((item, i) => { const banco = getBancoStyle(item.banco); return React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-4 py-3' }, React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${banco.bg} ${banco.text}` }, banco.name) ), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600 whitespace-nowrap' }, formatDate(item.data_transacao)), React.createElement('td', { className: 'px-4 py-3 text-sm' }, React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${item.tipo === 'CREDITO' ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'}` }, item.tipo === 'CREDITO' ? '💰 Crédito' : '💸 Débito') ), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, (item.categoria || '-').replace(/_/g, ' ')), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-900 max-w-[200px] truncate' }, item.descricao || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-500 font-mono' }, item.documento || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium text-green-600' }, item.entrada ? formatMoney(item.entrada) : '-'), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium text-red-600' }, item.saida ? formatMoney(item.saida) : '-') ); }) ) ) ), extratoFiltrado.length > 200 && React.createElement('div', { className: 'p-3 bg-gray-50 border-t text-center text-sm text-gray-500' }, `Mostrando 200 de ${extratoFiltrado.length} transações`) ) ), // ========== CLIENTES ========== subTab === 'clientes' && React.createElement('div', { className: 'space-y-4' }, // Cards de resumo React.createElement('div', { className: 'grid grid-cols-2 md:grid-cols-4 gap-4' }, [ { label: 'Total Clientes', value: alunos.length, color: 'bg-blue-500' }, { label: 'Ativos', value: alunos.filter(a => a.situacao_matricula === 'Vigente').length, color: 'bg-green-500' }, { label: 'Inativos', value: alunos.filter(a => a.situacao_matricula !== 'Vigente').length, color: 'bg-gray-500' }, { label: 'Filtrados', value: clientesFiltrados.length, color: 'bg-orange-500' } ].map((c, i) => React.createElement('div', { key: i, className: 'bg-white rounded-xl shadow-sm border p-4 flex items-center gap-3' }, React.createElement('div', { className: `w-10 h-10 ${c.color} rounded-lg flex items-center justify-center` }, React.createElement('span', { className: 'text-lg font-bold text-white' }, c.value) ), React.createElement('span', { className: 'text-sm text-gray-500' }, c.label) )) ), // Filtros React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4 space-y-3' }, // Primeira linha: busca e filtros básicos React.createElement('div', { className: 'flex flex-wrap gap-3' }, React.createElement('div', { className: 'flex-1 min-w-[200px] relative' }, React.createElement(Icon, { name: 'search', className: 'absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400' }), React.createElement('input', { type: 'text', placeholder: 'Buscar por nome, CPF...', value: buscaCliente, onChange: e => setBuscaCliente(e.target.value), className: 'w-full pl-9 pr-3 py-2 border rounded-lg text-sm' }) ), React.createElement('select', { value: filtroSituacaoCliente, onChange: e => setFiltroSituacaoCliente(e.target.value), className: 'px-3 py-2 border rounded-lg text-sm bg-white' }, React.createElement('option', { value: '' }, 'Todas Situações'), situacoesCliente.map(s => React.createElement('option', { key: s, value: s }, s)) ), React.createElement('select', { value: filtroPerfilCliente, onChange: e => setFiltroPerfilCliente(e.target.value), className: 'px-3 py-2 border rounded-lg text-sm bg-white' }, React.createElement('option', { value: '' }, 'Todos Perfis'), perfisCliente.map(p => React.createElement('option', { key: p, value: p }, p)) ) ), // Segunda linha: filtros de contrato React.createElement('div', { className: 'flex flex-wrap gap-3 items-end pt-2 border-t' }, React.createElement('div', { className: 'flex-1 min-w-[140px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Início Contrato De'), React.createElement('input', { type: 'date', value: filtroContratoInicio, onChange: e => setFiltroContratoInicio(e.target.value), className: 'w-full px-3 py-2 border rounded-lg text-sm' }) ), React.createElement('div', { className: 'flex-1 min-w-[140px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Início Contrato Até'), React.createElement('input', { type: 'date', value: filtroContratoFim, onChange: e => setFiltroContratoFim(e.target.value), className: 'w-full px-3 py-2 border rounded-lg text-sm' }) ), React.createElement('div', { className: 'flex-1 min-w-[140px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Vencimento De'), React.createElement('input', { type: 'date', value: filtroVencimentoInicio, onChange: e => setFiltroVencimentoInicio(e.target.value), className: 'w-full px-3 py-2 border rounded-lg text-sm' }) ), React.createElement('div', { className: 'flex-1 min-w-[140px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Vencimento Até'), React.createElement('input', { type: 'date', value: filtroVencimentoFim, onChange: e => setFiltroVencimentoFim(e.target.value), className: 'w-full px-3 py-2 border rounded-lg text-sm' }) ), (filtroContratoInicio || filtroContratoFim || filtroVencimentoInicio || filtroVencimentoFim) && React.createElement('button', { onClick: limparFiltrosContrato, className: 'px-3 py-2 text-sm text-gray-600 hover:text-gray-800 hover:bg-gray-100 rounded-lg transition-colors' }, 'Limpar filtros') ) ), // Tabela React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border overflow-hidden' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Nome', 'CPF', 'Responsável', 'Situação', 'Perfil', 'Venc. Contrato'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, h)) ) ), React.createElement('tbody', { className: 'divide-y' }, clientesFiltrados.length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 6, className: 'px-4 py-12 text-center text-gray-500' }, 'Nenhum cliente encontrado')) : clientesFiltrados.slice(0, 100).map((c, i) => { const perfilColor = perfilColors[c.perfil] || perfilColors['60+'] || { badge: 'bg-gray-100 text-gray-700' }; const diasVenc = diasParaVencimento(c.termino_contrato); const contratoStatus = getContratoStatusStyle(diasVenc); return React.createElement('tr', { key: i, className: 'hover:bg-orange-50 cursor-pointer', onClick: () => selecionarCliente(c) }, React.createElement('td', { className: 'px-4 py-3' }, React.createElement('div', { className: 'flex items-center gap-2' }, React.createElement('div', { className: 'w-8 h-8 bg-orange-100 rounded-lg flex items-center justify-center' }, React.createElement('span', { className: 'text-sm font-bold text-orange-600' }, c.nome?.charAt(0)) ), React.createElement('span', { className: 'font-medium' }, c.nome) ) ), React.createElement('td', { className: 'px-4 py-3 text-sm font-mono text-gray-600' }, c.cpf_aluno || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, c.resp_financeiro_nome || '-'), React.createElement('td', { className: 'px-4 py-3' }, React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${c.situacao_matricula === 'Vigente' ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-600'}` }, c.situacao_matricula || '-')), React.createElement('td', { className: 'px-4 py-3' }, React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${perfilColor.badge}` }, c.perfil)), React.createElement('td', { className: 'px-4 py-3' }, c.termino_contrato ? React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${contratoStatus.bg} ${contratoStatus.text}` }, formatDate(c.termino_contrato)) : React.createElement('span', { className: 'text-xs text-gray-400' }, '-') ) ); }) ) ) ) ), // Modal de detalhes do cliente selectedCliente && React.createElement('div', { className: 'fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50 p-4', onClick: () => setSelectedCliente(null) }, React.createElement('div', { className: 'bg-white rounded-2xl shadow-2xl w-full max-w-4xl max-h-[90vh] flex flex-col', onClick: e => e.stopPropagation() }, // Header React.createElement('div', { className: 'p-5 border-b flex items-center justify-between' }, React.createElement('div', { className: 'flex items-center gap-3' }, React.createElement('div', { className: 'w-12 h-12 bg-gradient-to-br from-orange-500 to-orange-600 rounded-xl flex items-center justify-center' }, React.createElement('span', { className: 'text-lg font-bold text-white' }, selectedCliente.nome?.charAt(0)) ), React.createElement('div', null, React.createElement('h2', { className: 'text-lg font-bold text-gray-900' }, selectedCliente.nome), React.createElement('p', { className: 'text-sm text-gray-500' }, `Matrícula: ${selectedCliente.matricula || selectedCliente.cod_aluno}`) ) ), React.createElement('button', { onClick: () => setSelectedCliente(null), className: 'p-2 hover:bg-gray-100 rounded-lg' }, React.createElement(Icon, { name: 'x', className: 'w-5 h-5 text-gray-400' }) ) ), // Abas React.createElement('div', { className: 'px-5 pt-3 border-b flex gap-1 overflow-x-auto' }, abas.map(aba => React.createElement('button', { key: aba.id, onClick: () => trocarAbaDetalhe(aba.id), className: `flex items-center gap-2 px-4 py-2.5 text-sm font-medium rounded-t-lg whitespace-nowrap ${abaDetalhe === aba.id ? 'bg-orange-50 text-orange-600 border-b-2 border-orange-500' : 'text-gray-500 hover:bg-gray-50'}` }, React.createElement(Icon, { name: aba.icon, className: 'w-4 h-4' }), aba.label )) ), // Conteúdo React.createElement('div', { className: 'flex-1 overflow-y-auto p-5' }, // Aba Dados abaDetalhe === 'dados' && React.createElement('div', { className: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, React.createElement('div', { className: 'bg-gray-50 rounded-xl p-4' }, React.createElement('h4', { className: 'text-xs font-semibold text-gray-500 uppercase mb-3' }, 'Dados do Aluno'), [['Nome', selectedCliente.nome], ['CPF', selectedCliente.cpf_aluno], ['Perfil', selectedCliente.perfil], ['Turma', selectedCliente.turma], ['Situação', selectedCliente.situacao_matricula], ['Telefone', selectedCliente.telefone]].map(([l, v], i) => React.createElement('div', { key: i, className: 'flex justify-between py-1.5 border-b border-gray-100 last:border-0' }, React.createElement('span', { className: 'text-sm text-gray-500' }, l), React.createElement('span', { className: 'text-sm font-medium text-gray-900' }, v || '-') ) ) ), React.createElement('div', { className: 'bg-gray-50 rounded-xl p-4' }, React.createElement('h4', { className: 'text-xs font-semibold text-gray-500 uppercase mb-3' }, 'Responsável Financeiro'), [['Nome', selectedCliente.resp_financeiro_nome], ['CPF', selectedCliente.resp_financeiro_cpf], ['Email', selectedCliente.resp_financeiro_email], ['Telefone', selectedCliente.resp_financeiro_telefone]].map(([l, v], i) => React.createElement('div', { key: i, className: 'flex justify-between py-1.5 border-b border-gray-100 last:border-0' }, React.createElement('span', { className: 'text-sm text-gray-500' }, l), React.createElement('span', { className: 'text-sm font-medium text-gray-900 break-all' }, v || '-') ) ) ) ), // Aba Contrato (NOVA!) abaDetalhe === 'contrato' && React.createElement('div', { className: 'space-y-4' }, // Card de status do contrato React.createElement('div', { className: `rounded-xl p-6 ${getContratoStatusStyle(diasParaVencimento(selectedCliente.termino_contrato)).bg} border` }, React.createElement('div', { className: 'flex items-center justify-between' }, React.createElement('div', null, React.createElement('h4', { className: 'text-lg font-bold text-gray-900' }, 'Status do Contrato'), React.createElement('p', { className: `text-sm font-medium ${getContratoStatusStyle(diasParaVencimento(selectedCliente.termino_contrato)).text}` }, getContratoStatusStyle(diasParaVencimento(selectedCliente.termino_contrato)).label ) ), React.createElement('div', { className: 'w-16 h-16 bg-white/50 rounded-xl flex items-center justify-center' }, React.createElement(Icon, { name: diasParaVencimento(selectedCliente.termino_contrato) < 0 ? 'alert-circle' : 'file-check', className: 'w-8 h-8 text-gray-700' }) ) ) ), // Informações do contrato React.createElement('div', { className: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, React.createElement('div', { className: 'bg-gray-50 rounded-xl p-4' }, React.createElement('h4', { className: 'text-xs font-semibold text-gray-500 uppercase mb-3' }, 'Datas do Contrato'), [ ['Início do Contrato', formatDate(selectedCliente.inicio_contrato) || '-'], ['Término do Contrato', formatDate(selectedCliente.termino_contrato) || '-'], ['Dias até Vencimento', diasParaVencimento(selectedCliente.termino_contrato) !== null ? (diasParaVencimento(selectedCliente.termino_contrato) < 0 ? `Vencido há ${Math.abs(diasParaVencimento(selectedCliente.termino_contrato))} dias` : `${diasParaVencimento(selectedCliente.termino_contrato)} dias`) : '-'] ].map(([l, v], i) => React.createElement('div', { key: i, className: 'flex justify-between py-1.5 border-b border-gray-100 last:border-0' }, React.createElement('span', { className: 'text-sm text-gray-500' }, l), React.createElement('span', { className: 'text-sm font-medium text-gray-900' }, v) ) ) ), React.createElement('div', { className: 'bg-gray-50 rounded-xl p-4' }, React.createElement('h4', { className: 'text-xs font-semibold text-gray-500 uppercase mb-3' }, 'Histórico'), [ ['Dias no Supera', selectedCliente.dias_no_supera ? `${selectedCliente.dias_no_supera} dias` : '-'], ['Renovações (estimado)', calcularRenovacoes(selectedCliente.inicio_contrato, selectedCliente.termino_contrato, selectedCliente.dias_no_supera)], ['Plano de Pagamento', selectedCliente.plano_pagamento || '-'] ].map(([l, v], i) => React.createElement('div', { key: i, className: 'flex justify-between py-1.5 border-b border-gray-100 last:border-0' }, React.createElement('span', { className: 'text-sm text-gray-500' }, l), React.createElement('span', { className: 'text-sm font-medium text-gray-900' }, v) ) ) ) ), // Nota explicativa React.createElement('div', { className: 'bg-blue-50 border border-blue-200 rounded-xl p-4 flex items-start gap-3' }, React.createElement(Icon, { name: 'info', className: 'w-5 h-5 text-blue-500 mt-0.5' }), React.createElement('div', null, React.createElement('p', { className: 'text-sm text-blue-700' }, 'O número de renovações é estimado com base no tempo total no Supera dividido pela duração do contrato atual.'), React.createElement('p', { className: 'text-xs text-blue-600 mt-1' }, 'Para histórico detalhado de renovações, consulte o sistema Sophia.') ) ) ), // Aba Boletos abaDetalhe === 'boletos' && ( carregandoBoletos ? React.createElement('div', { className: 'flex justify-center py-12' }, React.createElement('div', { className: 'w-8 h-8 border-4 border-orange-200 border-t-orange-500 rounded-full animate-spin' })) : clienteBoletos.length === 0 ? React.createElement('div', { className: 'text-center py-12 text-gray-500' }, 'Nenhum boleto encontrado') : React.createElement('div', { className: 'space-y-2' }, clienteBoletos.map((b, i) => React.createElement('div', { key: i, className: 'flex items-center gap-3 p-3 bg-gray-50 rounded-lg' }, React.createElement('div', { className: `w-1 h-10 rounded-full ${b.boleto_status === 'PAID' ? 'bg-green-500' : b.boleto_status === 'OVERDUE' ? 'bg-red-500' : 'bg-orange-500'}` }), React.createElement('div', { className: 'flex-1' }, React.createElement('p', { className: 'font-medium' }, getMonthName(b.mes_referencia)), React.createElement('p', { className: 'text-xs text-gray-500' }, `Venc: ${formatDate(b.data_vencimento)}`) ), React.createElement('span', { className: 'font-bold' }, formatMoney(b.valor_cobrado)), React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${getStatusClass(b.boleto_status)}` }, getStatusLabel(b.boleto_status)), b.pdf_local_path && b.boleto_status !== 'PAID' && React.createElement('a', { href: `${API_BASE}/clientes/download-boleto?invoiceId=${b.cora_invoice_id}`, target: '_blank', className: 'px-3 py-1.5 bg-orange-500 text-white rounded-lg text-sm' }, 'PDF') ) )) ), // Aba NFS-e abaDetalhe === 'nfse' && ( carregandoNfse ? React.createElement('div', { className: 'flex justify-center py-12' }, React.createElement('div', { className: 'w-8 h-8 border-4 border-orange-200 border-t-orange-500 rounded-full animate-spin' })) : clienteNfse.length === 0 ? React.createElement('div', { className: 'text-center py-12 text-gray-500' }, 'Nenhuma nota fiscal encontrada') : React.createElement('div', { className: 'space-y-2' }, clienteNfse.map((n, i) => React.createElement('div', { key: i, className: 'flex items-center gap-3 p-3 bg-gray-50 rounded-lg' }, React.createElement('div', { className: 'w-9 h-9 bg-blue-100 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'receipt', className: 'w-4 h-4 text-blue-600' }) ), React.createElement('div', { className: 'flex-1' }, React.createElement('p', { className: 'font-medium' }, `NFS-e #${n.numero_nfse || 'S/N'}`), React.createElement('p', { className: 'text-xs text-gray-500' }, `Emissão: ${formatDate(n.data_emissao)}`) ), React.createElement('span', { className: 'font-bold' }, formatMoney(n.valor_servico)), n.pdf_path && React.createElement('a', { href: `${API_BASE}/clientes/download-nfse?id=${n.id}`, target: '_blank', className: 'px-3 py-1.5 bg-blue-500 text-white rounded-lg text-sm' }, 'PDF') ) )) ), // Aba Envios abaDetalhe === 'envios' && ( carregandoEnvios ? React.createElement('div', { className: 'flex justify-center py-12' }, React.createElement('div', { className: 'w-8 h-8 border-4 border-orange-200 border-t-orange-500 rounded-full animate-spin' })) : clienteEnvios.length === 0 ? React.createElement('div', { className: 'text-center py-12 text-gray-500' }, React.createElement(Icon, { name: 'send', className: 'w-12 h-12 mx-auto text-gray-300 mb-3' }), 'Nenhum envio de alerta encontrado' ) : React.createElement('div', { className: 'space-y-2' }, clienteEnvios.map((env, i) => React.createElement('div', { key: i, className: 'flex items-center gap-3 p-3 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors' }, React.createElement('div', { className: `w-10 h-10 rounded-lg flex items-center justify-center ${env.tipo_envio === 'DIA_01' ? 'bg-blue-100 text-blue-600' : env.tipo_envio === 'VENCIMENTO' ? 'bg-orange-100 text-orange-600' : 'bg-purple-100 text-purple-600'}` }, React.createElement(Icon, { name: env.tipo_envio === 'DIA_01' ? 'calendar' : env.tipo_envio === 'VENCIMENTO' ? 'alert-circle' : 'bell', className: 'w-5 h-5' }) ), React.createElement('div', { className: 'flex-1 min-w-0' }, React.createElement('div', { className: 'flex items-center gap-2' }, React.createElement('p', { className: 'font-medium text-gray-900' }, env.tipo_envio_label || env.tipo_envio), env.pago && React.createElement('span', { className: 'px-2 py-0.5 text-xs rounded-full bg-green-100 text-green-700' }, 'Pago') ), React.createElement('p', { className: 'text-sm text-gray-500' }, `${getMonthName(env.mes_referencia)} • Venc: ${env.vencimento_formatado}`) ), React.createElement('div', { className: 'text-right' }, React.createElement('p', { className: 'font-bold text-gray-900' }, formatMoney(env.valor_cobrado)), React.createElement('p', { className: 'text-xs text-gray-500' }, env.envio_formatado) ) ) )) ) ) ) ), // ========== CONTAS A PAGAR ========== subTab === 'contasapagar' && React.createElement('div', { className: 'space-y-4' }, // Filtros React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border border-gray-100 p-4' }, React.createElement('div', { className: 'flex flex-wrap gap-3 items-end' }, React.createElement('div', { className: 'flex-1 min-w-[150px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Data Início'), React.createElement('input', { type: 'date', value: dataInicioContas, onChange: e => setDataInicioContas(e.target.value), className: 'w-full px-3 py-2 border border-gray-200 rounded-lg text-sm' }) ), React.createElement('div', { className: 'flex-1 min-w-[150px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Data Fim'), React.createElement('input', { type: 'date', value: dataFimContas, onChange: e => setDataFimContas(e.target.value), className: 'w-full px-3 py-2 border border-gray-200 rounded-lg text-sm' }) ), React.createElement('div', null, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Status'), React.createElement('select', { value: filtroStatusContas, onChange: e => setFiltroStatusContas(e.target.value), className: 'px-3 py-2 border border-gray-200 rounded-lg text-sm bg-white' }, React.createElement('option', { value: '' }, 'Todos'), React.createElement('option', { value: 'pago' }, 'Pagos'), React.createElement('option', { value: 'pendente' }, 'Pendentes') ) ), React.createElement('div', null, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Classificação'), React.createElement('select', { value: filtroClassificacao, onChange: e => setFiltroClassificacao(e.target.value), className: 'px-3 py-2 border border-gray-200 rounded-lg text-sm bg-white' }, React.createElement('option', { value: '' }, 'Todas'), classificacoesContas.map(c => React.createElement('option', { key: c, value: c }, c)) ) ), React.createElement('button', { onClick: carregarContasPagar, className: 'px-4 py-2 bg-orange-500 hover:bg-orange-600 text-white rounded-lg text-sm font-medium transition-colors flex items-center gap-2' }, React.createElement(Icon, { name: 'search', className: 'w-4 h-4' }), 'Buscar' ) ), React.createElement('input', { type: 'text', placeholder: 'Filtrar por fornecedor ou descrição...', value: buscaContaPagar, onChange: e => setBuscaContaPagar(e.target.value), className: 'w-full mt-3 px-3 py-2 border border-gray-200 rounded-lg text-sm' }) ), // Totais React.createElement('div', { className: 'grid grid-cols-3 gap-4' }, React.createElement('div', { className: 'bg-blue-50 border border-blue-200 rounded-xl p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-blue-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'calculator', className: 'w-5 h-5 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-sm text-blue-600' }, 'Total Geral'), React.createElement('p', { className: 'text-xl font-bold text-blue-700' }, formatMoney(totaisContas.total)) ) ), React.createElement('div', { className: 'bg-green-50 border border-green-200 rounded-xl p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-green-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'check-circle', className: 'w-5 h-5 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-sm text-green-600' }, 'Total Pago'), React.createElement('p', { className: 'text-xl font-bold text-green-700' }, formatMoney(totaisContas.pagos)) ) ), React.createElement('div', { className: 'bg-amber-50 border border-amber-200 rounded-xl p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-amber-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'clock', className: 'w-5 h-5 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-sm text-amber-600' }, 'Pendente'), React.createElement('p', { className: 'text-xl font-bold text-amber-700' }, formatMoney(totaisContas.pendente)) ) ) ), // Tabela React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border overflow-hidden' }, React.createElement('div', { className: 'p-4 border-b flex items-center justify-between' }, React.createElement('h3', { className: 'font-semibold text-gray-900' }, 'Contas a Pagar'), carregandoContasPagar && React.createElement('div', { className: 'w-5 h-5 border-2 border-orange-200 border-t-orange-500 rounded-full animate-spin' }) ), React.createElement('div', { className: 'overflow-x-auto' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Fornecedor', 'Descrição', 'Classificação', 'Vencimento', 'Valor', 'Status'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, h) )) ), React.createElement('tbody', { className: 'divide-y' }, contasFiltradas.length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 6, className: 'px-4 py-8 text-center text-gray-500' }, carregandoContasPagar ? 'Carregando...' : 'Nenhuma conta encontrada')) : contasFiltradas.slice(0, 100).map((c, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, c.nome || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600 max-w-[200px] truncate' }, c.descricao || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, c.classificacao_desc || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600 whitespace-nowrap' }, formatDate(c.data_vencimento)), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, formatMoney(c.valor)), React.createElement('td', { className: 'px-4 py-3' }, React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${c.status === 'pago' ? 'bg-green-100 text-green-700' : 'bg-amber-100 text-amber-700'}` }, c.status === 'pago' ? 'Pago' : 'Pendente')) ) ) ) ) ) ) ), // ========== VENDAS ========== subTab === 'vendas' && React.createElement('div', { className: 'space-y-4' }, // Filtros React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border border-gray-100 p-4' }, React.createElement('div', { className: 'flex flex-wrap gap-3 items-end' }, React.createElement('div', { className: 'flex-1 min-w-[150px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Data Início'), React.createElement('input', { type: 'date', value: dataInicioVendas, onChange: e => setDataInicioVendas(e.target.value), className: 'w-full px-3 py-2 border border-gray-200 rounded-lg text-sm' }) ), React.createElement('div', { className: 'flex-1 min-w-[150px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Data Fim'), React.createElement('input', { type: 'date', value: dataFimVendas, onChange: e => setDataFimVendas(e.target.value), className: 'w-full px-3 py-2 border border-gray-200 rounded-lg text-sm' }) ), React.createElement('div', null, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Produto'), React.createElement('select', { value: filtroProduto, onChange: e => setFiltroProduto(e.target.value), className: 'px-3 py-2 border border-gray-200 rounded-lg text-sm bg-white' }, React.createElement('option', { value: '' }, 'Todos'), produtosUnicos.map(p => React.createElement('option', { key: p, value: p }, p)) ) ), React.createElement('div', null, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Vendedor'), React.createElement('select', { value: filtroVendedor, onChange: e => setFiltroVendedor(e.target.value), className: 'px-3 py-2 border border-gray-200 rounded-lg text-sm bg-white' }, React.createElement('option', { value: '' }, 'Todos'), vendedoresUnicos.map(v => React.createElement('option', { key: v, value: v }, v)) ) ), React.createElement('button', { onClick: carregarVendas, className: 'px-4 py-2 bg-orange-500 hover:bg-orange-600 text-white rounded-lg text-sm font-medium transition-colors flex items-center gap-2' }, React.createElement(Icon, { name: 'search', className: 'w-4 h-4' }), 'Buscar' ) ), React.createElement('input', { type: 'text', placeholder: 'Filtrar por cliente ou produto...', value: buscaVenda, onChange: e => setBuscaVenda(e.target.value), className: 'w-full mt-3 px-3 py-2 border border-gray-200 rounded-lg text-sm' }) ), // Totais React.createElement('div', { className: 'grid grid-cols-3 gap-4' }, React.createElement('div', { className: 'bg-blue-50 border border-blue-200 rounded-xl p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-blue-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'shopping-cart', className: 'w-5 h-5 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-sm text-blue-600' }, 'Total Bruto'), React.createElement('p', { className: 'text-xl font-bold text-blue-700' }, formatMoney(totaisVendas.totalBruto)) ) ), React.createElement('div', { className: 'bg-red-50 border border-red-200 rounded-xl p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-red-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'percent', className: 'w-5 h-5 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-sm text-red-600' }, 'Total Descontos'), React.createElement('p', { className: 'text-xl font-bold text-red-700' }, formatMoney(totaisVendas.totalDesconto)) ) ), React.createElement('div', { className: 'bg-green-50 border border-green-200 rounded-xl p-4 flex items-center gap-3' }, React.createElement('div', { className: 'w-10 h-10 bg-green-500 rounded-lg flex items-center justify-center' }, React.createElement(Icon, { name: 'dollar-sign', className: 'w-5 h-5 text-white' }) ), React.createElement('div', null, React.createElement('p', { className: 'text-sm text-green-600' }, 'Total Entrada'), React.createElement('p', { className: 'text-xl font-bold text-green-700' }, formatMoney(totaisVendas.totalEntrada)) ) ) ), // Tabela React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border overflow-hidden' }, React.createElement('div', { className: 'p-4 border-b flex items-center justify-between' }, React.createElement('h3', { className: 'font-semibold text-gray-900' }, `Vendas (${vendasFiltradas.length})`), carregandoVendas && React.createElement('div', { className: 'w-5 h-5 border-2 border-orange-200 border-t-orange-500 rounded-full animate-spin' }) ), React.createElement('div', { className: 'overflow-x-auto' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Data', 'Cliente', 'Produto', 'Vendedor', 'Valor Bruto', 'Desconto', 'Entrada'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, h) )) ), React.createElement('tbody', { className: 'divide-y' }, vendasFiltradas.length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 7, className: 'px-4 py-8 text-center text-gray-500' }, carregandoVendas ? 'Carregando...' : 'Nenhuma venda encontrada')) : vendasFiltradas.slice(0, 100).map((v, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600 whitespace-nowrap' }, formatDate(v.data_venda)), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, v.nome || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, v.produto || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, v.vendedor || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, formatMoney(v.valor_bruto)), React.createElement('td', { className: 'px-4 py-3 text-sm text-red-600' }, formatMoney(v.valor_desconto)), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium text-green-600' }, formatMoney(v.valor_entrada)) ) ) ) ) ) ) ), // ========== ESTOQUE ========== subTab === 'estoque' && React.createElement('div', { className: 'space-y-4' }, // Sub-abas React.createElement('div', { className: 'flex gap-2 bg-white rounded-xl p-2 shadow-sm border' }, [ { id: 'inventario', label: 'Inventário', icon: 'package' }, { id: 'entregas', label: 'Entregas Pendentes', icon: 'truck' }, { id: 'adquirir', label: 'A Adquirir', icon: 'shopping-bag' }, { id: 'kitsEntregues', label: 'Kits Entregues', icon: 'check-square' } ].map(tab => React.createElement('button', { key: tab.id, onClick: () => setAbaEstoque(tab.id), className: `flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-all ${abaEstoque === tab.id ? 'bg-orange-100 text-orange-700' : 'text-gray-600 hover:bg-gray-100'}` }, React.createElement(Icon, { name: tab.icon, className: 'w-4 h-4' }), tab.label )) ), // Busca React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4 flex gap-3' }, React.createElement('div', { className: 'flex-1 relative' }, React.createElement(Icon, { name: 'search', className: 'absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400' }), React.createElement('input', { type: 'text', placeholder: 'Buscar...', value: buscaEstoque, onChange: e => setBuscaEstoque(e.target.value), className: 'w-full pl-9 pr-3 py-2 border rounded-lg text-sm' }) ), React.createElement('button', { onClick: carregarEstoque, className: 'px-4 py-2 bg-orange-500 hover:bg-orange-600 text-white rounded-lg text-sm font-medium transition-colors flex items-center gap-2' }, React.createElement(Icon, { name: 'refresh-cw', className: 'w-4 h-4' }), 'Atualizar' ) ), // Tabela React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border overflow-hidden' }, React.createElement('div', { className: 'p-4 border-b flex items-center justify-between' }, React.createElement('h3', { className: 'font-semibold text-gray-900' }, abaEstoque === 'inventario' ? 'Inventário' : abaEstoque === 'entregas' ? 'Entregas Pendentes' : abaEstoque === 'adquirir' ? 'Materiais a Adquirir' : 'Kits Entregues' ), carregandoEstoque && React.createElement('div', { className: 'w-5 h-5 border-2 border-orange-200 border-t-orange-500 rounded-full animate-spin' }) ), React.createElement('div', { className: 'overflow-x-auto' }, abaEstoque === 'inventario' && React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Código', 'Descrição', 'Grupo', 'Estoque Atual', 'Est. Mínimo', 'Custo Médio', 'Preço Venda', 'Valor Total'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, h) )) ), React.createElement('tbody', { className: 'divide-y' }, estoque.inventario.filter(i => !buscaEstoque || i.descricao?.toLowerCase().includes(buscaEstoque.toLowerCase())).length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 8, className: 'px-4 py-8 text-center text-gray-500' }, carregandoEstoque ? 'Carregando...' : 'Nenhum item encontrado')) : estoque.inventario.filter(i => !buscaEstoque || i.descricao?.toLowerCase().includes(buscaEstoque.toLowerCase())).slice(0, 100).map((item, i) => { const baixoEstoque = item.estoque_atual <= item.estoque_minimo; return React.createElement('tr', { key: i, className: `hover:bg-gray-50 ${baixoEstoque ? 'bg-red-50' : ''}` }, React.createElement('td', { className: 'px-4 py-3 text-sm font-mono' }, item.cod_kit || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, item.descricao || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, item.grupo || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm font-bold', style: { color: baixoEstoque ? '#dc2626' : '#059669' } }, item.estoque_atual || 0), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, item.estoque_minimo || 0), React.createElement('td', { className: 'px-4 py-3 text-sm' }, formatMoney(item.custo_medio)), React.createElement('td', { className: 'px-4 py-3 text-sm' }, formatMoney(item.preco_venda)), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, formatMoney(item.valor_total)) ); }) ) ), abaEstoque === 'entregas' && React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Item', 'Descrição', 'Aluno', 'Telefone', 'Data Pendência', 'Qtd'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, h) )) ), React.createElement('tbody', { className: 'divide-y' }, estoque.entregas.filter(e => !buscaEstoque || e.nome_aluno?.toLowerCase().includes(buscaEstoque.toLowerCase())).length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 6, className: 'px-4 py-8 text-center text-gray-500' }, carregandoEstoque ? 'Carregando...' : 'Nenhuma entrega pendente')) : estoque.entregas.filter(e => !buscaEstoque || e.nome_aluno?.toLowerCase().includes(buscaEstoque.toLowerCase())).map((e, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-4 py-3 text-sm font-mono' }, e.item || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, e.descricao || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm' }, e.nome_aluno || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, e.telefone || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm' }, formatDate(e.data_pendencia)), React.createElement('td', { className: 'px-4 py-3 text-sm font-bold' }, e.quantidade || 1) ) ) ) ), abaEstoque === 'adquirir' && React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Código', 'Descrição', 'Quantidade Necessária', 'Estoque Atual', 'Estoque Mínimo'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, h) )) ), React.createElement('tbody', { className: 'divide-y' }, estoque.adquirir.filter(a => !buscaEstoque || a.descricao?.toLowerCase().includes(buscaEstoque.toLowerCase())).length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 5, className: 'px-4 py-8 text-center text-gray-500' }, carregandoEstoque ? 'Carregando...' : 'Nenhum material a adquirir')) : estoque.adquirir.filter(a => !buscaEstoque || a.descricao?.toLowerCase().includes(buscaEstoque.toLowerCase())).map((a, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-4 py-3 text-sm font-mono' }, a.cod_kit || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, a.descricao || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm font-bold text-red-600' }, a.quantidade_necessaria || 0), React.createElement('td', { className: 'px-4 py-3 text-sm' }, a.estoque_atual || 0), React.createElement('td', { className: 'px-4 py-3 text-sm' }, a.estoque_minimo || 0) ) ) ) ), abaEstoque === 'kitsEntregues' && React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Código', 'Descrição', 'Aluno', 'Data Entrega', 'Qtd'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, h) )) ), React.createElement('tbody', { className: 'divide-y' }, estoque.kitsEntregues.filter(k => !buscaEstoque || k.nome_aluno?.toLowerCase().includes(buscaEstoque.toLowerCase())).length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 5, className: 'px-4 py-8 text-center text-gray-500' }, carregandoEstoque ? 'Carregando...' : 'Nenhum kit entregue')) : estoque.kitsEntregues.filter(k => !buscaEstoque || k.nome_aluno?.toLowerCase().includes(buscaEstoque.toLowerCase())).map((k, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-4 py-3 text-sm font-mono' }, k.cod_kit || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, k.descricao || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm' }, k.nome_aluno || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm' }, formatDate(k.data_entrega)), React.createElement('td', { className: 'px-4 py-3 text-sm font-bold' }, k.quantidade || 1) ) ) ) ) ) ) ), // ========== CARTÕES (MAQUININHA) ========== subTab === 'cartoes' && React.createElement('div', { className: 'space-y-4' }, // Sub-abas internas React.createElement('div', { className: 'flex gap-2 bg-white rounded-xl p-2 shadow-sm border' }, [ { id: 'resumo', label: 'Resumo', icon: 'chart-bar' }, { id: 'vendas', label: 'Vendas', icon: 'credit-card' }, { id: 'areceber', label: 'A Receber', icon: 'calendar' } ].map(tab => React.createElement('button', { key: tab.id, onClick: () => { setAbaCartoes(tab.id); if (tab.id === 'vendas' && cartoesVendas.length === 0) carregarCartoesVendas(); if (tab.id === 'areceber' && cartoesAReceber.length === 0) carregarCartoesAReceber(); }, className: `flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-all ${abaCartoes === tab.id ? 'bg-orange-100 text-orange-700' : 'text-gray-600 hover:bg-gray-100'}` }, React.createElement(Icon, { name: tab.icon, className: 'w-4 h-4' }), tab.label )) ), // ===== RESUMO CARTÕES ===== abaCartoes === 'resumo' && React.createElement('div', { className: 'space-y-6' }, carregandoCartoes ? React.createElement('div', { className: 'flex items-center justify-center py-12' }, React.createElement('div', { className: 'w-8 h-8 border-4 border-orange-200 border-t-orange-500 rounded-full animate-spin' }) ) : React.createElement(React.Fragment, null, // Cards de Resumo React.createElement('div', { className: 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4' }, React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-5' }, React.createElement('div', { className: 'flex items-center justify-between' }, React.createElement('div', null, React.createElement('p', { className: 'text-sm text-gray-500' }, 'Vendas do Mês'), React.createElement('p', { className: 'text-2xl font-bold text-gray-900' }, formatMoney(cartoesResumo?.mes_atual?.valor_bruto || 0) ), React.createElement('p', { className: 'text-xs text-gray-400 mt-1' }, `${cartoesResumo?.mes_atual?.quantidade || 0} transações` ) ), React.createElement('div', { className: 'w-12 h-12 bg-blue-100 rounded-xl flex items-center justify-center' }, React.createElement(Icon, { name: 'credit-card', className: 'w-6 h-6 text-blue-600' }) ) ) ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-5' }, React.createElement('div', { className: 'flex items-center justify-between' }, React.createElement('div', null, React.createElement('p', { className: 'text-sm text-gray-500' }, 'Líquido do Mês'), React.createElement('p', { className: 'text-2xl font-bold text-green-600' }, formatMoney(cartoesResumo?.mes_atual?.valor_liquido || 0) ), React.createElement('p', { className: 'text-xs text-gray-400 mt-1' }, `Taxa: ${((1 - (cartoesResumo?.mes_atual?.valor_liquido || 0) / (cartoesResumo?.mes_atual?.valor_bruto || 1)) * 100).toFixed(2)}%` ) ), React.createElement('div', { className: 'w-12 h-12 bg-green-100 rounded-xl flex items-center justify-center' }, React.createElement(Icon, { name: 'trending-up', className: 'w-6 h-6 text-green-600' }) ) ) ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-5' }, React.createElement('div', { className: 'flex items-center justify-between' }, React.createElement('div', null, React.createElement('p', { className: 'text-sm text-gray-500' }, 'A Receber (30 dias)'), React.createElement('p', { className: 'text-2xl font-bold text-orange-600' }, formatMoney(cartoesResumo?.a_receber?.valor || 0) ), React.createElement('p', { className: 'text-xs text-gray-400 mt-1' }, `${cartoesResumo?.a_receber?.quantidade || 0} parcelas` ) ), React.createElement('div', { className: 'w-12 h-12 bg-orange-100 rounded-xl flex items-center justify-center' }, React.createElement(Icon, { name: 'clock', className: 'w-6 h-6 text-orange-600' }) ) ) ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-5' }, React.createElement('div', { className: 'flex items-center justify-between' }, React.createElement('div', null, React.createElement('p', { className: 'text-sm text-gray-500' }, 'Ticket Médio'), React.createElement('p', { className: 'text-2xl font-bold text-purple-600' }, formatMoney(cartoesResumo?.mes_atual?.ticket_medio || 0) ), React.createElement('p', { className: 'text-xs text-gray-400 mt-1' }, 'Valor médio por venda') ), React.createElement('div', { className: 'w-12 h-12 bg-purple-100 rounded-xl flex items-center justify-center' }, React.createElement(Icon, { name: 'receipt', className: 'w-6 h-6 text-purple-600' }) ) ) ) ), // Gráficos React.createElement('div', { className: 'grid grid-cols-1 lg:grid-cols-2 gap-6' }, React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-5' }, React.createElement('h3', { className: 'font-semibold text-gray-900 mb-4' }, 'Por Bandeira'), React.createElement('div', { className: 'space-y-3' }, (cartoesResumo?.por_bandeira || []).map((item, i) => { const percent = cartoesResumo?.mes_atual?.valor_bruto > 0 ? (item.valor_bruto / cartoesResumo.mes_atual.valor_bruto * 100) : 0; return React.createElement('div', { key: item.bandeira, className: 'space-y-1' }, React.createElement('div', { className: 'flex justify-between text-sm' }, React.createElement('span', { className: 'font-medium' }, item.bandeira), React.createElement('span', { className: 'text-gray-600' }, `${formatMoney(item.valor_bruto)} (${item.quantidade})` ) ), React.createElement('div', { className: 'w-full bg-gray-100 rounded-full h-2' }, React.createElement('div', { className: 'h-2 rounded-full transition-all duration-500', style: { width: `${percent}%`, backgroundColor: CORES_BANDEIRA[item.bandeira] || CORES_GRAFICO[i % CORES_GRAFICO.length] } }) ) ); }) ) ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-5' }, React.createElement('h3', { className: 'font-semibold text-gray-900 mb-4' }, 'Por Forma de Pagamento'), React.createElement('div', { className: 'space-y-3' }, (cartoesResumo?.por_forma_pagamento || []).map((item, i) => { const percent = cartoesResumo?.mes_atual?.valor_bruto > 0 ? (item.valor_bruto / cartoesResumo.mes_atual.valor_bruto * 100) : 0; return React.createElement('div', { key: item.forma_pagamento, className: 'space-y-1' }, React.createElement('div', { className: 'flex justify-between text-sm' }, React.createElement('span', { className: 'font-medium' }, item.forma_pagamento), React.createElement('span', { className: 'text-gray-600' }, `${formatMoney(item.valor_bruto)} (${item.quantidade})` ) ), React.createElement('div', { className: 'w-full bg-gray-100 rounded-full h-2' }, React.createElement('div', { className: 'h-2 rounded-full transition-all duration-500', style: { width: `${percent}%`, backgroundColor: CORES_GRAFICO[i % CORES_GRAFICO.length] } }) ) ); }) ) ) ), // Últimas Vendas React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border overflow-hidden' }, React.createElement('div', { className: 'p-4 border-b' }, React.createElement('h3', { className: 'font-semibold text-gray-900' }, 'Últimas Vendas') ), React.createElement('div', { className: 'overflow-x-auto' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Data', 'Bandeira', 'Forma', 'Cartão', 'Bruto', 'Líquido', 'Status'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, h) ) ) ), React.createElement('tbody', { className: 'divide-y' }, (cartoesResumo?.ultimas_vendas || []).slice(0, 10).map((v, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-4 py-3 text-sm' }, formatDate(v.data_transacao)), React.createElement('td', { className: 'px-4 py-3 text-sm' }, React.createElement('span', { className: 'px-2 py-1 rounded-full text-xs font-medium', style: { backgroundColor: `${CORES_BANDEIRA[v.bandeira] || '#6b7280'}20`, color: CORES_BANDEIRA[v.bandeira] || '#6b7280' } }, v.bandeira) ), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, v.forma_pagamento), React.createElement('td', { className: 'px-4 py-3 text-sm font-mono text-gray-500' }, v.numero_cartao), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, formatMoney(v.valor_parcela_bruto)), React.createElement('td', { className: 'px-4 py-3 text-sm font-medium text-green-600' }, formatMoney(v.valor_parcela_liquido)), React.createElement('td', { className: 'px-4 py-3 text-sm' }, React.createElement('span', { className: `px-2 py-1 rounded-full text-xs font-medium ${v.status?.includes('Processada') ? 'bg-green-100 text-green-700' : 'bg-yellow-100 text-yellow-700'}` }, v.status || '-') ) ) ) ) ) ) ) ) ), // ===== VENDAS CARTÕES ===== abaCartoes === 'vendas' && React.createElement('div', { className: 'space-y-4' }, // Filtros React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('div', { className: 'flex flex-wrap gap-3 items-end' }, React.createElement('div', { className: 'flex-1 min-w-[140px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Data Início'), React.createElement('input', { type: 'date', value: dataInicioCartoes, onChange: e => setDataInicioCartoes(e.target.value), className: 'w-full px-3 py-2 border rounded-lg text-sm' }) ), React.createElement('div', { className: 'flex-1 min-w-[140px]' }, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Data Fim'), React.createElement('input', { type: 'date', value: dataFimCartoes, onChange: e => setDataFimCartoes(e.target.value), className: 'w-full px-3 py-2 border rounded-lg text-sm' }) ), React.createElement('div', null, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Bandeira'), React.createElement('select', { value: filtroBandeiraCartoes, onChange: e => setFiltroBandeiraCartoes(e.target.value), className: 'px-3 py-2 border rounded-lg text-sm bg-white' }, React.createElement('option', { value: 'todos' }, 'Todas'), ['Mastercard', 'Visa', 'Elo', 'Hipercard'].map(b => React.createElement('option', { key: b, value: b }, b)) ) ), React.createElement('div', null, React.createElement('label', { className: 'block text-xs font-medium text-gray-500 mb-1' }, 'Forma'), React.createElement('select', { value: filtroFormaPagCartoes, onChange: e => setFiltroFormaPagCartoes(e.target.value), className: 'px-3 py-2 border rounded-lg text-sm bg-white' }, React.createElement('option', { value: 'todos' }, 'Todas'), ['Débito', 'Crédito'].map(f => React.createElement('option', { key: f, value: f }, f)) ) ), React.createElement('button', { onClick: carregarCartoesVendas, className: 'px-4 py-2 bg-orange-500 hover:bg-orange-600 text-white rounded-lg text-sm font-medium transition-colors flex items-center gap-2' }, carregandoCartoesVendas ? React.createElement('div', { className: 'w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin' }) : React.createElement(Icon, { name: 'search', className: 'w-4 h-4' }), 'Buscar' ) ), React.createElement('input', { type: 'text', placeholder: 'Buscar por transação ou cartão...', value: buscaCartoes, onChange: e => setBuscaCartoes(e.target.value), className: 'w-full mt-3 px-3 py-2 border rounded-lg text-sm' }) ), // Totais React.createElement('div', { className: 'grid grid-cols-2 md:grid-cols-4 gap-4' }, React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Transações'), React.createElement('p', { className: 'text-xl font-bold text-gray-900' }, cartoesVendas.filter(v => !buscaCartoes || v.numero_transacao?.includes(buscaCartoes) || v.numero_cartao?.includes(buscaCartoes)).length) ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Valor Bruto'), React.createElement('p', { className: 'text-xl font-bold text-gray-900' }, formatMoney(cartoesVendas.filter(v => !buscaCartoes || v.numero_transacao?.includes(buscaCartoes) || v.numero_cartao?.includes(buscaCartoes)).reduce((s, v) => s + parseFloat(v.valor_parcela_bruto || 0), 0))) ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Valor Líquido'), React.createElement('p', { className: 'text-xl font-bold text-green-600' }, formatMoney(cartoesVendas.filter(v => !buscaCartoes || v.numero_transacao?.includes(buscaCartoes) || v.numero_cartao?.includes(buscaCartoes)).reduce((s, v) => s + parseFloat(v.valor_parcela_liquido || 0), 0))) ), React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border p-4' }, React.createElement('p', { className: 'text-xs text-gray-500' }, 'Taxas'), React.createElement('p', { className: 'text-xl font-bold text-red-600' }, formatMoney(cartoesVendas.filter(v => !buscaCartoes || v.numero_transacao?.includes(buscaCartoes) || v.numero_cartao?.includes(buscaCartoes)).reduce((s, v) => s + parseFloat(v.desconto_parcela || 0), 0))) ) ), // Tabela React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border overflow-hidden' }, React.createElement('div', { className: 'p-4 border-b flex items-center justify-between' }, React.createElement('h3', { className: 'font-semibold text-gray-900' }, `Vendas (${cartoesVendas.filter(v => !buscaCartoes || v.numero_transacao?.includes(buscaCartoes) || v.numero_cartao?.includes(buscaCartoes)).length})`), carregandoCartoesVendas && React.createElement('div', { className: 'w-5 h-5 border-2 border-orange-200 border-t-orange-500 rounded-full animate-spin' }) ), React.createElement('div', { className: 'overflow-x-auto' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Data', 'Transação', 'Bandeira', 'Forma', 'Parcela', 'Cartão', 'Bruto', 'Taxa', 'Líquido', 'Liquidação'].map(h => React.createElement('th', { key: h, className: 'text-left px-3 py-3 text-xs font-semibold text-gray-500 uppercase whitespace-nowrap' }, h) ) ) ), React.createElement('tbody', { className: 'divide-y' }, cartoesVendas.filter(v => !buscaCartoes || v.numero_transacao?.includes(buscaCartoes) || v.numero_cartao?.includes(buscaCartoes)).length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 10, className: 'px-4 py-8 text-center text-gray-500' }, carregandoCartoesVendas ? 'Carregando...' : 'Nenhuma venda encontrada')) : cartoesVendas.filter(v => !buscaCartoes || v.numero_transacao?.includes(buscaCartoes) || v.numero_cartao?.includes(buscaCartoes)).slice(0, 100).map((v, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-3 py-2 text-sm whitespace-nowrap' }, formatDate(v.data_transacao)), React.createElement('td', { className: 'px-3 py-2 text-xs font-mono' }, v.numero_transacao), React.createElement('td', { className: 'px-3 py-2 text-sm' }, React.createElement('span', { className: 'px-2 py-0.5 rounded text-xs font-medium', style: { backgroundColor: `${CORES_BANDEIRA[v.bandeira] || '#6b7280'}15`, color: CORES_BANDEIRA[v.bandeira] || '#6b7280' } }, v.bandeira) ), React.createElement('td', { className: 'px-3 py-2 text-sm text-gray-600' }, v.forma_pagamento), React.createElement('td', { className: 'px-3 py-2 text-sm text-center' }, `${v.parcela}/${v.total_parcelas}`), React.createElement('td', { className: 'px-3 py-2 text-xs font-mono text-gray-500' }, v.numero_cartao), React.createElement('td', { className: 'px-3 py-2 text-sm font-medium text-right' }, formatMoney(v.valor_parcela_bruto)), React.createElement('td', { className: 'px-3 py-2 text-sm text-red-600 text-right' }, formatMoney(v.desconto_parcela)), React.createElement('td', { className: 'px-3 py-2 text-sm font-medium text-green-600 text-right' }, formatMoney(v.valor_parcela_liquido)), React.createElement('td', { className: 'px-3 py-2 text-sm text-gray-600' }, formatDate(v.data_liquidacao)) ) ) ) ) ) ) ), // ===== A RECEBER ===== abaCartoes === 'areceber' && React.createElement('div', { className: 'space-y-4' }, // Card Total React.createElement('div', { className: 'bg-gradient-to-r from-orange-500 to-orange-600 rounded-xl shadow-lg p-6 text-white' }, React.createElement('div', { className: 'flex items-center justify-between' }, React.createElement('div', null, React.createElement('p', { className: 'text-orange-100 text-sm' }, 'Total a Receber (Próx. 30 dias)'), React.createElement('p', { className: 'text-3xl font-bold mt-1' }, formatMoney(cartoesAReceber.reduce((s, r) => s + parseFloat(r.valor_liquido || 0), 0))), React.createElement('p', { className: 'text-orange-200 text-sm mt-2' }, `${cartoesAReceber.reduce((s, r) => s + parseInt(r.quantidade || 0), 0)} parcelas`) ), React.createElement('div', { className: 'w-16 h-16 bg-white/20 rounded-2xl flex items-center justify-center' }, React.createElement(Icon, { name: 'calendar', className: 'w-8 h-8 text-white' }) ) ) ), // Botão atualizar React.createElement('div', { className: 'flex justify-end' }, React.createElement('button', { onClick: carregarCartoesAReceber, className: 'px-4 py-2 bg-orange-500 hover:bg-orange-600 text-white rounded-lg text-sm font-medium transition-colors flex items-center gap-2' }, carregandoCartoesReceber ? React.createElement('div', { className: 'w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin' }) : React.createElement(Icon, { name: 'refresh-cw', className: 'w-4 h-4' }), 'Atualizar' ) ), // Tabela React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border overflow-hidden' }, React.createElement('div', { className: 'p-4 border-b' }, React.createElement('h3', { className: 'font-semibold text-gray-900' }, 'Previsão de Recebimentos') ), React.createElement('div', { className: 'overflow-x-auto' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Data Liquidação', 'Bandeira', 'Forma', 'Transações', 'Valor Líquido'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, h) ) ) ), React.createElement('tbody', { className: 'divide-y' }, cartoesAReceber.length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 5, className: 'px-4 py-8 text-center text-gray-500' }, carregandoCartoesReceber ? 'Carregando...' : 'Nenhum recebimento previsto')) : cartoesAReceber.map((r, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-4 py-3 text-sm font-medium' }, formatDate(r.data_liquidacao)), React.createElement('td', { className: 'px-4 py-3 text-sm' }, React.createElement('span', { className: 'px-2 py-1 rounded text-xs font-medium', style: { backgroundColor: `${CORES_BANDEIRA[r.bandeira] || '#6b7280'}15`, color: CORES_BANDEIRA[r.bandeira] || '#6b7280' } }, r.bandeira) ), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, r.forma_pagamento), React.createElement('td', { className: 'px-4 py-3 text-sm text-center' }, r.quantidade), React.createElement('td', { className: 'px-4 py-3 text-sm font-bold text-green-600' }, formatMoney(r.valor_liquido)) ) ) ) ) ) ) ) ) ); }; }; })();