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]);
|
||||
|
||||
// Sincronizar estado local com filtros atuais
|
||||
React.useEffect(() => {
|
||||
setSelectedValues(currentFilter);
|
||||
}, [currentFilter]);
|
||||
|
||||
// Verificar se todos estão selecionados
|
||||
React.useEffect(() => {
|
||||
setSelectAll(selectedValues.length === filteredValues.length && filteredValues.length > 0);
|
||||
|
|
@ -140,6 +145,7 @@ const ExcelFilter: React.FC<ExcelFilterProps> = ({
|
|||
|
||||
const handleClear = () => {
|
||||
setSelectedValues([]);
|
||||
setSelectAll(false);
|
||||
onFilterChange(column.field, []);
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
|
@ -155,10 +161,10 @@ const ExcelFilter: React.FC<ExcelFilterProps> = ({
|
|||
<Button
|
||||
variant="ghost"
|
||||
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)}
|
||||
>
|
||||
<ArrowUpDown className="h-4 w-4" />
|
||||
<ArrowUpDown className="h-3 w-3 text-gray-600" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<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
|
||||
React.useEffect(() => {
|
||||
console.log('🔄 Analítico - useEffect dos filtros chamado');
|
||||
|
|
@ -559,22 +571,66 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
|||
renderHeader: (params: any) => (
|
||||
<div className="flex items-center justify-between w-full">
|
||||
<span className="text-sm font-medium">{col.headerName}</span>
|
||||
<ExcelFilter
|
||||
column={col}
|
||||
data={data}
|
||||
onFilterChange={handleColumnFilterChange}
|
||||
onSortChange={handleColumnSortChange}
|
||||
currentFilter={columnFilters[col.field] || []}
|
||||
currentSort={columnSorts[col.field] || null}
|
||||
/>
|
||||
<div className="flex items-center">
|
||||
<ExcelFilter
|
||||
column={col}
|
||||
data={data}
|
||||
onFilterChange={handleColumnFilterChange}
|
||||
onSortChange={handleColumnSortChange}
|
||||
currentFilter={columnFilters[col.field] || []}
|
||||
currentSort={columnSorts[col.field] || null}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
}, [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(() => {
|
||||
if (!data || data.length === 0) {
|
||||
if (!sortedAndFilteredData || sortedAndFilteredData.length === 0) {
|
||||
return {
|
||||
valorRealizado: 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;
|
||||
return sum + (isNaN(valor) ? 0 : valor);
|
||||
}, 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);
|
||||
return sum + (isNaN(valor) ? 0 : valor);
|
||||
}, 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);
|
||||
return sum + (isNaN(valor) ? 0 : valor);
|
||||
}, 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);
|
||||
return sum + (isNaN(valor) ? 0 : valor);
|
||||
}, 0);
|
||||
|
|
@ -609,13 +665,13 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
|||
valorConfirmado,
|
||||
valorPago,
|
||||
};
|
||||
}, [data]);
|
||||
}, [sortedAndFilteredData]);
|
||||
|
||||
// Exportação XLSX
|
||||
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
|
||||
? new Date(item.data_competencia).toLocaleDateString("pt-BR")
|
||||
: "-",
|
||||
|
|
@ -684,7 +740,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
|||
|
||||
{/* Controls */}
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Input
|
||||
{/* <Input
|
||||
placeholder="Filtrar tudo..."
|
||||
value={globalFilter ?? ""}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
|
|
@ -699,7 +755,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
|||
>
|
||||
<Filter className="w-4 h-4 mr-2" />
|
||||
Filtros Avançados
|
||||
</Button>
|
||||
</Button> */}
|
||||
{globalFilter && (
|
||||
<Button
|
||||
variant="outline"
|
||||
|
|
@ -711,15 +767,26 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
|||
</Button>
|
||||
)}
|
||||
{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
|
||||
onClick={exportToExcel}
|
||||
variant="outline"
|
||||
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" />
|
||||
Exportar XLSX
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -778,12 +845,16 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
|||
|
||||
<div style={{ height: "calc(100% - 2rem)", width: "100%" }}>
|
||||
<DataGrid
|
||||
rows={data}
|
||||
key={`datagrid-${sortedAndFilteredData.length}-${Object.keys(columnFilters).length}`}
|
||||
rows={sortedAndFilteredData}
|
||||
columns={columns}
|
||||
loading={loading}
|
||||
disableRowSelectionOnClick
|
||||
density="compact"
|
||||
slots={{ toolbar: GridToolbar }}
|
||||
disableColumnMenu={true}
|
||||
disableColumnSorting={true}
|
||||
getRowId={(row) => row.id || `row-${row.recnum || Math.random()}`}
|
||||
initialState={{
|
||||
sorting: { sortModel: [{ field: "data_vencimento", sort: "desc" }] },
|
||||
}}
|
||||
|
|
@ -805,6 +876,54 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
|||
borderBottom: "1px solid #e5e7eb",
|
||||
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": {
|
||||
backgroundColor: "#f8fafc",
|
||||
borderTop: "1px solid #e5e7eb",
|
||||
|
|
|
|||
Loading…
Reference in New Issue