From a2b132e9dc7b305f0b2a609f776839365c7814f8 Mon Sep 17 00:00:00 2001 From: PotapovaA Date: Mon, 9 Nov 2026 14:13:23 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BA=D1=80=D0=B5=D1=81=D1=82=D0=B8=D0=BA=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=BE=D1=87=D0=B8=D1=81=D1=82=D0=BA=D0=B8?= =?UTF-8?q?=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B8=20=D0=BF=D0=BE=D0=B8?= =?UTF-8?q?=D1=81=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RealtimeTable/RealtimeTable.jsx | 19 ++++++++-- .../SettingPanel/SettingPanel.jsx | 7 ++-- web/src/components/common/SearchComponent.jsx | 35 +++++++++++++++++-- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/web/src/components/RealtimeTable/RealtimeTable.jsx b/web/src/components/RealtimeTable/RealtimeTable.jsx index 1ac2247..6f294c1 100644 --- a/web/src/components/RealtimeTable/RealtimeTable.jsx +++ b/web/src/components/RealtimeTable/RealtimeTable.jsx @@ -107,6 +107,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => { editingCells: dataEditingCells, } = useRealtimeData(formId, sheetName, direction, formType, year); const [globalFilter, setGlobalFilter] = useState(''); + const [searchInput, setSearchInput] = useState(''); const [searchMatchIndex, setSearchMatchIndex] = useState(-1); const [activeSearchMatch, setActiveSearchMatch] = useState(null); const [pendingSearchDirection, setPendingSearchDirection] = useState(0); @@ -166,6 +167,10 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => { ); useEffect(() => () => handleGlobalFilterChange.clear(), [handleGlobalFilterChange]); + const handleSearchInputChange = useCallback((value) => { + setSearchInput(value); + handleGlobalFilterChange(value); + }, [handleGlobalFilterChange]); const { updateCell: contextUpdateCell, @@ -803,6 +808,14 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => { const handleSearchNext = useCallback(() => navigateToSearchMatch(1), [navigateToSearchMatch]); const handleSearchPrevious = useCallback(() => navigateToSearchMatch(-1), [navigateToSearchMatch]); + const handleClearSearch = useCallback(() => { + handleGlobalFilterChange.clear(); + setPendingSearchDirection(0); + setSearchInput(''); + setGlobalFilter(''); + setSearchMatchIndex(-1); + setActiveSearchMatch(null); + }, [handleGlobalFilterChange]); const handleSearchKeyDown = useCallback( (event) => { @@ -814,6 +827,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => { if (normalizeFilterValue(inputValue) !== normalizeFilterValue(globalFilter)) { handleGlobalFilterChange.clear(); + setSearchInput(inputValue); setGlobalFilter(inputValue); setPendingSearchDirection(direction); return; @@ -1070,8 +1084,9 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => { onChangeSizeMult={setSizeMult} denomination={denomination} onChangeDenomination={setTableDenomination} - onGlobalFilterChange={handleGlobalFilterChange} - globalFilter={globalFilter} + onGlobalFilterChange={handleSearchInputChange} + onClearSearch={handleClearSearch} + globalFilter={searchInput} onSearchKeyDown={handleSearchKeyDown} onSearchNext={handleSearchNext} onSearchPrevious={handleSearchPrevious} diff --git a/web/src/components/RealtimeTable/SettingPanel/SettingPanel.jsx b/web/src/components/RealtimeTable/SettingPanel/SettingPanel.jsx index 0ffc992..e53af3e 100644 --- a/web/src/components/RealtimeTable/SettingPanel/SettingPanel.jsx +++ b/web/src/components/RealtimeTable/SettingPanel/SettingPanel.jsx @@ -1,3 +1,4 @@ +import FilterAltOutlinedIcon from '@mui/icons-material/FilterAltOutlined'; import { Divider, IconButton, Stack, Tooltip, Typography } from '@mui/material'; import { memo, useCallback, useMemo, useState } from 'react'; import { FORM_TYPE_OPTIONS } from '../../../constants/constants'; @@ -18,7 +19,6 @@ import { Program, Project, RemoveLine, - Search, VisibleExpenseItems, } from '../../common/icons/icons'; import { collectLeafColumns } from '../utils/columnUtils'; @@ -76,6 +76,7 @@ const SettingPanel = ({ columnsCurStage, onChangeSizeMult, onGlobalFilterChange, + onClearSearch, globalFilter, onSearchKeyDown, onSearchNext, @@ -283,6 +284,8 @@ const SettingPanel = ({ - + diff --git a/web/src/components/common/SearchComponent.jsx b/web/src/components/common/SearchComponent.jsx index 21394a9..10acd68 100644 --- a/web/src/components/common/SearchComponent.jsx +++ b/web/src/components/common/SearchComponent.jsx @@ -1,8 +1,19 @@ -import { InputAdornment, TextField } from '@mui/material'; +import CloseIcon from '@mui/icons-material/Close'; +import { IconButton, InputAdornment, TextField } from '@mui/material'; import { memo, useEffect, useRef, useState } from 'react'; import { Search } from './icons/icons'; -function SearchComponent({ placeholder = 'Поиск...', value = '', onChange, debounceMs = 0, height = '2rem', sx: sxProp, ...rest }) { +function SearchComponent({ + placeholder = 'Поиск...', + value = '', + onChange, + onClear, + clearable = false, + debounceMs = 0, + height = '2rem', + sx: sxProp, + ...rest +}) { const [inputValue, setInputValue] = useState(value); const onChangeRef = useRef(onChange); @@ -32,6 +43,11 @@ function SearchComponent({ placeholder = 'Поиск...', value = '', onChange, } }; + const handleClear = () => { + setInputValue(''); + (onClear ?? onChange)(''); + }; + return ( ), + ...(clearable && inputValue + ? { + endAdornment: ( + + event.preventDefault()} + onClick={handleClear}> + + + + ), + } + : {}), }, }} />