4.4 KiB
4.4 KiB
components/useTableFilters.tsx
// добавьте новую функцию для экспорта CSV
export function useTableFilters(schema: FieldInfo[]| null, initialData: unknown[] | null) {
const [filters, setFilters] = useState<FiltersState>({})
const [visibleColumns, setVisibleColumns] = useState<VisibilityState>({})
// Инициализация видимости колонок
useMemo(() => {
if (!schema){
return;
}
const initialVisibility: VisibilityState = {}
schema.forEach(field => {
initialVisibility[field.name] = true
})
setVisibleColumns(initialVisibility)
}, [schema])
// Обновление фильтров
const handleFilterChange = useCallback((name: string, filterPart: unknown) => {
setFilters(prev => ({
...prev,
[name]: {
...prev[name],
...filterPart
}
}))
}, [])
// Переключатель видимости колонки
const handleColumnToggle = useCallback((name: string) => {
setVisibleColumns(prev => ({
...prev,
[name]: !prev[name]
}))
}, [])
// Функция экспорта данных в CSV
const handleExportCSV = useCallback(() => {
if (!initialData || !schema || initialData.length === 0) {
alert('Нет данных для экспорта')
return
}
const visibleFields = schema.filter(field => visibleColumns[field.name])
const header = visibleFields.map(field => `"${field.title.replace(/"/g, '""')}"`).join(';')
const rows = initialData
.filter(item => schema.every(field => {
const value = item[field.name]
const filter = filters[field.name]
if (!filter) return true
if (field.type === 'string') {
if (filter.searchText) {
if (typeof value !== 'string') return false
if (!value.toLowerCase().includes(filter.searchText.toLowerCase())) return false
}
if (filter.exactMatch && filter.searchText) {
return value.toLowerCase() === filter.searchText.toLowerCase()
}
if (filter.empty !== undefined) {
const isEmpty = value === '' || value === null || value === undefined
if (filter.empty && !isEmpty) return false
if (filter.notEmpty && isEmpty) return false
}
} else if (field.format === 'date') {
const dateValue = new Date(value as string).getTime()
if (filter.fromDate) {
const fromTime = new Date(filter.fromDate).getTime()
if (dateValue < fromTime) return false
}
if (filter.toDate) {
const toTime = new Date(filter.toDate).getTime()
if (dateValue > toTime) return false
}
} else if (field.type === 'number') {
const numValue = Number(value)
if (filter.gte !== undefined && numValue < filter.gte) return false
if (filter.lte !== undefined && numValue > filter.lte) return false
}
return true
}))
.map(item => {
const row = visibleFields.map(field => {
const val = item[field.name]
// Обработка null/undefined
const strVal = val !== undefined && val !== null ? String(val) : ''
// Экранирование кавычек
return `"${strVal.replace(/"/g, '""')}"`
})
return row.join(';')
})
const csvContent = [header, ...rows].join('\n')
// Создаем ссылку для скачивания
const blob = new Blob([csvContent], { type: 'text/csv' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = 'export.csv'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(url)
}, [initialData, schema, filters, visibleColumns])
return {
filters,
setFilters,
visibleColumns,
setVisibleColumns,
handleFilterChange,
handleColumnToggle,
filteredData,
handleExportCSV // добавьте сюда
}
}
Ваш файл, где вызывается handleExport (примеры использования)
const {
filters,
handleFilterChange,
visibleColumns,
handleColumnToggle,
filteredData,
handleExportCSV // новая функция
} = useTableFilters(schema, dataPage.items)
const handleExport = async () => {
handleExportCSV()
}