Compare commits
No commits in common. "bde86898e2eb9fc6f10578555bebf201bde61cae" and "54bf00e22c967d25cd586b4822e5e9bd07ef59ac" have entirely different histories.
bde86898e2
...
54bf00e22c
@ -2,7 +2,6 @@ import {
|
|||||||
fetchBaseQuery,
|
fetchBaseQuery,
|
||||||
FetchArgs,
|
FetchArgs,
|
||||||
createApi,
|
createApi,
|
||||||
BaseQueryApi,
|
|
||||||
} from '@reduxjs/toolkit/query/react';
|
} from '@reduxjs/toolkit/query/react';
|
||||||
import {
|
import {
|
||||||
RegionListResponseData,
|
RegionListResponseData,
|
||||||
@ -10,7 +9,6 @@ import {
|
|||||||
PokemonResponseData,
|
PokemonResponseData,
|
||||||
EvolutionChainResponseData,
|
EvolutionChainResponseData,
|
||||||
PokemonSpeciesResponseData,
|
PokemonSpeciesResponseData,
|
||||||
nameUrlPair,
|
|
||||||
} from 'types/api';
|
} from 'types/api';
|
||||||
|
|
||||||
export interface pokeApiFullListFetchArgs extends FetchArgs {
|
export interface pokeApiFullListFetchArgs extends FetchArgs {
|
||||||
@ -21,7 +19,12 @@ interface PokeAPIPaginatedResponse {
|
|||||||
count: number;
|
count: number;
|
||||||
next: string | null;
|
next: string | null;
|
||||||
previous: string | null;
|
previous: string | null;
|
||||||
results: nameUrlPair[];
|
results: any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PokeAPIFullListResponse {
|
||||||
|
count: number;
|
||||||
|
results: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getIdFromUrl = (url: string) => {
|
export const getIdFromUrl = (url: string) => {
|
||||||
@ -30,7 +33,7 @@ export const getIdFromUrl = (url: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
async function fetchAllPages(url: string | null) {
|
async function fetchAllPages(url: string | null) {
|
||||||
const allResults: nameUrlPair[] = [];
|
const allResults: any[] = [];
|
||||||
|
|
||||||
while (url) {
|
while (url) {
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
@ -47,7 +50,7 @@ export const paginationBaseQuery = (baseUrl: string) =>
|
|||||||
|
|
||||||
export const pokeApiAllPagesCustomBaseQuery = async (
|
export const pokeApiAllPagesCustomBaseQuery = async (
|
||||||
args: pokeApiFullListFetchArgs,
|
args: pokeApiFullListFetchArgs,
|
||||||
api: BaseQueryApi,
|
api: any,
|
||||||
extra: any,
|
extra: any,
|
||||||
baseUrl: string,
|
baseUrl: string,
|
||||||
) => {
|
) => {
|
||||||
@ -59,17 +62,19 @@ export const pokeApiAllPagesCustomBaseQuery = async (
|
|||||||
data.results = data.results.concat(allResults);
|
data.results = data.results.concat(allResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.data = {
|
const fullListReponse: PokeAPIFullListResponse = {
|
||||||
count: data.count,
|
count: data.count,
|
||||||
results: data.results,
|
results: data.results,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
result.data = fullListReponse;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const pokeApiBaseQuery = async (
|
export const pokeApiBaseQuery = async (
|
||||||
args: pokeApiFullListFetchArgs,
|
args: pokeApiFullListFetchArgs,
|
||||||
api: BaseQueryApi,
|
api: any,
|
||||||
extra: any,
|
extra: any,
|
||||||
) => {
|
) => {
|
||||||
const baseUrl = 'https://pokeapi.co/api/v2/';
|
const baseUrl = 'https://pokeapi.co/api/v2/';
|
||||||
|
@ -6,8 +6,10 @@ import {
|
|||||||
setSelectedRegion,
|
setSelectedRegion,
|
||||||
setSelectedType,
|
setSelectedType,
|
||||||
setSelectedSort,
|
setSelectedSort,
|
||||||
|
setRegionOptions,
|
||||||
|
setTypeOptions,
|
||||||
|
setSortOptions,
|
||||||
setSearchInput,
|
setSearchInput,
|
||||||
initializeFilterSlice,
|
|
||||||
} from './filterSlice';
|
} from './filterSlice';
|
||||||
import { useGetTypeListQuery } from 'app/services/pokeApi';
|
import { useGetTypeListQuery } from 'app/services/pokeApi';
|
||||||
import { RegionPokemonRange } from './types/slice';
|
import { RegionPokemonRange } from './types/slice';
|
||||||
@ -29,22 +31,61 @@ export const createRegionPokemonListOptionElements = (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useGetRegionOptions = () => {
|
||||||
|
const data: RegionPokemonRange[] = [
|
||||||
|
{ region: 'kanto', startId: 1, endId: 151 },
|
||||||
|
{ region: 'johto', startId: 152, endId: 251 },
|
||||||
|
{ region: 'hoenn', startId: 252, endId: 386 },
|
||||||
|
{ region: 'sinnoh', startId: 387, endId: 493 },
|
||||||
|
{ region: 'unova', startId: 494, endId: 649 },
|
||||||
|
{ region: 'kalos', startId: 650, endId: 721 },
|
||||||
|
{ region: 'alola', startId: 722, endId: 809 },
|
||||||
|
{ region: 'galar', startId: 810, endId: 898 },
|
||||||
|
];
|
||||||
|
return { data: data };
|
||||||
|
};
|
||||||
|
|
||||||
|
const useGetSortOptions = () => {
|
||||||
|
const data = [
|
||||||
|
{ name: 'ID', value: 'id' },
|
||||||
|
{ name: 'Name', value: 'name' },
|
||||||
|
];
|
||||||
|
|
||||||
|
return { data: data };
|
||||||
|
};
|
||||||
|
|
||||||
const Filters = () => {
|
const Filters = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const typeOptions = useAppSelector(state => state.filter.typeOptions);
|
|
||||||
const sortOptions = useAppSelector(state => state.filter.sortOptions);
|
|
||||||
const regionOptions = useAppSelector(state => state.filter.regionOptions);
|
|
||||||
const selectedRegion = useAppSelector(state => state.filter.selectedRegion);
|
const selectedRegion = useAppSelector(state => state.filter.selectedRegion);
|
||||||
const selectedType = useAppSelector(state => state.filter.selectedType);
|
const selectedType = useAppSelector(state => state.filter.selectedType);
|
||||||
const selectedSort = useAppSelector(state => state.filter.selectedSort);
|
const selectedSort = useAppSelector(state => state.filter.selectedSort);
|
||||||
const searchInput = useAppSelector(state => state.filter.searchInput);
|
const searchInput = useAppSelector(state => state.filter.searchInput);
|
||||||
|
|
||||||
const { isLoading: isFetchingTypeOptions } = useGetTypeListQuery();
|
const regionPokemonList = useAppSelector(state => state.filter.regionOptions);
|
||||||
|
|
||||||
|
const { data: fetchedRegionOptions } = useGetRegionOptions();
|
||||||
|
const { data: fetchedTypeOptions, isLoading: isFetchingTypeOptions } =
|
||||||
|
useGetTypeListQuery();
|
||||||
|
const { data: fetchedSortOptions } = useGetSortOptions();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(initializeFilterSlice());
|
dispatch(setRegionOptions(fetchedRegionOptions));
|
||||||
}, [dispatch]);
|
dispatch(setSortOptions(fetchedSortOptions));
|
||||||
|
|
||||||
|
dispatch(setSelectedRegion(fetchedRegionOptions[0].region));
|
||||||
|
|
||||||
|
dispatch(setSelectedSort(fetchedSortOptions[0].value));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isFetchingTypeOptions && fetchedTypeOptions) {
|
||||||
|
dispatch(setTypeOptions(fetchedTypeOptions.results));
|
||||||
|
dispatch(setSelectedType(fetchedTypeOptions.results[0].name));
|
||||||
|
}
|
||||||
|
}, [isFetchingTypeOptions]);
|
||||||
|
|
||||||
|
const optionElements =
|
||||||
|
createRegionPokemonListOptionElements(regionPokemonList);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -60,7 +101,7 @@ const Filters = () => {
|
|||||||
}}
|
}}
|
||||||
value={selectedRegion}
|
value={selectedRegion}
|
||||||
>
|
>
|
||||||
{createRegionPokemonListOptionElements(regionOptions)}
|
{optionElements}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -75,9 +116,9 @@ const Filters = () => {
|
|||||||
{isFetchingTypeOptions ? (
|
{isFetchingTypeOptions ? (
|
||||||
<option>Loading...</option>
|
<option>Loading...</option>
|
||||||
) : (
|
) : (
|
||||||
typeOptions.map(type => (
|
fetchedTypeOptions?.results.map(type => (
|
||||||
<option key={type} value={type}>
|
<option key={type.name} value={type.name}>
|
||||||
{type}
|
{type.name}
|
||||||
</option>
|
</option>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
@ -93,7 +134,7 @@ const Filters = () => {
|
|||||||
onChange={e => dispatch(setSelectedSort(e.target.value))}
|
onChange={e => dispatch(setSelectedSort(e.target.value))}
|
||||||
value={selectedSort}
|
value={selectedSort}
|
||||||
>
|
>
|
||||||
{sortOptions.map(option => (
|
{fetchedSortOptions.map(option => (
|
||||||
<option key={option.value} value={option.value}>
|
<option key={option.value} value={option.value}>
|
||||||
{option.name}
|
{option.name}
|
||||||
</option>
|
</option>
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
import {
|
import { createSlice, PayloadAction, Slice } from '@reduxjs/toolkit';
|
||||||
createAsyncThunk,
|
|
||||||
createSlice,
|
|
||||||
PayloadAction,
|
|
||||||
Slice,
|
|
||||||
} from '@reduxjs/toolkit';
|
|
||||||
import { FilterState } from './types/slice';
|
import { FilterState } from './types/slice';
|
||||||
import { RegionPokemonRange } from './types/slice';
|
import { RegionPokemonRange } from './types/slice';
|
||||||
import { pokeApi } from 'app/services/pokeApi';
|
import { pokeApi } from 'app/services/pokeApi';
|
||||||
@ -20,33 +15,6 @@ const initialState: FilterState = {
|
|||||||
searchInput: '',
|
searchInput: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const initializeFilterSlice = createAsyncThunk(
|
|
||||||
'filter/initializeFilterSlice',
|
|
||||||
async (_args, thunkAPI) => {
|
|
||||||
const dispatch = thunkAPI.dispatch;
|
|
||||||
|
|
||||||
const regionOptions = [
|
|
||||||
{ region: 'kanto', startId: 1, endId: 151 },
|
|
||||||
{ region: 'johto', startId: 152, endId: 251 },
|
|
||||||
{ region: 'hoenn', startId: 252, endId: 386 },
|
|
||||||
{ region: 'sinnoh', startId: 387, endId: 493 },
|
|
||||||
{ region: 'unova', startId: 494, endId: 649 },
|
|
||||||
{ region: 'kalos', startId: 650, endId: 721 },
|
|
||||||
{ region: 'alola', startId: 722, endId: 809 },
|
|
||||||
{ region: 'galar', startId: 810, endId: 898 },
|
|
||||||
];
|
|
||||||
|
|
||||||
dispatch(pokeApi.endpoints.getTypeList.initiate());
|
|
||||||
|
|
||||||
const sortOptions = [
|
|
||||||
{ name: 'ID', value: 'id' },
|
|
||||||
{ name: 'Name', value: 'name' },
|
|
||||||
];
|
|
||||||
|
|
||||||
return { regionOptions, sortOptions };
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export const filterSlice: Slice<FilterState> = createSlice({
|
export const filterSlice: Slice<FilterState> = createSlice({
|
||||||
name: 'filter',
|
name: 'filter',
|
||||||
initialState,
|
initialState,
|
||||||
@ -77,15 +45,6 @@ export const filterSlice: Slice<FilterState> = createSlice({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
extraReducers: builder => {
|
extraReducers: builder => {
|
||||||
builder.addCase(initializeFilterSlice.fulfilled, (state, action) => {
|
|
||||||
if (action.payload) {
|
|
||||||
state.regionOptions = action.payload.regionOptions;
|
|
||||||
state.sortOptions = action.payload.sortOptions;
|
|
||||||
|
|
||||||
state.selectedRegion = action.payload.regionOptions[0].region;
|
|
||||||
state.selectedSort = action.payload.sortOptions[0].value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.addMatcher(
|
builder.addMatcher(
|
||||||
pokeApi.endpoints.getTypeList.matchFulfilled,
|
pokeApi.endpoints.getTypeList.matchFulfilled,
|
||||||
(state, action) => {
|
(state, action) => {
|
||||||
|
@ -76,7 +76,7 @@ const Pokedex = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(fetchPokemonsInTheRegion(selectedRegion));
|
dispatch(fetchPokemonsInTheRegion(selectedRegion));
|
||||||
}, [dispatch, selectedRegion]);
|
}, [selectedRegion]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -37,6 +37,7 @@ export interface PokemonResponseData {
|
|||||||
base_experience: number;
|
base_experience: number;
|
||||||
forms: nameUrlPair[];
|
forms: nameUrlPair[];
|
||||||
height: number;
|
height: number;
|
||||||
|
held_items: any[];
|
||||||
id: number;
|
id: number;
|
||||||
is_default: boolean;
|
is_default: boolean;
|
||||||
location_area_encounters: string;
|
location_area_encounters: string;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user