Files
G4F/StaticHelper/source/old_input.md

5.7 KiB
Raw Blame History


import { useState, useMemo, useCallback } from 'react'
import { FieldInfo } from '../types/common'
import {FiltersState, VisibilityState} from "../types/filters.ts";



/**
 * Хук для управления фильтрами и видимостью колонок таблицы.
 * @param schema Схема полей таблицы.
 * @param initialData
 * @returns Объекты состояния фильтров и видимости, а также функции для их изменения.
 */
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]
    }))
  }, [])

  // Логика фильтрации данных, вынесенная из компонента
  const filteredData = useMemo(() => {
    if (!initialData || !schema){
      return ;
    }
    return initialData.filter(item => {
      return 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
      })
    })
  }, [initialData, filters, schema])

  return {
    filters,
    setFilters,
    visibleColumns,
    setVisibleColumns,
    handleFilterChange,
    handleColumnToggle,
    filteredData
  }
}


export function FilteredTable({ schema, filteredData, visibleColumns}: FilteredTableProps) {

    return (
        <div className="filtered-table">


            <table className="filtered-table-main" style={{ overflowX: 'auto', display: 'block' }}>
                <thead>
                <tr>
                    {schema.map(
                        (field) =>
                            visibleColumns[field.name] && (
                                <th key={field.name} className="column-header">
                                    {field.title}
                                </th>
                            )
                    )}
                </tr>
                </thead>
                <tbody>
                {filteredData.length > 0 ? (
                    filteredData.map((item) => (
                        <tr key={(item as {id: number}).id}>
                            {schema.map(
                                (field) =>
                                    visibleColumns[field.name] && (
                                        <td key={field.name} className="data-cell">
                                            {item[field.name] ?? "-"}
                                        </td>
                                    )
                            )}
                        </tr>
                    ))
                ) : (
                    <tr>
                        <td colSpan={schema.length} className="no-data">
                            Нет данных для отображения
                        </td>
                    </tr>
                )}
                </tbody>
            </table>
        </div>
    )
}

const {
        filters,
        handleFilterChange,
        visibleColumns,
        handleColumnToggle,
        filteredData
    } = useTableFilters(schema, dataPage.items)

    
    const handleExport = async () => {
        if (!filteredData || filteredData.length === 0) {
            alert('Нет данных для экспорта')
            return
        }


        const blob = new Blob([buffer], {
            type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        })
        saveAs(blob, "Отчёт.")
    };

в handleExport сохранять csv