fix: remoção dos filtros avançados
This commit is contained in:
parent
a7adda84a5
commit
7b0c5d2070
|
|
@ -112,6 +112,11 @@ const ExcelFilter: React.FC<ExcelFilterProps> = ({
|
||||||
);
|
);
|
||||||
}, [uniqueValues, searchTerm]);
|
}, [uniqueValues, searchTerm]);
|
||||||
|
|
||||||
|
// Sincronizar estado local com filtros atuais
|
||||||
|
React.useEffect(() => {
|
||||||
|
setSelectedValues(currentFilter);
|
||||||
|
}, [currentFilter]);
|
||||||
|
|
||||||
// Verificar se todos estão selecionados
|
// Verificar se todos estão selecionados
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setSelectAll(selectedValues.length === filteredValues.length && filteredValues.length > 0);
|
setSelectAll(selectedValues.length === filteredValues.length && filteredValues.length > 0);
|
||||||
|
|
@ -140,6 +145,7 @@ const ExcelFilter: React.FC<ExcelFilterProps> = ({
|
||||||
|
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
setSelectedValues([]);
|
setSelectedValues([]);
|
||||||
|
setSelectAll(false);
|
||||||
onFilterChange(column.field, []);
|
onFilterChange(column.field, []);
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
};
|
};
|
||||||
|
|
@ -155,10 +161,10 @@ const ExcelFilter: React.FC<ExcelFilterProps> = ({
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="h-8 w-8 p-0"
|
className="h-6 w-6 p-0 hover:bg-gray-200 rounded-sm"
|
||||||
onClick={() => setIsOpen(true)}
|
onClick={() => setIsOpen(true)}
|
||||||
>
|
>
|
||||||
<ArrowUpDown className="h-4 w-4" />
|
<ArrowUpDown className="h-3 w-3 text-gray-600" />
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="max-w-md">
|
<DialogContent className="max-w-md">
|
||||||
|
|
@ -290,6 +296,12 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
}));
|
}));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Função para limpar todos os filtros
|
||||||
|
const clearAllFilters = React.useCallback(() => {
|
||||||
|
setColumnFilters({});
|
||||||
|
setColumnSorts({});
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Atualizar filtros externos quando os props mudarem
|
// Atualizar filtros externos quando os props mudarem
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
console.log('🔄 Analítico - useEffect dos filtros chamado');
|
console.log('🔄 Analítico - useEffect dos filtros chamado');
|
||||||
|
|
@ -559,22 +571,66 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
renderHeader: (params: any) => (
|
renderHeader: (params: any) => (
|
||||||
<div className="flex items-center justify-between w-full">
|
<div className="flex items-center justify-between w-full">
|
||||||
<span className="text-sm font-medium">{col.headerName}</span>
|
<span className="text-sm font-medium">{col.headerName}</span>
|
||||||
<ExcelFilter
|
<div className="flex items-center">
|
||||||
column={col}
|
<ExcelFilter
|
||||||
data={data}
|
column={col}
|
||||||
onFilterChange={handleColumnFilterChange}
|
data={data}
|
||||||
onSortChange={handleColumnSortChange}
|
onFilterChange={handleColumnFilterChange}
|
||||||
currentFilter={columnFilters[col.field] || []}
|
onSortChange={handleColumnSortChange}
|
||||||
currentSort={columnSorts[col.field] || null}
|
currentFilter={columnFilters[col.field] || []}
|
||||||
/>
|
currentSort={columnSorts[col.field] || null}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
}, [data, columnFilters, columnSorts, handleColumnFilterChange, handleColumnSortChange]);
|
}, [data, columnFilters, columnSorts, handleColumnFilterChange, handleColumnSortChange]);
|
||||||
|
|
||||||
// Calcular totais das colunas de valores
|
// Filtrar dados baseado nos filtros de coluna
|
||||||
|
const filteredData = React.useMemo(() => {
|
||||||
|
if (!data || data.length === 0) return data;
|
||||||
|
|
||||||
|
return data.filter((row) => {
|
||||||
|
return Object.entries(columnFilters).every(([field, filterValues]) => {
|
||||||
|
if (!filterValues || filterValues.length === 0) return true;
|
||||||
|
|
||||||
|
const cellValue = (row as any)[field];
|
||||||
|
const stringValue = cellValue === null || cellValue === undefined ? "" : String(cellValue);
|
||||||
|
|
||||||
|
return filterValues.includes(stringValue);
|
||||||
|
});
|
||||||
|
}).map((row, index) => ({
|
||||||
|
...row,
|
||||||
|
id: `filtered-${row.id || row.recnum || index}` // Garantir ID único e estável
|
||||||
|
}));
|
||||||
|
}, [data, columnFilters]);
|
||||||
|
|
||||||
|
// Ordenar dados baseado na ordenação de coluna
|
||||||
|
const sortedAndFilteredData = React.useMemo(() => {
|
||||||
|
if (!filteredData || filteredData.length === 0) return filteredData;
|
||||||
|
|
||||||
|
const sortField = Object.keys(columnSorts).find(field => columnSorts[field] !== null);
|
||||||
|
if (!sortField || !columnSorts[sortField]) return filteredData;
|
||||||
|
|
||||||
|
return [...filteredData].sort((a, b) => {
|
||||||
|
const aValue = (a as any)[sortField];
|
||||||
|
const bValue = (b as any)[sortField];
|
||||||
|
|
||||||
|
// Converter para string para comparação
|
||||||
|
const aString = aValue === null || aValue === undefined ? "" : String(aValue);
|
||||||
|
const bString = bValue === null || bValue === undefined ? "" : String(bValue);
|
||||||
|
|
||||||
|
if (columnSorts[sortField] === 'asc') {
|
||||||
|
return aString.localeCompare(bString);
|
||||||
|
} else {
|
||||||
|
return bString.localeCompare(aString);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [filteredData, columnSorts]);
|
||||||
|
|
||||||
|
// Calcular totais das colunas de valores (usando dados filtrados)
|
||||||
const columnTotals = React.useMemo(() => {
|
const columnTotals = React.useMemo(() => {
|
||||||
if (!data || data.length === 0) {
|
if (!sortedAndFilteredData || sortedAndFilteredData.length === 0) {
|
||||||
return {
|
return {
|
||||||
valorRealizado: 0,
|
valorRealizado: 0,
|
||||||
valorPrevisto: 0,
|
valorPrevisto: 0,
|
||||||
|
|
@ -583,22 +639,22 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const valorRealizado = data.reduce((sum, item) => {
|
const valorRealizado = sortedAndFilteredData.reduce((sum, item) => {
|
||||||
const valor = typeof item.valor === "string" ? parseFloat(item.valor) : item.valor;
|
const valor = typeof item.valor === "string" ? parseFloat(item.valor) : item.valor;
|
||||||
return sum + (isNaN(valor) ? 0 : valor);
|
return sum + (isNaN(valor) ? 0 : valor);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
const valorPrevisto = data.reduce((sum, item) => {
|
const valorPrevisto = sortedAndFilteredData.reduce((sum, item) => {
|
||||||
const valor = typeof item.valor_previsto === "string" ? parseFloat(item.valor_previsto) : (item.valor_previsto || 0);
|
const valor = typeof item.valor_previsto === "string" ? parseFloat(item.valor_previsto) : (item.valor_previsto || 0);
|
||||||
return sum + (isNaN(valor) ? 0 : valor);
|
return sum + (isNaN(valor) ? 0 : valor);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
const valorConfirmado = data.reduce((sum, item) => {
|
const valorConfirmado = sortedAndFilteredData.reduce((sum, item) => {
|
||||||
const valor = typeof item.valor_confirmado === "string" ? parseFloat(item.valor_confirmado) : (item.valor_confirmado || 0);
|
const valor = typeof item.valor_confirmado === "string" ? parseFloat(item.valor_confirmado) : (item.valor_confirmado || 0);
|
||||||
return sum + (isNaN(valor) ? 0 : valor);
|
return sum + (isNaN(valor) ? 0 : valor);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
const valorPago = data.reduce((sum, item) => {
|
const valorPago = sortedAndFilteredData.reduce((sum, item) => {
|
||||||
const valor = typeof item.valor_pago === "string" ? parseFloat(item.valor_pago) : (item.valor_pago || 0);
|
const valor = typeof item.valor_pago === "string" ? parseFloat(item.valor_pago) : (item.valor_pago || 0);
|
||||||
return sum + (isNaN(valor) ? 0 : valor);
|
return sum + (isNaN(valor) ? 0 : valor);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
@ -609,13 +665,13 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
valorConfirmado,
|
valorConfirmado,
|
||||||
valorPago,
|
valorPago,
|
||||||
};
|
};
|
||||||
}, [data]);
|
}, [sortedAndFilteredData]);
|
||||||
|
|
||||||
// Exportação XLSX
|
// Exportação XLSX
|
||||||
const exportToExcel = () => {
|
const exportToExcel = () => {
|
||||||
if (data.length === 0) return;
|
if (sortedAndFilteredData.length === 0) return;
|
||||||
|
|
||||||
const exportData = data.map((item) => ({
|
const exportData = sortedAndFilteredData.map((item) => ({
|
||||||
"Data Competência": item.data_competencia
|
"Data Competência": item.data_competencia
|
||||||
? new Date(item.data_competencia).toLocaleDateString("pt-BR")
|
? new Date(item.data_competencia).toLocaleDateString("pt-BR")
|
||||||
: "-",
|
: "-",
|
||||||
|
|
@ -684,7 +740,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
|
|
||||||
{/* Controls */}
|
{/* Controls */}
|
||||||
<div className="flex gap-2 flex-wrap">
|
<div className="flex gap-2 flex-wrap">
|
||||||
<Input
|
{/* <Input
|
||||||
placeholder="Filtrar tudo..."
|
placeholder="Filtrar tudo..."
|
||||||
value={globalFilter ?? ""}
|
value={globalFilter ?? ""}
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||||
|
|
@ -699,7 +755,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
>
|
>
|
||||||
<Filter className="w-4 h-4 mr-2" />
|
<Filter className="w-4 h-4 mr-2" />
|
||||||
Filtros Avançados
|
Filtros Avançados
|
||||||
</Button>
|
</Button> */}
|
||||||
{globalFilter && (
|
{globalFilter && (
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|
@ -711,15 +767,26 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{data.length > 0 && (
|
{data.length > 0 && (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Button
|
||||||
|
onClick={clearAllFilters}
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="flex items-center gap-2 bg-white border-gray-300 hover:bg-red-50 hover:border-red-300 text-gray-700"
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
Limpar Filtros
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={exportToExcel}
|
onClick={exportToExcel}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="flex items-center gap-2 bg-white border-gray-300 hover:bg-green-50 hover:border-green-300 text-gray-700"
|
className="flex items-center gap-2 bg-white border-gray-300 hover:bg-green-50 hover:border-green-300 text-gray-700"
|
||||||
>
|
>
|
||||||
<Download className="h-4 w-4" />
|
<Download className="h-4 w-4" />
|
||||||
Exportar XLSX
|
Exportar XLSX
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -778,12 +845,16 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
|
|
||||||
<div style={{ height: "calc(100% - 2rem)", width: "100%" }}>
|
<div style={{ height: "calc(100% - 2rem)", width: "100%" }}>
|
||||||
<DataGrid
|
<DataGrid
|
||||||
rows={data}
|
key={`datagrid-${sortedAndFilteredData.length}-${Object.keys(columnFilters).length}`}
|
||||||
|
rows={sortedAndFilteredData}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
disableRowSelectionOnClick
|
disableRowSelectionOnClick
|
||||||
density="compact"
|
density="compact"
|
||||||
slots={{ toolbar: GridToolbar }}
|
slots={{ toolbar: GridToolbar }}
|
||||||
|
disableColumnMenu={true}
|
||||||
|
disableColumnSorting={true}
|
||||||
|
getRowId={(row) => row.id || `row-${row.recnum || Math.random()}`}
|
||||||
initialState={{
|
initialState={{
|
||||||
sorting: { sortModel: [{ field: "data_vencimento", sort: "desc" }] },
|
sorting: { sortModel: [{ field: "data_vencimento", sort: "desc" }] },
|
||||||
}}
|
}}
|
||||||
|
|
@ -805,6 +876,54 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
borderBottom: "1px solid #e5e7eb",
|
borderBottom: "1px solid #e5e7eb",
|
||||||
padding: "8px 16px",
|
padding: "8px 16px",
|
||||||
},
|
},
|
||||||
|
// Ocultar todos os ícones nativos das colunas
|
||||||
|
"& .MuiDataGrid-columnHeaderMenuContainer": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-columnHeaderMenuButton": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-columnHeaderSortIcon": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-columnHeaderSortIconContainer": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-iconButtonContainer": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-columnHeaderSeparator": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-columnHeaderSortButton": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
// Ocultar qualquer ícone de menu adicional
|
||||||
|
"& .MuiDataGrid-menuIcon": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-menuIconButton": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-columnHeaderMenuIcon": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-columnHeaderMenuIconButton": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-menuContainer": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-menu": {
|
||||||
|
display: "none !important",
|
||||||
|
},
|
||||||
|
// Garantir que nosso botão customizado apareça
|
||||||
|
"& .MuiDataGrid-columnHeaderTitleContainer": {
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
"& .MuiDataGrid-footerContainer": {
|
"& .MuiDataGrid-footerContainer": {
|
||||||
backgroundColor: "#f8fafc",
|
backgroundColor: "#f8fafc",
|
||||||
borderTop: "1px solid #e5e7eb",
|
borderTop: "1px solid #e5e7eb",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue