Merge pull request #5 from JurunenseDevInterno/fix-redimensionamento-tabela-analitica

Fix redimensionamento tabela analitica
This commit is contained in:
Alessandro Gonçalves 2025-10-22 16:35:58 -03:00 committed by GitHub
commit 631aed62f8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 1339 additions and 600 deletions

31
package-lock.json generated
View File

@ -8,6 +8,7 @@
"name": "dre-gerencial", "name": "dre-gerencial",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-label": "^2.1.7", "@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-select": "^2.2.6", "@radix-ui/react-select": "^2.2.6",
@ -1536,6 +1537,36 @@
} }
} }
}, },
"node_modules/@radix-ui/react-checkbox": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz",
"integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-context": "1.1.2",
"@radix-ui/react-presence": "1.1.5",
"@radix-ui/react-primitive": "2.1.3",
"@radix-ui/react-use-controllable-state": "1.2.2",
"@radix-ui/react-use-previous": "1.1.1",
"@radix-ui/react-use-size": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-collection": { "node_modules/@radix-ui/react-collection": {
"version": "1.1.7", "version": "1.1.7",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",

View File

@ -9,6 +9,7 @@
"lint": "eslint" "lint": "eslint"
}, },
"dependencies": { "dependencies": {
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-label": "^2.1.7", "@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-select": "^2.2.6", "@radix-ui/react-select": "^2.2.6",

View File

@ -7,6 +7,7 @@ import {
getSortedRowModel, getSortedRowModel,
getFilteredRowModel, getFilteredRowModel,
ColumnFiltersState, ColumnFiltersState,
ColumnSizingState,
} from "@tanstack/react-table"; } from "@tanstack/react-table";
import { useVirtualizer } from "@tanstack/react-virtual"; import { useVirtualizer } from "@tanstack/react-virtual";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
@ -67,6 +68,7 @@ interface AnaliticoProps {
codigoGrupo?: string; codigoGrupo?: string;
codigoSubgrupo?: string; codigoSubgrupo?: string;
codigoConta?: string; codigoConta?: string;
linhaSelecionada?: string; // Adicionar propriedade para linha selecionada
}; };
} }
@ -75,6 +77,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
const [loading, setLoading] = React.useState(false); const [loading, setLoading] = React.useState(false);
const [globalFilter, setGlobalFilter] = React.useState(""); const [globalFilter, setGlobalFilter] = React.useState("");
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]); const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
const [columnSizing, setColumnSizing] = React.useState<ColumnSizingState>({});
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const [conditions, setConditions] = React.useState([ const [conditions, setConditions] = React.useState([
{ column: "", operator: "contains", value: "" }, { column: "", operator: "contains", value: "" },
@ -88,6 +91,14 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
console.log('🔄 Analítico - useEffect dos filtros chamado'); console.log('🔄 Analítico - useEffect dos filtros chamado');
console.log('📋 Filtros recebidos via props:', filtros); console.log('📋 Filtros recebidos via props:', filtros);
console.log('📋 Filtros externos atuais:', filtrosExternos); console.log('📋 Filtros externos atuais:', filtrosExternos);
console.log('🔍 Detalhes dos filtros:', {
dataInicio: filtros.dataInicio,
dataFim: filtros.dataFim,
centroCusto: filtros.centroCusto,
codigoGrupo: filtros.codigoGrupo,
codigoConta: filtros.codigoConta,
linhaSelecionada: filtros.linhaSelecionada
});
setFiltrosExternos(filtros); setFiltrosExternos(filtros);
}, [filtros, filtrosExternos]); }, [filtros, filtrosExternos]);
@ -125,6 +136,13 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
const url = `/api/analitico-oracle?${params.toString()}`; const url = `/api/analitico-oracle?${params.toString()}`;
console.log('🌐 Fazendo requisição para:', url); console.log('🌐 Fazendo requisição para:', url);
console.log('📋 Parâmetros enviados:', {
dataInicio: filtrosExternos.dataInicio,
dataFim: filtrosExternos.dataFim,
centroCusto: filtrosExternos.centroCusto,
codigoGrupo: filtrosExternos.codigoGrupo,
codigoConta: filtrosExternos.codigoConta
});
const response = await fetch(url); const response = await fetch(url);
if (response.ok) { if (response.ok) {
@ -153,6 +171,9 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
accessorKey: "data_vencimento", accessorKey: "data_vencimento",
header: "Data de Vencimento", header: "Data de Vencimento",
filterFn: "advancedText", filterFn: "advancedText",
size: 140,
minSize: 100,
maxSize: 200,
cell: ({ getValue }: { getValue: () => string }) => { cell: ({ getValue }: { getValue: () => string }) => {
const value = getValue(); const value = getValue();
return new Date(value).toLocaleDateString("pt-BR"); return new Date(value).toLocaleDateString("pt-BR");
@ -162,6 +183,9 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
accessorKey: "data_caixa", accessorKey: "data_caixa",
header: "Data de Caixa", header: "Data de Caixa",
filterFn: "advancedText", filterFn: "advancedText",
size: 120,
minSize: 100,
maxSize: 180,
cell: ({ getValue }: { getValue: () => string }) => { cell: ({ getValue }: { getValue: () => string }) => {
const value = getValue(); const value = getValue();
return new Date(value).toLocaleDateString("pt-BR"); return new Date(value).toLocaleDateString("pt-BR");
@ -171,6 +195,9 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
accessorKey: "entidade", accessorKey: "entidade",
header: "Entidade", header: "Entidade",
filterFn: "advancedText", filterFn: "advancedText",
size: 120,
minSize: 80,
maxSize: 200,
cell: ({ getValue }: { getValue: () => string }) => { cell: ({ getValue }: { getValue: () => string }) => {
const value = getValue(); const value = getValue();
return value || "-"; return value || "-";
@ -180,31 +207,49 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
accessorKey: "codigo_fornecedor", accessorKey: "codigo_fornecedor",
header: "Código do Fornecedor", header: "Código do Fornecedor",
filterFn: "advancedText", filterFn: "advancedText",
size: 120,
minSize: 100,
maxSize: 150,
}, },
{ {
accessorKey: "nome_fornecedor", accessorKey: "nome_fornecedor",
header: "Nome do Fornecedor", header: "Nome do Fornecedor",
filterFn: "advancedText", filterFn: "advancedText",
size: 220,
minSize: 150,
maxSize: 400,
}, },
{ {
accessorKey: "codigo_centrocusto", accessorKey: "codigo_centrocusto",
header: "Centro de Custo", header: "Centro de Custo",
filterFn: "advancedText", filterFn: "advancedText",
size: 140,
minSize: 100,
maxSize: 200,
}, },
{ {
accessorKey: "codigo_conta", accessorKey: "codigo_conta",
header: "Código da Conta", header: "Código da Conta",
filterFn: "advancedText", filterFn: "advancedText",
size: 130,
minSize: 100,
maxSize: 180,
}, },
{ {
accessorKey: "conta", accessorKey: "conta",
header: "Nome da Conta", header: "Nome da Conta",
filterFn: "advancedText", filterFn: "advancedText",
size: 160,
minSize: 120,
maxSize: 300,
}, },
{ {
accessorKey: "valor", accessorKey: "valor",
header: "Valor Realizado", header: "Valor Realizado",
filterFn: "advancedText", filterFn: "advancedText",
size: 130,
minSize: 100,
maxSize: 200,
cell: ({ getValue }: { getValue: () => number }) => { cell: ({ getValue }: { getValue: () => number }) => {
const value = getValue(); const value = getValue();
const formatted = new Intl.NumberFormat("pt-BR", { const formatted = new Intl.NumberFormat("pt-BR", {
@ -223,6 +268,9 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
accessorKey: "valor_previsto", accessorKey: "valor_previsto",
header: "Valor Previsto", header: "Valor Previsto",
filterFn: "advancedText", filterFn: "advancedText",
size: 120,
minSize: 100,
maxSize: 180,
cell: ({ getValue }: { getValue: () => number }) => { cell: ({ getValue }: { getValue: () => number }) => {
const value = getValue(); const value = getValue();
if (!value || value === 0) return "-"; if (!value || value === 0) return "-";
@ -242,6 +290,9 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
accessorKey: "valor_confirmado", accessorKey: "valor_confirmado",
header: "Valor Confirmado", header: "Valor Confirmado",
filterFn: "advancedText", filterFn: "advancedText",
size: 130,
minSize: 100,
maxSize: 200,
cell: ({ getValue }: { getValue: () => number }) => { cell: ({ getValue }: { getValue: () => number }) => {
const value = getValue(); const value = getValue();
if (!value || value === 0) return "-"; if (!value || value === 0) return "-";
@ -261,6 +312,9 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
accessorKey: "valor_pago", accessorKey: "valor_pago",
header: "Valor Pago", header: "Valor Pago",
filterFn: "advancedText", filterFn: "advancedText",
size: 140,
minSize: 100,
maxSize: 200,
cell: ({ getValue }: { getValue: () => number }) => { cell: ({ getValue }: { getValue: () => number }) => {
const value = getValue(); const value = getValue();
if (!value || value === 0) return "-"; if (!value || value === 0) return "-";
@ -280,16 +334,25 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
accessorKey: "historico", accessorKey: "historico",
header: "Histórico", header: "Histórico",
filterFn: "advancedText", filterFn: "advancedText",
size: 320,
minSize: 200,
maxSize: 500,
}, },
{ {
accessorKey: "historico2", accessorKey: "historico2",
header: "Histórico 2", header: "Histórico 2",
filterFn: "advancedText", filterFn: "advancedText",
size: 500,
minSize: 300,
maxSize: 800,
}, },
{ {
accessorKey: "numero_lancamento", accessorKey: "numero_lancamento",
header: "Número do Lançamento", header: "Número do Lançamento",
filterFn: "advancedText", filterFn: "advancedText",
size: 30,
minSize: 20,
maxSize: 50,
cell: ({ getValue }: { getValue: () => number }) => { cell: ({ getValue }: { getValue: () => number }) => {
const value = getValue(); const value = getValue();
return value || "-"; return value || "-";
@ -341,13 +404,16 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
const table = useReactTable({ const table = useReactTable({
data, data,
columns: columns as any, columns: columns as any,
state: { globalFilter, columnFilters }, state: { globalFilter, columnFilters, columnSizing },
onGlobalFilterChange: setGlobalFilter, onGlobalFilterChange: setGlobalFilter,
onColumnFiltersChange: setColumnFilters, onColumnFiltersChange: setColumnFilters,
onColumnSizingChange: setColumnSizing,
filterFns, filterFns,
getCoreRowModel: getCoreRowModel(), getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(), getFilteredRowModel: getFilteredRowModel(),
getSortedRowModel: getSortedRowModel(), getSortedRowModel: getSortedRowModel(),
enableColumnResizing: true,
columnResizeMode: 'onChange',
}); });
const parentRef = React.useRef<HTMLDivElement>(null); const parentRef = React.useRef<HTMLDivElement>(null);
@ -542,69 +608,21 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
}; };
return ( return (
<div className="w-full max-w-none mx-auto p-6"> <div className="w-full max-w-none mx-auto p-2">
{/* Header Section */} {/* Header Section */}
<div className="mb-6"> <div className="mb-2">
<div className="flex items-center gap-3 mb-4"> <div className="flex items-center justify-between mb-1">
{/* <div className="w-12 h-12 bg-gradient-to-r from-blue-600 to-indigo-600 rounded-xl flex items-center justify-center shadow-lg">
<svg
className="w-7 h-7 text-white"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
/>
</svg>
</div> */}
<div> <div>
<h1 className="text-2xl font-bold text-gray-900"> <h1 className="text-2xl font-bold text-gray-900">
Análise Analítica Análise Analítica{filtros.linhaSelecionada ? ` - ${filtros.linhaSelecionada}` : ""}
</h1> </h1>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
Relatório detalhado de transações Relatório detalhado de transações
</p> </p>
</div> </div>
</div>
{/* Filtros Externos Ativos */}
{(filtrosExternos.dataInicio || filtrosExternos.centroCusto || filtrosExternos.codigoGrupo || filtrosExternos.codigoConta) && (
<div className="mb-4 p-3 bg-blue-50 border border-blue-200 rounded-lg">
<div className="flex items-center gap-2 mb-2">
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
<span className="text-sm font-medium text-blue-900">Filtros aplicados pela tabela DRE Gerencial:</span>
</div>
<div className="flex flex-wrap gap-2 text-xs text-blue-800">
{filtrosExternos.dataInicio && filtrosExternos.dataFim && (
<span className="px-2 py-1 bg-blue-100 rounded">
Período: {filtrosExternos.dataInicio} a {filtrosExternos.dataFim}
</span>
)}
{filtrosExternos.centroCusto && (
<span className="px-2 py-1 bg-blue-100 rounded">
Centro: {filtrosExternos.centroCusto}
</span>
)}
{filtrosExternos.codigoGrupo && (
<span className="px-2 py-1 bg-blue-100 rounded">
Grupo: {filtrosExternos.codigoGrupo}
</span>
)}
{filtrosExternos.codigoConta && (
<span className="px-2 py-1 bg-blue-100 rounded">
Conta: {filtrosExternos.codigoConta}
</span>
)}
</div>
</div>
)}
{/* Controls */} {/* Controls */}
<div className="flex gap-3 flex-wrap"> <div className="flex gap-2 flex-wrap">
<Input <Input
placeholder="Filtrar tudo..." placeholder="Filtrar tudo..."
value={globalFilter ?? ""} value={globalFilter ?? ""}
@ -650,44 +668,68 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
</div> </div>
</div> </div>
{/* Filtros Externos Ativos */}
{(filtrosExternos.dataInicio || filtrosExternos.centroCusto || filtrosExternos.codigoGrupo || filtrosExternos.codigoConta) && (
<div className="mb-2 p-2 bg-transparent border-transparent rounded-lg">
<div className="flex items-center gap-2 mb-1">
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
<span className="text-sm font-medium text-blue-900">Filtros aplicados pela tabela DRE Gerencial:</span>
</div>
<div className="flex flex-wrap gap-2 text-xs text-blue-800">
{filtrosExternos.dataInicio && filtrosExternos.dataFim && (
<span className="px-2 py-1 bg-blue-100 rounded">
Período: {filtrosExternos.dataInicio} a {filtrosExternos.dataFim}
</span>
)}
{filtrosExternos.centroCusto && (
<span className="px-2 py-1 bg-blue-100 rounded">
Centro: {filtrosExternos.centroCusto}
</span>
)}
{filtrosExternos.codigoGrupo && (
<span className="px-2 py-1 bg-blue-100 rounded">
Grupo: {filtrosExternos.codigoGrupo}
</span>
)}
{filtrosExternos.codigoConta && (
<span className="px-2 py-1 bg-blue-100 rounded">
Conta: {filtrosExternos.codigoConta}
</span>
)}
</div>
</div>
)}
</div>
{/* Table Container */} {/* Table Container */}
<div className="bg-white rounded-xl shadow-lg border border-gray-200 overflow-x-auto"> <div className="bg-white rounded-xl shadow-lg border border-gray-200 overflow-x-auto">
<div className="min-w-[2800px]"> <div className="min-w-[2800px]">
{/* Table Header */} {/* Table Header */}
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 border-b border-gray-200 sticky top-0 z-20"> <div className="bg-gradient-to-r from-blue-50 to-indigo-50 border-b border-gray-200 sticky top-0 z-20">
<div className="flex items-center px-4 py-3 text-xs font-semibold text-gray-700 uppercase tracking-wide"> <div className="flex items-center px-4 py-3 text-xs font-semibold text-gray-700 uppercase tracking-wide">
<div className="w-[140px] whitespace-nowrap"> {table.getHeaderGroups().map(headerGroup => (
Data de Vencimento headerGroup.headers.map(header => (
<div
key={header.id}
className="whitespace-nowrap flex items-center"
style={{ width: header.getSize() }}
>
{header.isPlaceholder ? null : (
<div className="flex items-center gap-2 w-full">
<span>{String(header.column.columnDef.header)}</span>
{header.column.getCanResize() && (
<div
className="w-1 h-6 bg-gray-300 hover:bg-blue-500 cursor-col-resize"
onMouseDown={header.getResizeHandler()}
onTouchStart={header.getResizeHandler()}
/>
)}
</div> </div>
<div className="w-[120px] whitespace-nowrap">Data de Caixa</div> )}
<div className="w-[120px] whitespace-nowrap">Entidade</div>
<div className="w-[120px] whitespace-nowrap">
Cód. Fornec
</div>
<div className="w-[220px] whitespace-nowrap">
Nome do Fornecedor
</div>
<div className="w-[140px] whitespace-nowrap">Centro de Custo</div>
<div className="w-[130px] whitespace-nowrap">Código da Conta</div>
<div className="w-[160px] whitespace-nowrap">Nome da Conta</div>
<div className="w-[130px] whitespace-nowrap text-right">
Valor Realizado
</div>
<div className="w-[120px] whitespace-nowrap text-right">
Valor Previsto
</div>
<div className="w-[130px] whitespace-nowrap text-right">
Valor Confirmado
</div>
<div className="w-[140px] whitespace-nowrap text-right">
Valor Pago
</div>
<div className="w-[20px] whitespace-nowrap"></div>
<div className="w-[320px] whitespace-nowrap">Histórico</div>
<div className="w-[500px] whitespace-nowrap">Histórico 2</div>
<div className="w-[30px] whitespace-nowrap">
Número do Lançamento
</div> </div>
))
))}
</div> </div>
</div> </div>
@ -741,110 +783,15 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
className="absolute top-0 left-0 w-full flex items-center px-4 py-3 text-sm border-b border-gray-100 hover:bg-gray-50 transition-colors" className="absolute top-0 left-0 w-full flex items-center px-4 py-3 text-sm border-b border-gray-100 hover:bg-gray-50 transition-colors"
style={{ transform: `translateY(${virtualRow.start}px)` }} style={{ transform: `translateY(${virtualRow.start}px)` }}
> >
<div className="w-[140px] text-gray-600 whitespace-nowrap"> {row.getVisibleCells().map(cell => (
{new Date(
row.original.data_vencimento
).toLocaleDateString("pt-BR")}
</div>
<div className="w-[120px] text-gray-600 whitespace-nowrap">
{new Date(row.original.data_caixa).toLocaleDateString(
"pt-BR"
)}
</div>
<div className="w-[120px] text-gray-500 whitespace-nowrap">
{row.original.entidade || "-"}
</div>
<div className="w-[120px] font-medium text-gray-900 whitespace-nowrap">
{row.original.codigo_fornecedor}
</div>
<div <div
className="w-[220px] text-gray-700 truncate" key={cell.id}
title={row.original.nome_fornecedor} className="whitespace-nowrap overflow-hidden"
style={{ width: cell.column.getSize() }}
> >
{row.original.nome_fornecedor} {String(cell.renderValue() || '')}
</div>
<div className="w-[140px] text-gray-600 whitespace-nowrap">
{row.original.codigo_centrocusto}
</div>
<div className="w-[130px] text-gray-600 whitespace-nowrap">
{row.original.codigo_conta}
</div>
<div
className="w-[160px] text-gray-700 truncate"
title={row.original.conta}
>
{row.original.conta}
</div>
<div
className={`w-[130px] text-right font-semibold whitespace-nowrap ${
row.original.valor < 0
? "text-red-600"
: "text-gray-900"
}`}
>
{new Intl.NumberFormat("pt-BR", {
style: "currency",
currency: "BRL",
}).format(row.original.valor)}
</div>
<div className="w-[120px] text-right whitespace-nowrap">
{row.original.valor_previsto && row.original.valor_previsto !== 0 ? (
<span className={`font-semibold ${
row.original.valor_previsto < 0 ? "text-red-600" : "text-gray-900"
}`}>
{new Intl.NumberFormat("pt-BR", {
style: "currency",
currency: "BRL",
}).format(row.original.valor_previsto)}
</span>
) : (
<span className="text-gray-500">-</span>
)}
</div>
<div className="w-[130px] text-right whitespace-nowrap">
{row.original.valor_confirmado && row.original.valor_confirmado !== 0 ? (
<span className={`font-semibold ${
row.original.valor_confirmado < 0 ? "text-red-600" : "text-gray-900"
}`}>
{new Intl.NumberFormat("pt-BR", {
style: "currency",
currency: "BRL",
}).format(row.original.valor_confirmado)}
</span>
) : (
<span className="text-gray-500">-</span>
)}
</div>
<div className="w-[140px] text-right whitespace-nowrap">
{row.original.valor_pago && row.original.valor_pago !== 0 ? (
<span className={`font-semibold ${
row.original.valor_pago < 0 ? "text-red-600" : "text-gray-900"
}`}>
{new Intl.NumberFormat("pt-BR", {
style: "currency",
currency: "BRL",
}).format(row.original.valor_pago)}
</span>
) : (
<span className="text-gray-500">-</span>
)}
</div>
<div className="w-[20px] whitespace-nowrap"></div>
<div
className="w-[320px] text-gray-700 truncate"
title={row.original.historico}
>
{row.original.historico}
</div>
<div
className="w-[500px] text-gray-700 truncate"
title={row.original.historico2}
>
{row.original.historico2}
</div>
<div className="w-[30px] text-gray-500 whitespace-nowrap">
{row.original.numero_lancamento || "-"}
</div> </div>
))}
</div> </div>
); );
})} })}
@ -856,29 +803,32 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
{data.length > 0 && ( {data.length > 0 && (
<div className="bg-gradient-to-r from-gray-50 to-gray-100 border-t border-gray-200 sticky bottom-0 z-10"> <div className="bg-gradient-to-r from-gray-50 to-gray-100 border-t border-gray-200 sticky bottom-0 z-10">
<div className="flex items-center px-4 py-3 text-sm font-semibold text-gray-900"> <div className="flex items-center px-4 py-3 text-sm font-semibold text-gray-900">
<div className="w-[140px] whitespace-nowrap text-gray-600"> {table.getHeaderGroups().map(headerGroup => (
TOTAL: {table.getRowModel().rows.length} registros headerGroup.headers.map((header, index) => (
</div>
<div className="w-[120px] whitespace-nowrap"></div>
<div className="w-[120px] whitespace-nowrap"></div>
<div className="w-[120px] whitespace-nowrap"></div>
<div className="w-[220px] whitespace-nowrap"></div>
<div className="w-[140px] whitespace-nowrap"></div>
<div className="w-[130px] whitespace-nowrap"></div>
<div className="w-[160px] whitespace-nowrap"></div>
<div <div
className={`w-[130px] text-right font-bold whitespace-nowrap ${ key={header.id}
className="whitespace-nowrap"
style={{ width: header.getSize() }}
>
{index === 0 && (
<span className="text-gray-600">
TOTAL: {table.getRowModel().rows.length} registros
</span>
)}
{index === 8 && (
<span className={`text-right font-bold ${
columnTotals.valorRealizado < 0 columnTotals.valorRealizado < 0
? "text-red-600" ? "text-red-600"
: "text-green-600" : "text-green-600"
}`} }`}>
>
{new Intl.NumberFormat("pt-BR", { {new Intl.NumberFormat("pt-BR", {
style: "currency", style: "currency",
currency: "BRL", currency: "BRL",
}).format(columnTotals.valorRealizado)} }).format(columnTotals.valorRealizado)}
</div> </span>
<div className="w-[120px] text-right whitespace-nowrap"> )}
{index === 9 && (
<span className="text-right">
{columnTotals.valorPrevisto !== 0 ? ( {columnTotals.valorPrevisto !== 0 ? (
<span className={`font-bold ${ <span className={`font-bold ${
columnTotals.valorPrevisto < 0 ? "text-red-600" : "text-green-600" columnTotals.valorPrevisto < 0 ? "text-red-600" : "text-green-600"
@ -891,8 +841,10 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
) : ( ) : (
<span className="text-gray-500">-</span> <span className="text-gray-500">-</span>
)} )}
</div> </span>
<div className="w-[130px] text-right whitespace-nowrap"> )}
{index === 10 && (
<span className="text-right">
{columnTotals.valorConfirmado !== 0 ? ( {columnTotals.valorConfirmado !== 0 ? (
<span className={`font-bold ${ <span className={`font-bold ${
columnTotals.valorConfirmado < 0 ? "text-red-600" : "text-green-600" columnTotals.valorConfirmado < 0 ? "text-red-600" : "text-green-600"
@ -905,8 +857,10 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
) : ( ) : (
<span className="text-gray-500">-</span> <span className="text-gray-500">-</span>
)} )}
</div> </span>
<div className="w-[140px] text-right whitespace-nowrap"> )}
{index === 11 && (
<span className="text-right">
{columnTotals.valorPago !== 0 ? ( {columnTotals.valorPago !== 0 ? (
<span className={`font-bold ${ <span className={`font-bold ${
columnTotals.valorPago < 0 ? "text-red-600" : "text-green-600" columnTotals.valorPago < 0 ? "text-red-600" : "text-green-600"
@ -919,11 +873,11 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
) : ( ) : (
<span className="text-gray-500">-</span> <span className="text-gray-500">-</span>
)} )}
</span>
)}
</div> </div>
<div className="w-[20px] whitespace-nowrap"></div> ))
<div className="w-[320px] whitespace-nowrap"></div> ))}
<div className="w-[500px] whitespace-nowrap"></div>
<div className="w-[30px] whitespace-nowrap"></div>
</div> </div>
</div> </div>
)} )}
@ -987,7 +941,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
{conditions.map((cond, idx) => ( {conditions.map((cond, idx) => (
<div <div
key={idx} key={idx}
className="flex gap-3 items-start p-4 bg-gray-50 rounded-lg border border-gray-200" className="flex gap-2 items-start p-2 bg-gray-50 rounded-lg border border-gray-200"
> >
<div className="flex-1"> <div className="flex-1">
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">
@ -1100,7 +1054,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
</div> </div>
</div> </div>
<DialogFooter className="flex gap-3 pt-6 border-t border-gray-200"> <DialogFooter className="flex gap-2 pt-3 border-t border-gray-200">
<Button <Button
variant="outline" variant="outline"
onClick={clearFilters} onClick={clearFilters}

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,8 @@ export async function GET(request: NextRequest) {
data_cai: item.DATA || "2023-03", // Usar DATA do Oracle data_cai: item.DATA || "2023-03", // Usar DATA do Oracle
grupo: codgrupo ? `${codgrupo} - ${nomeGrupo}` : nomeGrupo, // Concatenar código + nome grupo: codgrupo ? `${codgrupo} - ${nomeGrupo}` : nomeGrupo, // Concatenar código + nome
subgrupo: item.CENTROCUSTO || "", // Usar CENTROCUSTO como subgrupo subgrupo: item.CENTROCUSTO || "", // Usar CENTROCUSTO como subgrupo
centro_custo: item.CODIGOCENTROCUSTO || "", // Usar CODIGOCENTROCUSTO centro_custo: item.CENTROCUSTO || "", // Usar CENTROCUSTO (nome do centro)
codigo_centro_custo: item.CODIGOCENTROCUSTO || "", // Usar CODIGOCENTROCUSTO (código do centro)
codigo_conta: parseInt(item.CODCONTA) || 0, // Converter CODCONTA para número codigo_conta: parseInt(item.CODCONTA) || 0, // Converter CODCONTA para número
conta: item.CONTA || "", // Usar CONTA do Oracle conta: item.CONTA || "", // Usar CONTA do Oracle
valor: item.VALOR?.toString() || "0", // Converter VALOR para string valor: item.VALOR?.toString() || "0", // Converter VALOR para string

View File

@ -0,0 +1,30 @@
"use client"
import * as React from "react"
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
import { Check } from "lucide-react"
import { cn } from "@/lib/utils"
const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
>(({ className, ...props }, ref) => (
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
className
)}
{...props}
>
<CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current")}
>
<Check className="h-4 w-4" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
))
Checkbox.displayName = CheckboxPrimitive.Root.displayName
export { Checkbox }