diff --git a/src/components/FunctionalArea/TopBar/SearchBar/SearchBar.component.tsx b/src/components/FunctionalArea/TopBar/SearchBar/SearchBar.component.tsx index b1dda9048890405f60bb926f55bbed7326c0c4ce..fc28ddc3b711bc72190ee2aa0be5538c74f6165f 100644 --- a/src/components/FunctionalArea/TopBar/SearchBar/SearchBar.component.tsx +++ b/src/components/FunctionalArea/TopBar/SearchBar/SearchBar.component.tsx @@ -1,4 +1,8 @@ -import { autocompleteSearchSelector } from '@/redux/autocomplete/autocomplete.selectors'; +import { + autocompleteChemicalSelector, + autocompleteDrugSelector, + autocompleteSearchSelector, +} from '@/redux/autocomplete/autocomplete.selectors'; import { currentSelectedSearchElement, searchDrawerOpenSelector, @@ -37,6 +41,8 @@ export const SearchBar = (): JSX.Element => { const isPerfectMatch = useSelector(perfectMatchSelector); const searchValueState = useSelector(searchValueSelector); const searchAutocompleteState = useSelector(autocompleteSearchSelector); + const drugAutocompleteState = useSelector(autocompleteDrugSelector); + const chemicalAutocompleteState = useSelector(autocompleteChemicalSelector); const dispatch = useAppDispatch(); const router = useRouter(); const currentTab = useSelector(currentSelectedSearchElement); @@ -87,11 +93,12 @@ export const SearchBar = (): JSX.Element => { openSearchDrawerIfClosed(currentTab); }; - // eslint-disable-next-line no-console - console.log(searchAutocompleteState.searchValues); - const suggestions = searchAutocompleteState.searchValues.map(entry => { - return { name: entry }; - }); + const suggestions = searchAutocompleteState.searchValues + .concat(drugAutocompleteState.searchValues, chemicalAutocompleteState.searchValues) + .map(entry => { + return { name: entry }; + }) + .sort((a: Suggestion, b: Suggestion) => a.name.localeCompare(b.name)); const getSuggestions = (value: string): Suggestion[] => { const inputValue = value.trim().toLowerCase(); diff --git a/src/components/FunctionalArea/TopBar/TopBar.component.test.tsx b/src/components/FunctionalArea/TopBar/TopBar.component.test.tsx index 839585389d8757b198ba0db2ec900794649cc144..0fb6117915a0eae1c6631f65133822a9bf64fc12 100644 --- a/src/components/FunctionalArea/TopBar/TopBar.component.test.tsx +++ b/src/components/FunctionalArea/TopBar/TopBar.component.test.tsx @@ -119,6 +119,8 @@ describe('TopBar - component', () => { map: initialMapStateFixture, search: SEARCH_STATE_INITIAL_MOCK, autocompleteSearch: AUTOCOMPLETE_INITIAL_STATE, + autocompleteDrug: AUTOCOMPLETE_INITIAL_STATE, + autocompleteChemical: AUTOCOMPLETE_INITIAL_STATE, backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, }); @@ -136,6 +138,8 @@ describe('TopBar - component', () => { user: USER_INITIAL_STATE_MOCK, search: SEARCH_STATE_INITIAL_MOCK, autocompleteSearch: AUTOCOMPLETE_INITIAL_STATE, + autocompleteDrug: AUTOCOMPLETE_INITIAL_STATE, + autocompleteChemical: AUTOCOMPLETE_INITIAL_STATE, drawer: initialStateFixture, project: { ...PROJECT_STATE_INITIAL_MOCK, diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts index b8002874697094abc0a67ae1bb7b44257ffb0bf0..423aefbfbe19d9c5ab79eb7077d6cd0af7e0b2e0 100644 --- a/src/redux/apiPath.ts +++ b/src/redux/apiPath.ts @@ -112,4 +112,6 @@ export const apiPath = { getSearchAutocomplete: (): string => `projects/${PROJECT_ID}/models/*/bioEntities/suggestedQueryList`, + getDrugAutocomplete: (): string => `projects/${PROJECT_ID}/drugs/suggestedQueryList`, + getChemicalAutocomplete: (): string => `projects/${PROJECT_ID}/chemicals/suggestedQueryList`, }; diff --git a/src/redux/autocomplete/autocomplete.reducers.ts b/src/redux/autocomplete/autocomplete.reducers.ts index 8fb6ce0e5de26b51d0d129ab319a1ddb41f30e02..a36fa9a370add7af40898ef2cac8c441aac40072 100644 --- a/src/redux/autocomplete/autocomplete.reducers.ts +++ b/src/redux/autocomplete/autocomplete.reducers.ts @@ -1,6 +1,10 @@ import { AutocompleteState } from '@/redux/autocomplete/autocomplete.types'; import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; -import { getSearchAutocomplete } from '@/redux/autocomplete/autocomplete.thunks'; +import { + getChemicalAutocomplete, + getDrugAutocomplete, + getSearchAutocomplete, +} from '@/redux/autocomplete/autocomplete.thunks'; export const getSearchAutocompleteReducer = ( builder: ActionReducerMapBuilder<AutocompleteState>, @@ -17,3 +21,35 @@ export const getSearchAutocompleteReducer = ( // TODO: error management to be discussed in the team }); }; + +export const getDrugAutocompleteReducer = ( + builder: ActionReducerMapBuilder<AutocompleteState>, +): void => { + builder.addCase(getDrugAutocomplete.pending, state => { + state.loading = 'pending'; + }); + builder.addCase(getDrugAutocomplete.fulfilled, (state, action) => { + state.searchValues = action.payload ? action.payload : []; + state.loading = 'succeeded'; + }); + builder.addCase(getDrugAutocomplete.rejected, state => { + state.loading = 'failed'; + // TODO: error management to be discussed in the team + }); +}; + +export const getChemicalAutocompleteReducer = ( + builder: ActionReducerMapBuilder<AutocompleteState>, +): void => { + builder.addCase(getChemicalAutocomplete.pending, state => { + state.loading = 'pending'; + }); + builder.addCase(getChemicalAutocomplete.fulfilled, (state, action) => { + state.searchValues = action.payload ? action.payload : []; + state.loading = 'succeeded'; + }); + builder.addCase(getChemicalAutocomplete.rejected, state => { + state.loading = 'failed'; + // TODO: error management to be discussed in the team + }); +}; diff --git a/src/redux/autocomplete/autocomplete.selectors.ts b/src/redux/autocomplete/autocomplete.selectors.ts index c6f1f6ae54d476b94608216a7ec97f9ae24e35f5..d1ee002ae613cfa11a49029ca8c5b12c9bb092d1 100644 --- a/src/redux/autocomplete/autocomplete.selectors.ts +++ b/src/redux/autocomplete/autocomplete.selectors.ts @@ -5,3 +5,13 @@ export const autocompleteSearchSelector = createSelector( rootSelector, state => state.autocompleteSearch, ); + +export const autocompleteDrugSelector = createSelector( + rootSelector, + state => state.autocompleteDrug, +); + +export const autocompleteChemicalSelector = createSelector( + rootSelector, + state => state.autocompleteChemical, +); diff --git a/src/redux/autocomplete/autocomplete.slice.ts b/src/redux/autocomplete/autocomplete.slice.ts index ab28dbc6b48f33ac0b3134ac899fc1cb8da674f4..6d042065c4d7edd5ceaeb5a6c3f4059df4e9aa8a 100644 --- a/src/redux/autocomplete/autocomplete.slice.ts +++ b/src/redux/autocomplete/autocomplete.slice.ts @@ -1,9 +1,13 @@ import { createSlice } from '@reduxjs/toolkit'; import { AUTOCOMPLETE_INITIAL_STATE } from '@/redux/autocomplete/autocomplete.constants'; -import { getSearchAutocompleteReducer } from '@/redux/autocomplete/autocomplete.reducers'; +import { + getChemicalAutocompleteReducer, + getDrugAutocompleteReducer, + getSearchAutocompleteReducer, +} from '@/redux/autocomplete/autocomplete.reducers'; export const autocompleteSearchSlice = createSlice({ - name: 'autocomplete', + name: 'autocompleteSearch', initialState: AUTOCOMPLETE_INITIAL_STATE, reducers: {}, extraReducers(builder) { @@ -12,3 +16,25 @@ export const autocompleteSearchSlice = createSlice({ }); export const autocompleteSearchReducer = autocompleteSearchSlice.reducer; + +export const autocompleteDrugSlice = createSlice({ + name: 'autocompleteDrug', + initialState: AUTOCOMPLETE_INITIAL_STATE, + reducers: {}, + extraReducers(builder) { + getDrugAutocompleteReducer(builder); + }, +}); + +export const autocompleteDrugReducer = autocompleteDrugSlice.reducer; + +export const autocompleteChemicalSlice = createSlice({ + name: 'autocompleteChemical', + initialState: AUTOCOMPLETE_INITIAL_STATE, + reducers: {}, + extraReducers(builder) { + getChemicalAutocompleteReducer(builder); + }, +}); + +export const autocompleteChemicalReducer = autocompleteChemicalSlice.reducer; diff --git a/src/redux/autocomplete/autocomplete.thunks.ts b/src/redux/autocomplete/autocomplete.thunks.ts index 6397ea42adfd9f462b0420de79f48112fab41449..d9204b9e906e38e46c6d2478dec8ce706db734ef 100644 --- a/src/redux/autocomplete/autocomplete.thunks.ts +++ b/src/redux/autocomplete/autocomplete.thunks.ts @@ -26,3 +26,43 @@ export const getSearchAutocomplete = createAsyncThunk< } }, ); + +export const getDrugAutocomplete = createAsyncThunk< + string[] | undefined, + void, + { state: RootState } & ThunkConfig +>( + 'project/getDrugAutocomplete', + // eslint-disable-next-line consistent-return + async () => { + try { + const response = await axiosInstance.get<string[]>(apiPath.getDrugAutocomplete()); + + const isDataValid = validateDataUsingZodSchema(response.data, autocompleteSchema); + + return isDataValid ? response.data : undefined; + } catch (error) { + return Promise.reject(getError({ error })); + } + }, +); + +export const getChemicalAutocomplete = createAsyncThunk< + string[] | undefined, + void, + { state: RootState } & ThunkConfig +>( + 'project/getChemicalAutocomplete', + // eslint-disable-next-line consistent-return + async () => { + try { + const response = await axiosInstance.get<string[]>(apiPath.getChemicalAutocomplete()); + + const isDataValid = validateDataUsingZodSchema(response.data, autocompleteSchema); + + return isDataValid ? response.data : undefined; + } catch (error) { + return Promise.reject(getError({ error })); + } + }, +); diff --git a/src/redux/root/init.thunks.ts b/src/redux/root/init.thunks.ts index 476e5b40ec72320420a176d6d219fea07bfb8880..9387f79cb62e54c63200f673d2f09781e412faed 100644 --- a/src/redux/root/init.thunks.ts +++ b/src/redux/root/init.thunks.ts @@ -7,7 +7,11 @@ import { PluginsManager } from '@/services/pluginsManager'; import { createAsyncThunk } from '@reduxjs/toolkit'; import { ZERO } from '@/constants/common'; import { getConstant } from '@/redux/constant/constant.thunks'; -import { getSearchAutocomplete } from '@/redux/autocomplete/autocomplete.thunks'; +import { + getChemicalAutocomplete, + getDrugAutocomplete, + getSearchAutocomplete, +} from '@/redux/autocomplete/autocomplete.thunks'; import { getAllBackgroundsByProjectId } from '../backgrounds/backgrounds.thunks'; import { getConfiguration, getConfigurationOptions } from '../configuration/configuration.thunks'; import { @@ -89,6 +93,8 @@ export const fetchInitialAppData = createAsyncThunk< // autocomplete dispatch(getSearchAutocomplete()); + dispatch(getDrugAutocomplete()); + dispatch(getChemicalAutocomplete()); /** Trigger search */ if (queryData.searchValue) { diff --git a/src/redux/root/root.fixtures.ts b/src/redux/root/root.fixtures.ts index 5f116bc51fbbd26be5d5831906787ba500776ecf..e260f230ea8bd4a0060fe58399cb9ef2b9965087 100644 --- a/src/redux/root/root.fixtures.ts +++ b/src/redux/root/root.fixtures.ts @@ -32,6 +32,8 @@ import { USER_INITIAL_STATE_MOCK } from '../user/user.mock'; export const INITIAL_STORE_STATE_MOCK: RootState = { autocompleteSearch: AUTOCOMPLETE_INITIAL_STATE, + autocompleteDrug: AUTOCOMPLETE_INITIAL_STATE, + autocompleteChemical: AUTOCOMPLETE_INITIAL_STATE, search: SEARCH_STATE_INITIAL_MOCK, project: PROJECT_STATE_INITIAL_MOCK, projects: PROJECTS_STATE_INITIAL_MOCK, diff --git a/src/redux/store.ts b/src/redux/store.ts index a5c2daeafdadca3cf7b2ad4c2d71c2b76ef2117f..f11f6e57248b0a405241aa54ee29d321e1b29ffc 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -18,7 +18,11 @@ import projectsReducer from '@/redux/projects/projects.slice'; import reactionsReducer from '@/redux/reactions/reactions.slice'; import searchReducer from '@/redux/search/search.slice'; import userReducer from '@/redux/user/user.slice'; -import { autocompleteSearchReducer } from '@/redux/autocomplete/autocomplete.slice'; +import { + autocompleteChemicalReducer, + autocompleteDrugReducer, + autocompleteSearchReducer, +} from '@/redux/autocomplete/autocomplete.slice'; import { AnyAction, ListenerEffectAPI, @@ -40,6 +44,8 @@ import statisticsReducer from './statistics/statistics.slice'; export const reducers = { autocompleteSearch: autocompleteSearchReducer, + autocompleteDrug: autocompleteDrugReducer, + autocompleteChemical: autocompleteChemicalReducer, search: searchReducer, project: projectReducer, projects: projectsReducer,