Implemented search in the filter bar

develop
Jason Zhu 2023-04-17 22:52:54 +10:00
parent 10442f9dc8
commit 3281629dcf
5 changed files with 63 additions and 4 deletions

View File

@ -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>
</> </>
); );

View File

@ -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}

View File

@ -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);
});
});
}); });

View File

@ -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;

View File

@ -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[];
}; };