diff --git a/src/components/FunctionalArea/TopBar/SearchBar/SearchBar.component.tsx b/src/components/FunctionalArea/TopBar/SearchBar/SearchBar.component.tsx index 05231d6f5f479ae6cdf8bf1d21a037481cf99906..294f6fb62710dd579c02966cdc090b35b872920c 100644 --- a/src/components/FunctionalArea/TopBar/SearchBar/SearchBar.component.tsx +++ b/src/components/FunctionalArea/TopBar/SearchBar/SearchBar.component.tsx @@ -5,12 +5,14 @@ import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { isPendingSearchStatusSelector, perfectMatchSelector, + searchInputSelector, } from '@/redux/search/search.selectors'; +import { setSearchInput } from '@/redux/search/search.slice'; import { getSearchData } from '@/redux/search/search.thunks'; import Image from 'next/image'; -import { ChangeEvent, KeyboardEvent, useEffect, useState } from 'react'; -import { useSelector } from 'react-redux'; import { useRouter } from 'next/router'; +import { ChangeEvent, KeyboardEvent } from 'react'; +import { useSelector } from 'react-redux'; import { getDefaultSearchTab, getSearchValuesArrayAndTrimToSeven } from './SearchBar.utils'; const ENTER_KEY_CODE = 'Enter'; @@ -19,24 +21,19 @@ export const SearchBar = (): JSX.Element => { const isPendingSearchStatus = useSelector(isPendingSearchStatusSelector); const isDrawerOpen = useSelector(isDrawerOpenSelector); const isPerfectMatch = useSelector(perfectMatchSelector); - const [searchValue, setSearchValue] = useState<string>(''); + const searchValue = useSelector(searchInputSelector); const dispatch = useAppDispatch(); const { query } = useRouter(); - useEffect(() => { - if (!searchValue && query.searchValue) { - setSearchValue(String(query.searchValue)); - } - }, [searchValue, query]); - const openSearchDrawerIfClosed = (defaultSearchTab: string): void => { if (!isDrawerOpen) { dispatch(openSearchDrawerWithSelectedTab(defaultSearchTab)); } }; - const onSearchChange = (event: ChangeEvent<HTMLInputElement>): void => - setSearchValue(event.target.value); + const onSearchChange = (event: ChangeEvent<HTMLInputElement>): void => { + dispatch(setSearchInput(event.target.value)); + }; const onSearchClick = (): void => { const searchValues = getSearchValuesArrayAndTrimToSeven(searchValue); diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts index 6580ded53c7165fd1a104b3e10344e3ce0762d09..0c2079d04320fc6daf02b194402aa5b2bbddb32b 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts @@ -1,5 +1,7 @@ /* eslint-disable no-magic-numbers */ import { searchedBioEntitesSelectorOfCurrentMap } from '@/redux/bioEntity/bioEntity.selectors'; +import { searchedChemicalsBioEntitesOfCurrentMapSelector } from '@/redux/chemicals/chemicals.selectors'; +import { searchedDrugsBioEntitesOfCurrentMapSelector } from '@/redux/drugs/drugs.selectors'; import { usePointToProjection } from '@/utils/map/usePointToProjection'; import BaseLayer from 'ol/layer/Base'; import VectorLayer from 'ol/layer/Vector'; @@ -11,11 +13,17 @@ import { getBioEntitiesFeatures } from './getBioEntitiesFeatures'; export const useOlMapPinsLayer = (): BaseLayer => { const pointToProjection = usePointToProjection(); const contentBioEntites = useSelector(searchedBioEntitesSelectorOfCurrentMap); + const chemicalsBioEntities = useSelector(searchedChemicalsBioEntitesOfCurrentMapSelector); + const drugsBioEntities = useSelector(searchedDrugsBioEntitesOfCurrentMapSelector); const bioEntityFeatures = useMemo( () => - [getBioEntitiesFeatures(contentBioEntites, { pointToProjection, type: 'bioEntity' })].flat(), - [contentBioEntites, pointToProjection], + [ + getBioEntitiesFeatures(contentBioEntites, { pointToProjection, type: 'bioEntity' }), + getBioEntitiesFeatures(chemicalsBioEntities, { pointToProjection, type: 'chemicals' }), + getBioEntitiesFeatures(drugsBioEntities, { pointToProjection, type: 'drugs' }), + ].flat(), + [contentBioEntites, drugsBioEntities, chemicalsBioEntities, pointToProjection], ); const vectorSource = useMemo(() => { diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.test.ts index f188b5fc5828b89f43f98e6f590a05da7c66bbbd..2cb880c6e384ee7522d63240a0467be5cbd650b8 100644 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.test.ts @@ -1,4 +1,3 @@ -import { FIRST } from '@/constants/common'; import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener'; import { handleDataReset } from './handleDataReset'; @@ -6,10 +5,17 @@ describe('handleDataReset', () => { const { store } = getReduxStoreWithActionsListener(); const { dispatch } = store; - it('should dispatch resetReactionsData action', () => { + it('should dispatch reset actions', () => { dispatch(handleDataReset); const actions = store.getActions(); - expect(actions[FIRST].type).toBe('reactions/resetReactionsData'); + const actionsTypes = [ + 'reactions/resetReactionsData', + 'search/clearSearchData', + 'drugs/clearDrugsData', + 'chemicals/clearChemicalsData', + ]; + + expect(actions.map(a => a.type)).toStrictEqual(actionsTypes); }); }); diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.ts index 4d3e1d6d526ee22725aff6b92ccbf273eec5ff79..1bc13bd160a0514668f7faf05a7224e7315ce3b7 100644 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.ts +++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.ts @@ -1,6 +1,12 @@ +import { clearChemicalsData } from '@/redux/chemicals/chemicals.slice'; +import { clearDrugsData } from '@/redux/drugs/drugs.slice'; import { resetReactionsData } from '@/redux/reactions/reactions.slice'; +import { clearSearchData } from '@/redux/search/search.slice'; import { AppDispatch } from '@/redux/store'; export const handleDataReset = (dispatch: AppDispatch): void => { dispatch(resetReactionsData()); + dispatch(clearSearchData()); + dispatch(clearDrugsData()); + dispatch(clearChemicalsData()); }; diff --git a/src/models/targetSchema.ts b/src/models/targetSchema.ts index bda0bfcaac652d98c5086c59a11687f4e792e1d8..015626e16f4e06ce2276a5e9a597701b63c7a031 100644 --- a/src/models/targetSchema.ts +++ b/src/models/targetSchema.ts @@ -1,6 +1,6 @@ import { z } from 'zod'; +import { bioEntitySchema } from './bioEntitySchema'; import { referenceSchema } from './referenceSchema'; -import { targetElementSchema } from './targetElementSchema'; import { targetParticipantSchema } from './targetParticipantSchema'; export const targetSchema = z.object({ @@ -9,7 +9,7 @@ export const targetSchema = z.object({ /** list of target references */ references: z.array(referenceSchema), /** list of elements on the map associated with this target */ - targetElements: z.array(targetElementSchema), + targetElements: z.array(bioEntitySchema), /** list of identifiers associated with this target */ targetParticipants: z.array(targetParticipantSchema), }); diff --git a/src/redux/chemicals/chemicals.reducers.test.ts b/src/redux/chemicals/chemicals.reducers.test.ts index 0a990dc596369385d33b4149fe72e5212a5726cb..59a87b20f784e059d63c5ea030274275b2562a6b 100644 --- a/src/redux/chemicals/chemicals.reducers.test.ts +++ b/src/redux/chemicals/chemicals.reducers.test.ts @@ -1,17 +1,17 @@ +import { DEFAULT_ERROR } from '@/constants/errors'; import { chemicalsFixture } from '@/models/fixtures/chemicalsFixture'; import { apiPath } from '@/redux/apiPath'; -import { DEFAULT_ERROR } from '@/constants/errors'; import { ToolkitStoreWithSingleSlice, createStoreInstanceUsingSliceReducer, } from '@/utils/createStoreInstanceUsingSliceReducer'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; +import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; import { HttpStatusCode } from 'axios'; import chemicalsReducer from './chemicals.slice'; import { getChemicals } from './chemicals.thunks'; import { ChemicalsState } from './chemicals.types'; -const mockedAxiosClient = mockNetworkResponse(); +const mockedAxiosClient = mockNetworkNewAPIResponse(); const SEARCH_QUERY = 'Corticosterone'; const INITIAL_STATE: ChemicalsState = { diff --git a/src/redux/chemicals/chemicals.reducers.ts b/src/redux/chemicals/chemicals.reducers.ts index 5f7603f6ad3ffe21ac980e9c85b4f4c0eaa7b076..1034ead8fca8535dae1481714de1e1db14644734 100644 --- a/src/redux/chemicals/chemicals.reducers.ts +++ b/src/redux/chemicals/chemicals.reducers.ts @@ -1,5 +1,5 @@ -import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; import { DEFAULT_ERROR } from '@/constants/errors'; +import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; import { getChemicals, getMultiChemicals } from './chemicals.thunks'; import { ChemicalsState } from './chemicals.types'; @@ -43,3 +43,8 @@ export const getMultiChemicalsReducer = ( // TODO: error management to be discussed in the team }); }; + +export const clearChemicalsDataReducer = (state: ChemicalsState): void => { + state.data = []; + state.loading = 'idle'; +}; diff --git a/src/redux/chemicals/chemicals.selectors.ts b/src/redux/chemicals/chemicals.selectors.ts index 09f59c724e9b9b47567276f8c0273ad1562ab828..f2d10808719aa1f04fac0a93bba36bc68812407d 100644 --- a/src/redux/chemicals/chemicals.selectors.ts +++ b/src/redux/chemicals/chemicals.selectors.ts @@ -1,9 +1,10 @@ import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; import { rootSelector } from '@/redux/root/root.selectors'; -import { Chemical } from '@/types/models'; -import { createSelector } from '@reduxjs/toolkit'; import { MultiSearchData } from '@/types/fetchDataState'; +import { BioEntity, Chemical } from '@/types/models'; +import { createSelector } from '@reduxjs/toolkit'; import { currentSelectedSearchElement } from '../drawer/drawer.selectors'; +import { currentModelIdSelector } from '../models/models.selectors'; export const chemicalsSelector = createSelector(rootSelector, state => state.chemicals); @@ -16,6 +17,24 @@ export const chemicalsForSelectedSearchElementSelector = createSelector( ), ); +export const searchedChemicalsBioEntitesOfCurrentMapSelector = createSelector( + chemicalsSelector, + currentSelectedSearchElement, + currentModelIdSelector, + (chemicalsState, currentSearchElement, currentModelId): BioEntity[] => { + return (chemicalsState?.data || []) + .filter(({ searchQueryElement }) => + currentSearchElement ? searchQueryElement === currentSearchElement : true, + ) + .map(({ data }) => data || []) + .flat() + .map(({ targets }) => targets.map(({ targetElements }) => targetElements)) + .flat() + .flat() + .filter(bioEntity => bioEntity.model === currentModelId); + }, +); + export const loadingChemicalsStatusSelector = createSelector( chemicalsForSelectedSearchElementSelector, state => state?.loading, diff --git a/src/redux/chemicals/chemicals.slice.ts b/src/redux/chemicals/chemicals.slice.ts index 2528d4f2aa642b003f5d41ee746b50f343cf12d8..6de994ae33b31d87b6c4a22ad209fb7b1c1bdcba 100644 --- a/src/redux/chemicals/chemicals.slice.ts +++ b/src/redux/chemicals/chemicals.slice.ts @@ -1,6 +1,10 @@ import { ChemicalsState } from '@/redux/chemicals/chemicals.types'; import { createSlice } from '@reduxjs/toolkit'; -import { getChemicalsReducer, getMultiChemicalsReducer } from './chemicals.reducers'; +import { + clearChemicalsDataReducer, + getChemicalsReducer, + getMultiChemicalsReducer, +} from './chemicals.reducers'; const initialState: ChemicalsState = { data: [], @@ -11,11 +15,15 @@ const initialState: ChemicalsState = { export const chemicalsSlice = createSlice({ name: 'chemicals', initialState, - reducers: {}, + reducers: { + clearChemicalsData: clearChemicalsDataReducer, + }, extraReducers: builder => { getChemicalsReducer(builder); getMultiChemicalsReducer(builder); }, }); +export const { clearChemicalsData } = chemicalsSlice.actions; + export default chemicalsSlice.reducer; diff --git a/src/redux/chemicals/chemicals.thunks.test.ts b/src/redux/chemicals/chemicals.thunks.test.ts index 93945477c94dd25afcf561a04ac592ce57d12f2e..88926792155e930d39ae396f25733fcb4e1fe099 100644 --- a/src/redux/chemicals/chemicals.thunks.test.ts +++ b/src/redux/chemicals/chemicals.thunks.test.ts @@ -4,13 +4,13 @@ import { ToolkitStoreWithSingleSlice, createStoreInstanceUsingSliceReducer, } from '@/utils/createStoreInstanceUsingSliceReducer'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; +import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; import { HttpStatusCode } from 'axios'; import chemicalsReducer from './chemicals.slice'; import { getChemicals } from './chemicals.thunks'; import { ChemicalsState } from './chemicals.types'; -const mockedAxiosClient = mockNetworkResponse(); +const mockedAxiosClient = mockNetworkNewAPIResponse(); const SEARCH_QUERY = 'Corticosterone'; describe('chemicals thunks', () => { diff --git a/src/redux/chemicals/chemicals.thunks.ts b/src/redux/chemicals/chemicals.thunks.ts index 848ee24d55f5d52d7f4cd4b929fdfc296a513bec..0afc94db5f8f686b845e8e514082866b18219908 100644 --- a/src/redux/chemicals/chemicals.thunks.ts +++ b/src/redux/chemicals/chemicals.thunks.ts @@ -1,6 +1,6 @@ import { chemicalSchema } from '@/models/chemicalSchema'; import { apiPath } from '@/redux/apiPath'; -import { axiosInstance } from '@/services/api/utils/axiosInstance'; +import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance'; import { Chemical } from '@/types/models'; import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; import { createAsyncThunk } from '@reduxjs/toolkit'; @@ -9,7 +9,7 @@ import { z } from 'zod'; export const getChemicals = createAsyncThunk( 'project/getChemicals', async (searchQuery: string): Promise<Chemical[] | undefined> => { - const response = await axiosInstance.get<Chemical[]>( + const response = await axiosInstanceNewAPI.get<Chemical[]>( apiPath.getChemicalsStringWithQuery(searchQuery), ); diff --git a/src/redux/drugs/drugs.reducers.test.ts b/src/redux/drugs/drugs.reducers.test.ts index b0db33c10f7deba0eee6e2a617a310473d49e154..3ad034db1d614a691017c221f541dfc39e4b6fcf 100644 --- a/src/redux/drugs/drugs.reducers.test.ts +++ b/src/redux/drugs/drugs.reducers.test.ts @@ -1,17 +1,17 @@ -import { HttpStatusCode } from 'axios'; +import { DEFAULT_ERROR } from '@/constants/errors'; import { drugsFixture } from '@/models/fixtures/drugFixtures'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; +import { apiPath } from '@/redux/apiPath'; import { ToolkitStoreWithSingleSlice, createStoreInstanceUsingSliceReducer, } from '@/utils/createStoreInstanceUsingSliceReducer'; -import { DEFAULT_ERROR } from '@/constants/errors'; -import { apiPath } from '@/redux/apiPath'; -import { getDrugs } from './drugs.thunks'; +import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; +import { HttpStatusCode } from 'axios'; import drugsReducer from './drugs.slice'; +import { getDrugs } from './drugs.thunks'; import { DrugsState } from './drugs.types'; -const mockedAxiosClient = mockNetworkResponse(); +const mockedAxiosClient = mockNetworkNewAPIResponse(); const SEARCH_QUERY = 'aspirin'; const INITIAL_STATE: DrugsState = { diff --git a/src/redux/drugs/drugs.reducers.ts b/src/redux/drugs/drugs.reducers.ts index 4dcd353fb5b7333e0abcedf15d41980ed08fff36..a3f834644c319dc7f31a40a7b318c30ef8f57b53 100644 --- a/src/redux/drugs/drugs.reducers.ts +++ b/src/redux/drugs/drugs.reducers.ts @@ -1,7 +1,7 @@ import { DEFAULT_ERROR } from '@/constants/errors'; import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; -import { DrugsState } from './drugs.types'; import { getDrugs, getMultiDrugs } from './drugs.thunks'; +import { DrugsState } from './drugs.types'; export const getDrugsReducer = (builder: ActionReducerMapBuilder<DrugsState>): void => { builder.addCase(getDrugs.pending, (state, action) => { @@ -41,3 +41,8 @@ export const getMultiDrugsReducer = (builder: ActionReducerMapBuilder<DrugsState // TODO: error management to be discussed in the team }); }; + +export const clearDrugsDataReducer = (state: DrugsState): void => { + state.data = []; + state.loading = 'idle'; +}; diff --git a/src/redux/drugs/drugs.selectors.ts b/src/redux/drugs/drugs.selectors.ts index 91cd36888dc7af0eeb1914ff2cefa38a745a6662..6790c081e1303eaec49e5b8dc3045ba4a8d4a0be 100644 --- a/src/redux/drugs/drugs.selectors.ts +++ b/src/redux/drugs/drugs.selectors.ts @@ -1,9 +1,10 @@ import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; import { rootSelector } from '@/redux/root/root.selectors'; -import { createSelector } from '@reduxjs/toolkit'; import { MultiSearchData } from '@/types/fetchDataState'; -import { Drug } from '@/types/models'; +import { BioEntity, Drug } from '@/types/models'; +import { createSelector } from '@reduxjs/toolkit'; import { currentSelectedSearchElement } from '../drawer/drawer.selectors'; +import { currentModelIdSelector } from '../models/models.selectors'; export const drugsSelector = createSelector(rootSelector, state => state.drugs); @@ -29,3 +30,21 @@ export const numberOfDrugsSelector = createSelector( return state.data.length && state?.data.map(e => e.targets.length)?.reduce((a, b) => a + b); }, ); + +export const searchedDrugsBioEntitesOfCurrentMapSelector = createSelector( + drugsSelector, + currentSelectedSearchElement, + currentModelIdSelector, + (drugsState, currentSearchElement, currentModelId): BioEntity[] => { + return (drugsState?.data || []) + .filter(({ searchQueryElement }) => + currentSearchElement ? searchQueryElement === currentSearchElement : true, + ) + .map(({ data }) => data || []) + .flat() + .map(({ targets }) => targets.map(({ targetElements }) => targetElements)) + .flat() + .flat() + .filter(bioEntity => bioEntity.model === currentModelId); + }, +); diff --git a/src/redux/drugs/drugs.slice.ts b/src/redux/drugs/drugs.slice.ts index 5d1a16e7379ef4019d52a741271b52438ea52a68..d7e8660d14e8f66967e094ecadb1dfb73a05479c 100644 --- a/src/redux/drugs/drugs.slice.ts +++ b/src/redux/drugs/drugs.slice.ts @@ -1,6 +1,6 @@ -import { createSlice } from '@reduxjs/toolkit'; import { DrugsState } from '@/redux/drugs/drugs.types'; -import { getDrugsReducer, getMultiDrugsReducer } from './drugs.reducers'; +import { createSlice } from '@reduxjs/toolkit'; +import { clearDrugsDataReducer, getDrugsReducer, getMultiDrugsReducer } from './drugs.reducers'; const initialState: DrugsState = { data: [], @@ -11,11 +11,15 @@ const initialState: DrugsState = { export const drugsSlice = createSlice({ name: 'drugs', initialState, - reducers: {}, + reducers: { + clearDrugsData: clearDrugsDataReducer, + }, extraReducers: builder => { getDrugsReducer(builder); getMultiDrugsReducer(builder); }, }); +export const { clearDrugsData } = drugsSlice.actions; + export default drugsSlice.reducer; diff --git a/src/redux/drugs/drugs.thunks.test.ts b/src/redux/drugs/drugs.thunks.test.ts index 514ffccfe9f8b57d1f698a98e48640f35186c130..bb18ddf134667e1c33c4d6d29388a511df9ecc97 100644 --- a/src/redux/drugs/drugs.thunks.test.ts +++ b/src/redux/drugs/drugs.thunks.test.ts @@ -1,16 +1,16 @@ -import { HttpStatusCode } from 'axios'; import { drugsFixture } from '@/models/fixtures/drugFixtures'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; +import { apiPath } from '@/redux/apiPath'; import { ToolkitStoreWithSingleSlice, createStoreInstanceUsingSliceReducer, } from '@/utils/createStoreInstanceUsingSliceReducer'; -import { apiPath } from '@/redux/apiPath'; -import { getDrugs } from './drugs.thunks'; +import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; +import { HttpStatusCode } from 'axios'; import drugsReducer from './drugs.slice'; +import { getDrugs } from './drugs.thunks'; import { DrugsState } from './drugs.types'; -const mockedAxiosClient = mockNetworkResponse(); +const mockedAxiosClient = mockNetworkNewAPIResponse(); const SEARCH_QUERY = 'aspirin'; describe('drugs thunks', () => { diff --git a/src/redux/drugs/drugs.thunks.ts b/src/redux/drugs/drugs.thunks.ts index 1f3258be999a25a219bf55ebbc01513a43cb6c8a..30074e33d6ee751c2f8886e3793050ba84e1d41f 100644 --- a/src/redux/drugs/drugs.thunks.ts +++ b/src/redux/drugs/drugs.thunks.ts @@ -1,15 +1,17 @@ -import { z } from 'zod'; -import { createAsyncThunk } from '@reduxjs/toolkit'; -import { axiosInstance } from '@/services/api/utils/axiosInstance'; -import { Drug } from '@/types/models'; import { drugSchema } from '@/models/drugSchema'; -import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; import { apiPath } from '@/redux/apiPath'; +import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance'; +import { Drug } from '@/types/models'; +import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; +import { createAsyncThunk } from '@reduxjs/toolkit'; +import { z } from 'zod'; export const getDrugs = createAsyncThunk( 'project/getDrugs', async (searchQuery: string): Promise<Drug[] | undefined> => { - const response = await axiosInstance.get<Drug[]>(apiPath.getDrugsStringWithQuery(searchQuery)); + const response = await axiosInstanceNewAPI.get<Drug[]>( + apiPath.getDrugsStringWithQuery(searchQuery), + ); const isDataValid = validateDataUsingZodSchema(response.data, z.array(drugSchema)); diff --git a/src/redux/search/search.constants.ts b/src/redux/search/search.constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..9a7afe4d6738df81e0fa0f8a29f10fbac28991a2 --- /dev/null +++ b/src/redux/search/search.constants.ts @@ -0,0 +1,8 @@ +import { SearchState } from './search.types'; + +export const SEARCH_INITIAL_STATE: SearchState = { + searchInput: '', + searchValue: [''], + perfectMatch: false, + loading: 'idle', +}; diff --git a/src/redux/search/search.mock.ts b/src/redux/search/search.mock.ts index 16f5498f21913e2f8baac144f58daf87ae1c5551..d5e7cc4a437b53b0c3b19d14de65cd1a001faee8 100644 --- a/src/redux/search/search.mock.ts +++ b/src/redux/search/search.mock.ts @@ -1,6 +1,7 @@ import { SearchState } from './search.types'; export const SEARCH_STATE_INITIAL_MOCK: SearchState = { + searchInput: '', searchValue: [''], perfectMatch: false, loading: 'idle', diff --git a/src/redux/search/search.reducers.test.ts b/src/redux/search/search.reducers.test.ts index 51bab3d5ae4226133bdeefd65485c77190c0b64d..76a76b3c7a753ac1a1e2391358f094b7db94a9a2 100644 --- a/src/redux/search/search.reducers.test.ts +++ b/src/redux/search/search.reducers.test.ts @@ -9,6 +9,7 @@ import searchReducer, { setPerfectMatch } from './search.slice'; const SEARCH_QUERY = ['Corticosterone']; const INITIAL_STATE: SearchState = { + searchInput: '', searchValue: [''], perfectMatch: false, loading: 'idle', diff --git a/src/redux/search/search.reducers.ts b/src/redux/search/search.reducers.ts index d4e555cda88fb3bf7281cfb9f5be985efed1a56e..4835372100f606dfe1db39d3aa690791e1793444 100644 --- a/src/redux/search/search.reducers.ts +++ b/src/redux/search/search.reducers.ts @@ -1,10 +1,16 @@ // updating state import { getSearchData } from '@/redux/search/search.thunks'; -import { SearchState, SetPerfectMatchAction } from '@/redux/search/search.types'; +import { + SearchState, + SetPerfectMatchAction, + SetSearchInputAction, +} from '@/redux/search/search.types'; import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; +import { SEARCH_INITIAL_STATE } from './search.constants'; export const getSearchDataReducer = (builder: ActionReducerMapBuilder<SearchState>): void => { builder.addCase(getSearchData.pending, (state, action) => { + state.searchInput = action.meta.arg.searchQueries.join(';'); state.searchValue = action.meta.arg.searchQueries; state.perfectMatch = action.meta.arg.isPerfectMatch; state.loading = 'pending'; @@ -21,3 +27,12 @@ export const getSearchDataReducer = (builder: ActionReducerMapBuilder<SearchStat export const setPerfectMatchReducer = (state: SearchState, action: SetPerfectMatchAction): void => { state.perfectMatch = action.payload; }; + +export const setSearchInputReducer = (state: SearchState, action: SetSearchInputAction): void => { + state.searchInput = action.payload; +}; + +export const clearSearchDataReducer = (state: SearchState): void => { + state.searchValue = SEARCH_INITIAL_STATE.searchValue; + state.loading = SEARCH_INITIAL_STATE.loading; +}; diff --git a/src/redux/search/search.selectors.ts b/src/redux/search/search.selectors.ts index f2c3b256db453d8093dd6c37bccd74425f311529..0add08e0eef29a62899e6e34b2bc249ab9fdb590 100644 --- a/src/redux/search/search.selectors.ts +++ b/src/redux/search/search.selectors.ts @@ -15,3 +15,5 @@ export const isPendingSearchStatusSelector = createSelector( ); export const perfectMatchSelector = createSelector(searchSelector, state => state.perfectMatch); + +export const searchInputSelector = createSelector(searchSelector, state => state.searchInput); diff --git a/src/redux/search/search.slice.ts b/src/redux/search/search.slice.ts index 08223dc6fe578d1b3abfe7e1129f4821c87253e9..f746f06e1bed6a8dfa49e3859ee32b48abf5420f 100644 --- a/src/redux/search/search.slice.ts +++ b/src/redux/search/search.slice.ts @@ -1,24 +1,25 @@ -import { getSearchDataReducer, setPerfectMatchReducer } from '@/redux/search/search.reducers'; -import { SearchState } from '@/redux/search/search.types'; +import { + clearSearchDataReducer, + getSearchDataReducer, + setPerfectMatchReducer, + setSearchInputReducer, +} from '@/redux/search/search.reducers'; import { createSlice } from '@reduxjs/toolkit'; - -const initialState: SearchState = { - searchValue: [''], - perfectMatch: false, - loading: 'idle', -}; +import { SEARCH_INITIAL_STATE } from './search.constants'; export const searchSlice = createSlice({ name: 'search', - initialState, + initialState: SEARCH_INITIAL_STATE, reducers: { setPerfectMatch: setPerfectMatchReducer, + setSearchInput: setSearchInputReducer, + clearSearchData: clearSearchDataReducer, }, extraReducers(builder) { getSearchDataReducer(builder); }, }); -export const { setPerfectMatch } = searchSlice.actions; +export const { setPerfectMatch, setSearchInput, clearSearchData } = searchSlice.actions; export default searchSlice.reducer; diff --git a/src/redux/search/search.types.ts b/src/redux/search/search.types.ts index 9525aa08ce6afc6ce7623fe462c95d3ab3fe13fc..dfb8685452ab0d24b434815491e19e681b391a3a 100644 --- a/src/redux/search/search.types.ts +++ b/src/redux/search/search.types.ts @@ -2,6 +2,7 @@ import { Loading } from '@/types/loadingState'; import { PayloadAction } from '@reduxjs/toolkit'; export interface SearchState { + searchInput: string; searchValue: string[]; perfectMatch: boolean; loading: Loading; @@ -9,3 +10,6 @@ export interface SearchState { export type SetPerfectMatchPayload = boolean; export type SetPerfectMatchAction = PayloadAction<SetPerfectMatchPayload>; + +export type SetSearchInputPayload = string; +export type SetSearchInputAction = PayloadAction<SetSearchInputPayload>;