import { FilterFilled } from '@ant-design/icons'; import { Button, Checkbox, Input, Select, Space, Table } from 'antd'; import type { TableColumnsType } from 'antd'; import { useState } from 'react'; import { TableTag } from '../../components/TableTag/TableTag'; import type { ConsolidatedRowOut, CounterpartyType, OsvFilters } from '../../types/api'; import { counterpartyTypeLabel, osvPeriodLabel } from '../../utils/labels'; import { formatAmount } from '../../utils/money'; import { innCell, needsMapping } from './counterpartyMapping'; import { COUNTERPARTY_TYPES, counterpartyTypeBadge } from './counterpartyTypeBadge'; import type { OsvFilterDraft } from './osvFilterState'; type MoneyKey = 'opening_debit' | 'opening_credit' | 'turnover_debit' | 'turnover_credit' | 'closing_debit' | 'closing_credit'; const money = (key: MoneyKey, title: string) => ({ key, title, dataIndex: key, align: 'right' as const, width: 140, render: (v: string | null) => formatAmount(v, { zeroDash: true }), }); const group = (title: string, children: TableColumnsType): TableColumnsType[number] => ({ title, align: 'center', children, }); type Member = { id: string; name: string }; type OnChange = (patch: OsvFilterDraft) => void; /** Фильтр в заголовке колонки: `close` закрывает выпадающее окно после «Применить» / «Сбросить». */ type FilterProps = { onChange: OnChange; close: () => void }; function DropdownShell({ onApply, onReset, close, children, }: { onApply: () => void; onReset: () => void; close: () => void; children: React.ReactNode; }) { return (
{children}
); } function EntityFilter({ members, value, onChange, close }: FilterProps & { members: Member[]; value?: string }) { const [draft, setDraft] = useState(value); return ( onChange({ legal_entity_id: draft })} onReset={() => { setDraft(undefined); onChange({ legal_entity_id: undefined }); }}> setDraft(e.target.value)} onPressEnter={() => { onChange({ account_root: draft }); close(); }} /> ); } function CounterpartyFilter({ q, onChange, close }: FilterProps & { q?: string }) { const [draft, setDraft] = useState(q ?? ''); return ( onChange({ q: draft })} onReset={() => { setDraft(''); onChange({ q: '' }); }}> setDraft(e.target.value)} onPressEnter={() => { onChange({ q: draft }); close(); }} /> ); } // «Показать ЮЛ без ИНН» баннера — тот же фильтр `unmapped`; в макете [32-osv-no-inn] его воронка в колонке ИНН подсвечена function UnmappedFilter({ value, onChange, close }: FilterProps & { value: boolean }) { const [draft, setDraft] = useState(value); return ( onChange({ unmapped: draft })} onReset={() => { setDraft(false); onChange({ unmapped: false }); }}> setDraft(e.target.checked)}> Только без ИНН и без связи с ЮЛ ); } // API принимает один counterparty_type — поэтому выбор одного значения, а не галочки макета function CounterpartyTypeFilter({ type, onChange, close }: FilterProps & { type?: CounterpartyType }) { const [draft, setDraft] = useState(type); return ( onChange({ counterparty_type: draft })} onReset={() => { setDraft(undefined); onChange({ counterparty_type: undefined }); }}>