"use client"; import * as React from "react"; import { DataGrid, GridToolbar } from "@mui/x-data-grid"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from "@/components/ui/dialog"; import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, } from "@/components/ui/select"; import { Download, Filter, X } from "lucide-react"; import * as XLSX from "xlsx"; interface AnaliticoItem { codigo_grupo: string; codigo_subgrupo: string; codigo_fornecedor: string; nome_fornecedor: string; id: number; codfilial: string; recnum: number; data_competencia: string; data_vencimento: string; data_pagamento: string; data_caixa: string; codigo_conta: string; conta: string; codigo_centrocusto: string; valor: number; historico: string; historico2: string; created_at: string; updated_at: string; // Campos adicionais do Oracle entidade?: string; tipo_parceiro?: string; valor_previsto?: number; valor_confirmado?: number; valor_pago?: number; numero_lancamento?: number; ano_mes_comp?: string; codgrupo?: string; } interface AnaliticoProps { filtros: { dataInicio: string; dataFim: string; centroCusto?: string; codigoGrupo?: string; codigoSubgrupo?: string; codigoConta?: string; linhaSelecionada?: string; }; } export default function AnaliticoComponent({ filtros }: AnaliticoProps) { const [data, setData] = React.useState([]); const [loading, setLoading] = React.useState(false); const [globalFilter, setGlobalFilter] = React.useState(""); const [open, setOpen] = React.useState(false); const [conditions, setConditions] = React.useState([ { column: "", operator: "contains", value: "" }, ]); // Estado para armazenar filtros externos (vindos do teste.tsx) const [filtrosExternos, setFiltrosExternos] = React.useState(filtros); // Atualizar filtros externos quando os props mudarem React.useEffect(() => { console.log('🔄 Analítico - useEffect dos filtros chamado'); console.log('📋 Filtros recebidos via props:', filtros); setFiltrosExternos(filtros); }, [filtros]); const fetchData = React.useCallback(async () => { console.log('🔄 Analítico - fetchData chamado'); console.log('📋 Filtros externos recebidos:', filtrosExternos); if (!filtrosExternos.dataInicio || !filtrosExternos.dataFim) { console.log('⚠️ Sem dataInicio ou dataFim, limpando dados'); setData([]); return; } setLoading(true); try { const params = new URLSearchParams(); if (filtrosExternos.dataInicio) { params.append('dataInicio', filtrosExternos.dataInicio); } if (filtrosExternos.dataFim) { params.append('dataFim', filtrosExternos.dataFim); } if (filtrosExternos.centroCusto) { params.append('centroCusto', filtrosExternos.centroCusto); } if (filtrosExternos.codigoGrupo) { params.append('codigoGrupo', filtrosExternos.codigoGrupo); } if (filtrosExternos.codigoConta) { params.append('codigoConta', filtrosExternos.codigoConta); } const url = `/api/analitico-oracle?${params.toString()}`; console.log('🌐 Fazendo requisição para:', url); const response = await fetch(url); if (response.ok) { const result = await response.json(); console.log('✅ Resposta da API recebida:', result.length, 'registros'); console.log('📝 Primeiros 2 registros:', result.slice(0, 2)); console.log('🔍 Verificando campos específicos:', { data_vencimento: result[0]?.data_vencimento, data_caixa: result[0]?.data_caixa, entidade: result[0]?.entidade, valor: result[0]?.valor, tipo_valor: typeof result[0]?.valor }); setData(result as AnaliticoItem[]); } else { console.error("❌ Erro ao buscar dados:", await response.text()); } } catch (error) { console.error("❌ Erro ao buscar dados:", error); } finally { setLoading(false); } }, [filtrosExternos]); React.useEffect(() => { fetchData(); }, [fetchData]); // Definir colunas do DataGridPro const columns = React.useMemo(() => [ { field: "data_vencimento", headerName: "Data de Vencimento", width: 150, sortable: true, resizable: true, renderCell: (params: any) => { if (!params.value) return "-"; try { return new Date(params.value).toLocaleDateString("pt-BR"); } catch (error) { return params.value; } }, }, { field: "data_caixa", headerName: "Data de Caixa", width: 130, sortable: true, resizable: true, renderCell: (params: any) => { if (!params.value) return "-"; try { return new Date(params.value).toLocaleDateString("pt-BR"); } catch (error) { return params.value; } }, }, { field: "entidade", headerName: "Entidade", width: 100, sortable: true, resizable: true, renderCell: (params: any) => params.value || "-", }, { field: "codigo_fornecedor", headerName: "Cód. Fornecedor", width: 140, sortable: true, resizable: true, }, { field: "nome_fornecedor", headerName: "Nome do Fornecedor", flex: 1, minWidth: 200, sortable: true, resizable: true, }, { field: "codigo_centrocusto", headerName: "Centro de Custo", width: 130, sortable: true, resizable: true, }, { field: "codigo_conta", headerName: "Código da Conta", width: 150, sortable: true, resizable: true, }, { field: "conta", headerName: "Nome da Conta", flex: 1, minWidth: 180, sortable: true, resizable: true, }, { field: "valor", headerName: "Valor Realizado", type: "number" as const, width: 140, sortable: true, resizable: true, renderCell: (params: any) => { const value = params.value; if (value === null || value === undefined || value === "") return "-"; const numValue = typeof value === "string" ? parseFloat(value) : Number(value); if (isNaN(numValue)) return "-"; const formatted = new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL", }).format(numValue); return ( {formatted} ); }, }, { field: "valor_previsto", headerName: "Valor Previsto", type: "number" as const, width: 130, sortable: true, resizable: true, renderCell: (params: any) => { const value = params.value; if (value === null || value === undefined || value === "" || value === 0) return "-"; const numValue = typeof value === "string" ? parseFloat(value) : Number(value); if (isNaN(numValue)) return "-"; const formatted = new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL", }).format(numValue); return ( {formatted} ); }, }, { field: "valor_confirmado", headerName: "Valor Confirmado", type: "number" as const, width: 140, sortable: true, resizable: true, renderCell: (params: any) => { const value = params.value; if (value === null || value === undefined || value === "" || value === 0) return "-"; const numValue = typeof value === "string" ? parseFloat(value) : Number(value); if (isNaN(numValue)) return "-"; const formatted = new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL", }).format(numValue); return ( {formatted} ); }, }, { field: "valor_pago", headerName: "Valor Pago", type: "number" as const, width: 130, sortable: true, resizable: true, renderCell: (params: any) => { const value = params.value; if (value === null || value === undefined || value === "" || value === 0) return "-"; const numValue = typeof value === "string" ? parseFloat(value) : Number(value); if (isNaN(numValue)) return "-"; const formatted = new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL", }).format(numValue); return ( {formatted} ); }, }, { field: "historico", headerName: "Histórico", flex: 1, minWidth: 250, sortable: true, resizable: true, }, { field: "historico2", headerName: "Histórico 2", flex: 1, minWidth: 300, sortable: true, resizable: true, }, { field: "numero_lancamento", headerName: "Número do Lançamento", width: 80, sortable: true, resizable: true, renderCell: (params: any) => params.value || "-", }, ] as any, []); // Calcular totais das colunas de valores const columnTotals = React.useMemo(() => { if (!data || data.length === 0) { return { valorRealizado: 0, valorPrevisto: 0, valorConfirmado: 0, valorPago: 0, }; } const valorRealizado = data.reduce((sum, item) => { const valor = typeof item.valor === "string" ? parseFloat(item.valor) : item.valor; return sum + (isNaN(valor) ? 0 : valor); }, 0); const valorPrevisto = data.reduce((sum, item) => { const valor = typeof item.valor_previsto === "string" ? parseFloat(item.valor_previsto) : (item.valor_previsto || 0); return sum + (isNaN(valor) ? 0 : valor); }, 0); const valorConfirmado = data.reduce((sum, item) => { const valor = typeof item.valor_confirmado === "string" ? parseFloat(item.valor_confirmado) : (item.valor_confirmado || 0); return sum + (isNaN(valor) ? 0 : valor); }, 0); const valorPago = data.reduce((sum, item) => { const valor = typeof item.valor_pago === "string" ? parseFloat(item.valor_pago) : (item.valor_pago || 0); return sum + (isNaN(valor) ? 0 : valor); }, 0); return { valorRealizado, valorPrevisto, valorConfirmado, valorPago, }; }, [data]); // Exportação XLSX const exportToExcel = () => { if (data.length === 0) return; const exportData = data.map((item) => ({ "Data Competência": item.data_competencia ? new Date(item.data_competencia).toLocaleDateString("pt-BR") : "-", "Data Vencimento": item.data_vencimento ? new Date(item.data_vencimento).toLocaleDateString("pt-BR") : "-", "Data Caixa": item.data_caixa ? new Date(item.data_caixa).toLocaleDateString("pt-BR") : "-", "Código Fornecedor": item.codigo_fornecedor, Fornecedor: item.nome_fornecedor, "Código Centro Custo": item.codigo_centrocusto, "Centro Custo": item.codigo_centrocusto, "Código Conta": item.codigo_conta, Conta: item.conta, Valor: typeof item.valor === "string" ? parseFloat(item.valor) : item.valor, Histórico: item.historico, "Histórico 2": item.historico2, Recnum: item.recnum, })); const wb = XLSX.utils.book_new(); const ws = XLSX.utils.json_to_sheet(exportData); const resumoData = [ { Métrica: "Total de Registros", Valor: data.length }, { Métrica: "Valor Total", Valor: columnTotals.valorRealizado }, { Métrica: "Filtros Aplicados", Valor: "Sim" }, ]; const wsResumo = XLSX.utils.json_to_sheet(resumoData); XLSX.utils.book_append_sheet(wb, ws, "Dados Analíticos"); XLSX.utils.book_append_sheet(wb, wsResumo, "Resumo"); const now = new Date(); const timestamp = now.toISOString().slice(0, 19).replace(/:/g, "-"); const fileName = `analitico_${timestamp}.xlsx`; XLSX.writeFile(wb, fileName); }; // Aplicar filtros avançados const applyFilters = () => { // Implementar lógica de filtros avançados se necessário setOpen(false); }; const clearFilters = () => { setConditions([{ column: "", operator: "contains", value: "" }]); setGlobalFilter(""); }; return (
{/* Header Section */}

Análise Analítica{filtros.linhaSelecionada ? ` - ${filtros.linhaSelecionada}` : ""}

Relatório detalhado de transações

{/* Controls */}
) => setGlobalFilter(e.target.value) } className="w-64 bg-white border-gray-300 focus:border-blue-500 focus:ring-blue-500" /> {globalFilter && ( )} {data.length > 0 && ( )}
{/* Filtros Externos Ativos */} {(filtrosExternos.dataInicio || filtrosExternos.centroCusto || filtrosExternos.codigoGrupo || filtrosExternos.codigoConta) && (
Filtros aplicados pela tabela DRE Gerencial:
{filtrosExternos.dataInicio && filtrosExternos.dataFim && ( Período: {filtrosExternos.dataInicio} a {filtrosExternos.dataFim} )} {filtrosExternos.centroCusto && ( Centro: {filtrosExternos.centroCusto} )} {filtrosExternos.codigoGrupo && ( Grupo: {filtrosExternos.codigoGrupo} )} {filtrosExternos.codigoConta && ( Conta: {filtrosExternos.codigoConta} )}
)}
{/* DataGridPro */}

Total de Registros: {data.length}

Valor Total: {new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL", }).format(columnTotals.valorRealizado)}
{/* Advanced Filters Dialog */} Filtros Avançados

Estes filtros são aplicados sobre os dados já filtrados pela tabela DRE Gerencial.

{conditions.map((cond, idx) => (
{!(cond.operator === "empty" || cond.operator === "notEmpty") && (
) => { const next = [...conditions]; next[idx].value = e.target.value; setConditions(next); }} placeholder="Digite o valor" className="w-full bg-white border-gray-300" />
)} {conditions.length > 1 && (
)}
))}
); }