From 56eb6c2d7ab5d32794957e31d9d9b8cfae9f40ae Mon Sep 17 00:00:00 2001 From: Clara Ni Date: Wed, 12 Feb 2025 10:25:20 +0100 Subject: [PATCH 1/4] front: make searchOperationalPoints independent of state Signed-off-by: Clara Ni --- .../Map/Search/useSearchOperationalPoint.tsx | 135 +++++++++--------- 1 file changed, 67 insertions(+), 68 deletions(-) diff --git a/front/src/common/Map/Search/useSearchOperationalPoint.tsx b/front/src/common/Map/Search/useSearchOperationalPoint.tsx index 413d9edf79a..b4d1fb1014e 100644 --- a/front/src/common/Map/Search/useSearchOperationalPoint.tsx +++ b/front/src/common/Map/Search/useSearchOperationalPoint.tsx @@ -1,14 +1,10 @@ -import { useState, useEffect, useMemo } from 'react'; +import { useState, useEffect, useMemo, useCallback } from 'react'; import { isEmpty } from 'lodash'; import { useSelector } from 'react-redux'; import DPY_TO_MAS_OPERATIONAL_POINTS from 'assets/operationStudies/DPYToMASOperationalPoints'; -import { - type SearchQuery, - type SearchResultItemOperationalPoint, - osrdEditoastApi, -} from 'common/api/osrdEditoastApi'; +import { type SearchResultItemOperationalPoint, osrdEditoastApi } from 'common/api/osrdEditoastApi'; import { useInfraID } from 'common/osrdContext'; import { setFailure } from 'reducers/main'; import { getIsSuperUser } from 'reducers/user/userSelectors'; @@ -44,69 +40,70 @@ export default function useSearchOperationalPoint({ const debouncedSearchTerm = useDebounce(searchTerm, debounceDelay); const [postSearch] = osrdEditoastApi.endpoints.postSearch.useMutation(); - const searchOperationalPointsByTrigram = async ( - infraId: number, - dpyToMasOperationalpointsFilter: SearchQuery - ) => { - const shouldSearchByTrigram = - !Number.isInteger(+debouncedSearchTerm) && debouncedSearchTerm.length < 4; - - if (!shouldSearchByTrigram) return []; - - const payload = { - object: 'operationalpoint', - query: [ - 'and', - ['=i', ['trigram'], debouncedSearchTerm], - ['=', ['infra_id'], infraId], - dpyToMasOperationalpointsFilter, - ], - }; - try { - const results = (await postSearch({ - searchPayload: payload, - pageSize: 101, - }).unwrap()) as SearchResultItemOperationalPoint[]; - return results; - } catch (error) { - setFailure(castErrorToFailure(error)); - return []; - } - }; + const searchOperationalPointsByTrigram = useCallback( + async (searchQuery: string) => { + const shouldSearchByTrigram = !Number.isInteger(+searchQuery) && searchQuery.length < 4; + + if (!shouldSearchByTrigram || !infraID) return []; + + const dpyToMasOperationalpointsFilter = isStdcm && !isSuperUser ? DPY_TO_MAS_FILTER : true; + + const payload = { + object: 'operationalpoint', + query: [ + 'and', + ['=i', ['trigram'], searchQuery], + ['=', ['infra_id'], infraID], + dpyToMasOperationalpointsFilter, + ], + }; + try { + const results = (await postSearch({ + searchPayload: payload, + pageSize: 101, + }).unwrap()) as SearchResultItemOperationalPoint[]; + return results; + } catch (error) { + setFailure(castErrorToFailure(error)); + return []; + } + }, + [infraID, isStdcm, isSuperUser] + ); - const searchOperationalPoints = async () => { - if (infraID === undefined) return; - - const dpyToMasOperationalpointsFilter = isStdcm && !isSuperUser ? DPY_TO_MAS_FILTER : true; - - const trigramResults = await searchOperationalPointsByTrigram( - infraID, - dpyToMasOperationalpointsFilter - ); - - try { - const results = (await postSearch({ - searchPayload: { - object: 'operationalpoint', - query: [ - 'and', - [ - 'or', - ['search', ['name'], debouncedSearchTerm], - ['like', ['to_string', ['uic']], `%${debouncedSearchTerm}%`], + const searchOperationalPoints = useCallback( + async (searchQuery: string) => { + if (infraID === undefined) return []; + + const trigramResults = await searchOperationalPointsByTrigram(searchQuery); + + const dpyToMasOperationalpointsFilter = isStdcm && !isSuperUser ? DPY_TO_MAS_FILTER : true; + + try { + const results = (await postSearch({ + searchPayload: { + object: 'operationalpoint', + query: [ + 'and', + [ + 'or', + ['search', ['name'], searchQuery], + ['like', ['to_string', ['uic']], `%${searchQuery}%`], + ], + ['=', ['infra_id'], infraID], + dpyToMasOperationalpointsFilter, ], - ['=', ['infra_id'], infraID], - dpyToMasOperationalpointsFilter, - ], - }, - pageSize: 101, - }).unwrap()) as SearchResultItemOperationalPoint[]; - setSearchResults([...trigramResults, ...results]); - } catch (error) { - setFailure(castErrorToFailure(error)); - setSearchResults([]); - } - }; + }, + pageSize: 101, + }).unwrap()) as SearchResultItemOperationalPoint[]; + return [...trigramResults, ...results]; + } catch (error) { + setFailure(castErrorToFailure(error)); + return []; + } + }, + [infraID, isStdcm, isSuperUser] + ); const sortOperationalPoints = ( a: SearchResultItemOperationalPoint, @@ -172,7 +169,9 @@ export default function useSearchOperationalPoint({ useEffect(() => { if (debouncedSearchTerm) { - searchOperationalPoints(); + searchOperationalPoints(debouncedSearchTerm).then((results) => { + setSearchResults(results); + }); } else if (searchResults.length !== 0) { setSearchResults([]); } From ec495e9ed549a67769ef174b68087802b47c19c3 Mon Sep 17 00:00:00 2001 From: Clara Ni Date: Wed, 12 Feb 2025 10:35:15 +0100 Subject: [PATCH 2/4] front: remove sortedSearchResults in useSearchOperationalPoint Signed-off-by: Clara Ni --- .../StdcmForm/StdcmOperationalPoint.tsx | 7 +- .../Map/Search/MapSearchOperationalPoint.tsx | 12 +- .../Map/Search/useSearchOperationalPoint.tsx | 107 +++++++++--------- 3 files changed, 60 insertions(+), 66 deletions(-) diff --git a/front/src/applications/stdcm/components/StdcmForm/StdcmOperationalPoint.tsx b/front/src/applications/stdcm/components/StdcmForm/StdcmOperationalPoint.tsx index 723f2a46472..50c47785e4c 100644 --- a/front/src/applications/stdcm/components/StdcmForm/StdcmOperationalPoint.tsx +++ b/front/src/applications/stdcm/components/StdcmForm/StdcmOperationalPoint.tsx @@ -41,12 +41,7 @@ const StdcmOperationalPoint = ({ location, pathStepId, disabled }: StdcmOperatio const { t } = useTranslation('stdcm'); const dispatch = useAppDispatch(); - const { - searchTerm, - setSearchTerm, - sortedSearchResults: searchResults, - setSearchResults, - } = useSearchOperationalPoint({ + const { searchTerm, setSearchTerm, searchResults, setSearchResults } = useSearchOperationalPoint({ initialSearchTerm: location?.name, initialChCodeFilter: location?.secondary_code, isStdcm: true, diff --git a/front/src/common/Map/Search/MapSearchOperationalPoint.tsx b/front/src/common/Map/Search/MapSearchOperationalPoint.tsx index 7151b21a3cb..772bfab2047 100644 --- a/front/src/common/Map/Search/MapSearchOperationalPoint.tsx +++ b/front/src/common/Map/Search/MapSearchOperationalPoint.tsx @@ -28,7 +28,7 @@ const MapSearchOperationalPoint = ({ const { searchTerm, chCodeFilter, - sortedSearchResults, + searchResults, filteredAndSortedSearchResults, mainOperationalPointsOnly, setSearchTerm, @@ -57,7 +57,7 @@ const MapSearchOperationalPoint = ({ switch (event.key) { case 'ArrowUp': setSelectedResultIndex((prevIndex) => { - const newIndex = prevIndex > 0 ? prevIndex - 1 : sortedSearchResults.length - 1; + const newIndex = prevIndex > 0 ? prevIndex - 1 : searchResults.length - 1; const element = document.getElementById(`result-${newIndex}`); if (element) { element.scrollIntoView({ block: 'nearest', inline: 'nearest' }); @@ -67,7 +67,7 @@ const MapSearchOperationalPoint = ({ break; case 'ArrowDown': setSelectedResultIndex((prevIndex) => { - const newIndex = prevIndex < sortedSearchResults.length - 1 ? prevIndex + 1 : 0; + const newIndex = prevIndex < searchResults.length - 1 ? prevIndex + 1 : 0; const element = document.getElementById(`result-${newIndex}`); if (element) { element.scrollIntoView({ block: 'nearest', inline: 'nearest' }); @@ -133,15 +133,15 @@ const MapSearchOperationalPoint = ({

- {sortedSearchResults.length > 100 + {searchResults.length > 100 ? t('resultsCountTooMuch') : t('resultsCount', { count: filteredAndSortedSearchResults.length, })}

- {sortedSearchResults.length > 0 && - sortedSearchResults.length <= 100 && + {searchResults.length > 0 && + searchResults.length <= 100 && filteredAndSortedSearchResults.map((searchResult, index) => (