Implemented search in the filter bar
parent
10442f9dc8
commit
3281629dcf
|
@ -8,6 +8,7 @@ import {
|
||||||
setRegionOptions,
|
setRegionOptions,
|
||||||
setSortOptions,
|
setSortOptions,
|
||||||
setTypeOptions,
|
setTypeOptions,
|
||||||
|
setSearchInput,
|
||||||
} from 'features/Pokedex/pokedexSlice';
|
} from 'features/Pokedex/pokedexSlice';
|
||||||
import { RegionPokemonRange } from 'features/Pokedex/types/slice';
|
import { RegionPokemonRange } from 'features/Pokedex/types/slice';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/hooks';
|
import { useAppDispatch, useAppSelector } from 'app/hooks';
|
||||||
|
@ -141,6 +142,15 @@ const Filters = () => {
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="filter__items">
|
||||||
|
<div>
|
||||||
|
<div>SEARCH</div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
onChange={e => dispatch(setSearchInput(e.target.value))}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -31,12 +31,22 @@ export const sortPokemonCardsByIdOrName = (
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const searchPokemonCardsByName = (
|
||||||
|
pokemonList: PokemonCardProps[],
|
||||||
|
searchInput: string,
|
||||||
|
) => {
|
||||||
|
return pokemonList.filter(pokemon =>
|
||||||
|
pokemon.name.toLowerCase().includes(searchInput.toLowerCase()),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const Pokedex = () => {
|
const Pokedex = () => {
|
||||||
const isLoadingPokemons = useAppSelector(
|
const isLoadingPokemons = useAppSelector(
|
||||||
state => state.pokedex.isLoadingPokemons,
|
state => state.pokedex.isLoadingPokemons,
|
||||||
);
|
);
|
||||||
const selectedType = useAppSelector(state => state.pokedex.selectedType);
|
const selectedType = useAppSelector(state => state.pokedex.selectedType);
|
||||||
const selectedSort = useAppSelector(state => state.pokedex.selectedSort);
|
const selectedSort = useAppSelector(state => state.pokedex.selectedSort);
|
||||||
|
const searchInput = useAppSelector(state => state.pokedex.searchInput);
|
||||||
|
|
||||||
const pokemonList = useAppSelector(state => state.pokedex.pokemonCardList);
|
const pokemonList = useAppSelector(state => state.pokedex.pokemonCardList);
|
||||||
|
|
||||||
|
@ -48,6 +58,10 @@ const Pokedex = () => {
|
||||||
filteredPokemonList,
|
filteredPokemonList,
|
||||||
selectedSort,
|
selectedSort,
|
||||||
);
|
);
|
||||||
|
const searchedPokemonCardList = searchPokemonCardsByName(
|
||||||
|
sortedFilteredPokemonCardList,
|
||||||
|
searchInput,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -56,7 +70,7 @@ const Pokedex = () => {
|
||||||
<Loading />
|
<Loading />
|
||||||
) : (
|
) : (
|
||||||
<div className="all__pokemons">
|
<div className="all__pokemons">
|
||||||
{sortedFilteredPokemonCardList.map(pokemonCard => (
|
{searchedPokemonCardList.map(pokemonCard => (
|
||||||
<PokemonCard
|
<PokemonCard
|
||||||
key={pokemonCard.id}
|
key={pokemonCard.id}
|
||||||
id={pokemonCard.id}
|
id={pokemonCard.id}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {
|
import {
|
||||||
filterPokemonCardsByType,
|
filterPokemonCardsByType,
|
||||||
sortPokemonCardsByIdOrName,
|
sortPokemonCardsByIdOrName,
|
||||||
|
searchPokemonCardsByName,
|
||||||
} from 'features/Pokedex/Pokedex';
|
} from 'features/Pokedex/Pokedex';
|
||||||
import { PokemonResponseData } from 'features/Pokedex/types/api';
|
import { PokemonResponseData } from 'features/Pokedex/types/api';
|
||||||
import pokemon3_Venusaur from 'features/Pokedex/__test__/pokemon3_Venusaur.json';
|
import pokemon3_Venusaur from 'features/Pokedex/__test__/pokemon3_Venusaur.json';
|
||||||
|
@ -81,4 +82,32 @@ describe('pokedex Component', () => {
|
||||||
expect(sortedList).toEqual([pokemon4_Charmander, pokemon3_Venusaur]);
|
expect(sortedList).toEqual([pokemon4_Charmander, pokemon3_Venusaur]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('searchPokemonByName works correctly', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
store = configureStore({
|
||||||
|
reducer: {
|
||||||
|
pokedex: pokedexSlice.reducer,
|
||||||
|
[pokedexApi.reducerPath]: pokedexApi.reducer,
|
||||||
|
},
|
||||||
|
middleware: getDefaultMiddleware =>
|
||||||
|
getDefaultMiddleware().concat(
|
||||||
|
pokedexApi.middleware,
|
||||||
|
listenerMiddleware.middleware,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const pokemonList: PokemonResponseData[] = [
|
||||||
|
pokemon3_Venusaur,
|
||||||
|
pokemon4_Charmander,
|
||||||
|
];
|
||||||
|
|
||||||
|
it('should search by name correctly', () => {
|
||||||
|
const searchName = 'char';
|
||||||
|
const searchedList = searchPokemonCardsByName(pokemonList, searchName);
|
||||||
|
expect(searchedList).toHaveLength(1);
|
||||||
|
expect(searchedList[0]).toEqual(pokemon4_Charmander);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -50,6 +50,7 @@ const initialState: PokedexState = {
|
||||||
selectedRegion: '',
|
selectedRegion: '',
|
||||||
selectedType: '',
|
selectedType: '',
|
||||||
selectedSort: '',
|
selectedSort: '',
|
||||||
|
searchInput: '',
|
||||||
isLoadingPokemons: true,
|
isLoadingPokemons: true,
|
||||||
pokemonCardList: [],
|
pokemonCardList: [],
|
||||||
};
|
};
|
||||||
|
@ -79,6 +80,9 @@ export const pokedexSlice: Slice<PokedexState> = createSlice({
|
||||||
) => {
|
) => {
|
||||||
state.sortOptions = action.payload;
|
state.sortOptions = action.payload;
|
||||||
},
|
},
|
||||||
|
setSearchInput: (state, action: PayloadAction<string>) => {
|
||||||
|
state.searchInput = action.payload;
|
||||||
|
},
|
||||||
setIsLoadingPokemons: (state, action: PayloadAction<boolean>) => {
|
setIsLoadingPokemons: (state, action: PayloadAction<boolean>) => {
|
||||||
state.isLoadingPokemons = action.payload;
|
state.isLoadingPokemons = action.payload;
|
||||||
},
|
},
|
||||||
|
@ -118,6 +122,7 @@ export const {
|
||||||
setRegionOptions,
|
setRegionOptions,
|
||||||
setTypeOptions,
|
setTypeOptions,
|
||||||
setSortOptions,
|
setSortOptions,
|
||||||
|
setSearchInput,
|
||||||
setIsLoadingPokemons,
|
setIsLoadingPokemons,
|
||||||
} = pokedexSlice.actions;
|
} = pokedexSlice.actions;
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,13 @@ import { PokemonResponseData } from './api';
|
||||||
import { PokemonCardProps } from '../PokemonCard';
|
import { PokemonCardProps } from '../PokemonCard';
|
||||||
|
|
||||||
export type PokedexState = {
|
export type PokedexState = {
|
||||||
selectedRegion: string;
|
|
||||||
regionOptions: RegionPokemonRange[];
|
regionOptions: RegionPokemonRange[];
|
||||||
selectedType: string;
|
|
||||||
typeOptions: string[];
|
typeOptions: string[];
|
||||||
selectedSort: string;
|
|
||||||
sortOptions: { name: string; value: string }[];
|
sortOptions: { name: string; value: string }[];
|
||||||
|
selectedRegion: string;
|
||||||
|
selectedType: string;
|
||||||
|
selectedSort: string;
|
||||||
|
searchInput: string;
|
||||||
isLoadingPokemons: boolean;
|
isLoadingPokemons: boolean;
|
||||||
pokemonCardList: PokemonCardProps[];
|
pokemonCardList: PokemonCardProps[];
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue