Trying to impolement InfoDialogSlice and related api endpoints (Code is faulty)
This commit is contained in:
parent
8c442946d3
commit
78b7a4a5f4
@ -1,6 +1,8 @@
|
|||||||
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
|
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
|
||||||
import { pokeApi } from 'app/services/pokeApi';
|
import { pokeApi } from 'app/services/pokeApi';
|
||||||
import { filterSlice } from 'features/Filters/filterSlice';
|
import { filterSlice } from 'features/Filters/filterSlice';
|
||||||
|
import { getIdFromUrl } from 'app/services/pokeApi';
|
||||||
|
|
||||||
import { configureStore } from '@reduxjs/toolkit';
|
import { configureStore } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import { AppStore } from 'app/store';
|
import { AppStore } from 'app/store';
|
||||||
@ -87,4 +89,18 @@ describe('pokeApi', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('test helper functions', () => {
|
||||||
|
test('getIdFromUrl works correctly for PokemonSpecies', () => {
|
||||||
|
const url = 'https://pokeapi.co/api/v2/pokemon-species/6/';
|
||||||
|
const id = getIdFromUrl(url);
|
||||||
|
expect(id).toBe(6);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('getIdFromUrl works correctly for evolution-chain', () => {
|
||||||
|
const url = 'https://pokeapi.co/api/v2/evolution-chain/2/';
|
||||||
|
const id = getIdFromUrl(url);
|
||||||
|
expect(id).toBe(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,10 @@ import {
|
|||||||
PokemonResponseData,
|
PokemonResponseData,
|
||||||
EvolutionChainResponseData,
|
EvolutionChainResponseData,
|
||||||
PokemonSpeciesResponseData,
|
PokemonSpeciesResponseData,
|
||||||
|
EvolutionChain,
|
||||||
} from 'types/api';
|
} from 'types/api';
|
||||||
|
import { InfoDialogComponentProps } from 'components/InfoDialogComponent';
|
||||||
|
import { EvolutionSpeciesProps } from 'components/EvolutionSpecies';
|
||||||
|
|
||||||
export interface pokeApiFullListFetchArgs extends FetchArgs {
|
export interface pokeApiFullListFetchArgs extends FetchArgs {
|
||||||
fetchAllPages?: boolean;
|
fetchAllPages?: boolean;
|
||||||
@ -27,6 +30,11 @@ interface PokeAPIFullListResponse {
|
|||||||
results: any[];
|
results: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getIdFromUrl = (url: string) => {
|
||||||
|
const urlParts = url.split('/');
|
||||||
|
return parseInt(urlParts[urlParts.length - 2]);
|
||||||
|
};
|
||||||
|
|
||||||
async function fetchAllPages(url: string | null) {
|
async function fetchAllPages(url: string | null) {
|
||||||
const allResults: any[] = [];
|
const allResults: any[] = [];
|
||||||
|
|
||||||
@ -40,6 +48,23 @@ async function fetchAllPages(url: string | null) {
|
|||||||
return allResults;
|
return allResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const convertEvolutionChainResponseDataToEvolutionSpeciesProps = (
|
||||||
|
evo: EvolutionChainResponseData,
|
||||||
|
): EvolutionSpeciesProps[] => {
|
||||||
|
const result: EvolutionSpeciesProps[] = [];
|
||||||
|
// const addEvolutionSpeciesProps = (evo: EvolutionChain, level: number) => {
|
||||||
|
// result.push({
|
||||||
|
// name: evo.species.name,
|
||||||
|
// });
|
||||||
|
// evo.evolves_to.forEach(evo => {
|
||||||
|
// addEvolutionSpeciesProps(evo, level + 1);
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// addEvolutionSpeciesProps(evo.chain, 0);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
export const paginationBaseQuery = (baseUrl: string) =>
|
export const paginationBaseQuery = (baseUrl: string) =>
|
||||||
fetchBaseQuery({ baseUrl });
|
fetchBaseQuery({ baseUrl });
|
||||||
|
|
||||||
@ -94,18 +119,40 @@ export const pokeApi = createApi({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
getPokemon: builder.query<PokemonResponseData, number | string>({
|
getPokemon: builder.query<PokemonResponseData, number>({
|
||||||
query: IdOrName => ({ url: `pokemon/${IdOrName}` }),
|
query: Id => ({ url: `pokemon/${Id}` }),
|
||||||
}),
|
}),
|
||||||
getPokemonSpecies: builder.query<
|
getPokemonSpecies: builder.query<PokemonSpeciesResponseData, number>({
|
||||||
PokemonSpeciesResponseData,
|
query: Id => ({ url: `pokemon-species/${Id}` }),
|
||||||
number | string
|
|
||||||
>({
|
|
||||||
query: IdOrName => ({ url: `pokemon-species/${IdOrName}` }),
|
|
||||||
}),
|
}),
|
||||||
getEvolutionChain: builder.query<EvolutionChainResponseData, number>({
|
getEvolutionChain: builder.query<EvolutionChainResponseData, number>({
|
||||||
query: Id => ({ url: `evolution-chain/${Id}` }),
|
query: Id => ({ url: `evolution-chain/${Id}` }),
|
||||||
}),
|
}),
|
||||||
|
getPokemonInfo: builder.query<string, number>({
|
||||||
|
async queryFn(pokemonId, queryApi) {
|
||||||
|
const pokemon: PokemonResponseData = await queryApi
|
||||||
|
.dispatch(pokeApi.endpoints.getPokemon.initiate(pokemonId))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
const pokemonSpecies: PokemonSpeciesResponseData = await queryApi
|
||||||
|
.dispatch(
|
||||||
|
pokeApi.endpoints.getPokemonSpecies.initiate(
|
||||||
|
getIdFromUrl(pokemon.species.url),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
const evolutionChain: EvolutionChainResponseData = await queryApi
|
||||||
|
.dispatch(
|
||||||
|
pokeApi.endpoints.getEvolutionChain.initiate(
|
||||||
|
getIdFromUrl(pokemonSpecies.evolution_chain.url),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
return { data: 'test' };
|
||||||
|
},
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { configureStore } from '@reduxjs/toolkit';
|
import { configureStore } from '@reduxjs/toolkit';
|
||||||
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
|
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
|
||||||
import { filterSlice } from 'features/Filters/filterSlice';
|
import { filterSlice } from 'features/Filters/filterSlice';
|
||||||
|
import { infoDialogSlice } from 'features/InfoDialog/infoDialogSlice';
|
||||||
import { pokeApi } from './services/pokeApi';
|
import { pokeApi } from './services/pokeApi';
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
@ -8,6 +9,7 @@ export const store = configureStore({
|
|||||||
// component slices
|
// component slices
|
||||||
pokedex: pokedexSlice.reducer,
|
pokedex: pokedexSlice.reducer,
|
||||||
filter: filterSlice.reducer,
|
filter: filterSlice.reducer,
|
||||||
|
infoDialog: infoDialogSlice.reducer,
|
||||||
|
|
||||||
// api slices
|
// api slices
|
||||||
[pokeApi.reducerPath]: pokeApi.reducer,
|
[pokeApi.reducerPath]: pokeApi.reducer,
|
||||||
|
@ -1 +1,2 @@
|
|||||||
export { default } from './EvolutionSpecies';
|
export { default } from './EvolutionSpecies';
|
||||||
|
export * from './EvolutionSpecies';
|
||||||
|
@ -36,14 +36,14 @@ export const Duduo: Story = {
|
|||||||
evolutionChain: [
|
evolutionChain: [
|
||||||
{
|
{
|
||||||
types: ['normal', 'flying'],
|
types: ['normal', 'flying'],
|
||||||
image:
|
image_url:
|
||||||
'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/dream-world/84.svg',
|
'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/dream-world/84.svg',
|
||||||
name: 'Doduo',
|
name: 'Doduo',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Dodrio',
|
name: 'Dodrio',
|
||||||
types: ['normal', 'flying'],
|
types: ['normal', 'flying'],
|
||||||
image:
|
image_url:
|
||||||
'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/dream-world/85.svg',
|
'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/dream-world/85.svg',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -7,7 +7,9 @@ import { findPokeTypeAsset } from 'components/PokemonTypes';
|
|||||||
import { colorTypeGradients } from 'components/utils';
|
import { colorTypeGradients } from 'components/utils';
|
||||||
import GenderRate from 'components/GenderRate';
|
import GenderRate from 'components/GenderRate';
|
||||||
import Delayed from 'components/Delayed';
|
import Delayed from 'components/Delayed';
|
||||||
import EvolutionSpecies from 'components/EvolutionSpecies';
|
import EvolutionSpecies, {
|
||||||
|
EvolutionSpeciesProps,
|
||||||
|
} from 'components/EvolutionSpecies';
|
||||||
|
|
||||||
interface Stat {
|
interface Stat {
|
||||||
stat__name: string;
|
stat__name: string;
|
||||||
@ -27,7 +29,7 @@ export interface InfoDialogComponentProps {
|
|||||||
description: string;
|
description: string;
|
||||||
abilities: string[];
|
abilities: string[];
|
||||||
stats: Stat[];
|
stats: Stat[];
|
||||||
evolutionChain: { types: string[]; image: string; name: string }[];
|
evolutionChain: EvolutionSpeciesProps[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const InfoDialog = ({
|
const InfoDialog = ({
|
||||||
@ -171,7 +173,7 @@ const InfoDialog = ({
|
|||||||
>
|
>
|
||||||
<EvolutionSpecies
|
<EvolutionSpecies
|
||||||
types={evo.types}
|
types={evo.types}
|
||||||
image_url={evo.image}
|
image_url={evo.image_url}
|
||||||
name={evo.name}
|
name={evo.name}
|
||||||
/>
|
/>
|
||||||
{evolutionChain.indexOf(evo) + 1 &&
|
{evolutionChain.indexOf(evo) + 1 &&
|
||||||
|
@ -1 +1,2 @@
|
|||||||
export { default } from './InfoDialogComponent';
|
export { default } from './InfoDialogComponent';
|
||||||
|
export type { InfoDialogComponentProps } from './InfoDialogComponent';
|
||||||
|
@ -1,131 +1,52 @@
|
|||||||
import { Dialog, DialogContent, Tooltip, Zoom } from '@mui/material';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
import { findPokeTypeAsset } from 'components/PokemonTypes';
|
import { useAppDispatch, useAppSelector } from 'app/hooks';
|
||||||
import { colorTypeGradients } from 'components/utils';
|
|
||||||
import GenderRate from 'components/GenderRate';
|
import InfoDialogComponent from 'components/InfoDialogComponent';
|
||||||
|
import {
|
||||||
|
useGetPokemonQuery,
|
||||||
|
useGetPokemonSpeciesQuery,
|
||||||
|
useGetEvolutionChainQuery,
|
||||||
|
} from 'app/services/pokeApi';
|
||||||
|
import { setPokemonSpeciesIdToFetch } from './infoDialogSlice';
|
||||||
|
|
||||||
export interface InfoDialogProps {
|
export interface InfoDialogProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
cancel: boolean;
|
pokemonId: string | number;
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
genere: string;
|
|
||||||
types: string[];
|
|
||||||
height: number;
|
|
||||||
weight: number;
|
|
||||||
genderRatio: number;
|
|
||||||
description: string;
|
|
||||||
abilities: string[];
|
|
||||||
stats: {
|
|
||||||
hp: number;
|
|
||||||
attack: number;
|
|
||||||
defense: number;
|
|
||||||
spAttack: number;
|
|
||||||
spDefense: number;
|
|
||||||
speed: number;
|
|
||||||
};
|
|
||||||
image: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const InfoDialog = (props: InfoDialogProps) => {
|
const InfoDialog = ({ pokemonId }: InfoDialogProps) => {
|
||||||
let finalColor;
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
if (props.types.length === 2) {
|
const isOpen = useAppSelector(state => state.infoDialog.isOpen);
|
||||||
finalColor = colorTypeGradients(
|
const skipGetPokemonSpeciesQuery = useAppSelector(
|
||||||
props.types[0],
|
state => state.infoDialog.skipGetPokemonSpeciesQuery,
|
||||||
props.types[1],
|
|
||||||
props.types.length,
|
|
||||||
);
|
);
|
||||||
} else {
|
const skipGetEvolutionChainQuery = useAppSelector(
|
||||||
finalColor = colorTypeGradients(
|
state => state.infoDialog.skipGetEvolutionChainQuery,
|
||||||
props.types[0],
|
);
|
||||||
props.types[0],
|
const selectedPokemonId = useAppSelector(
|
||||||
props.types.length,
|
state => state.infoDialog.selectedPokemonId,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<Dialog
|
<InfoDialogComponent
|
||||||
aria-labelledby="customized-dialog-title"
|
openDialog={isOpen}
|
||||||
open={props.open}
|
id={selectedPokemonId}
|
||||||
fullWidth
|
name={}
|
||||||
maxWidth="md"
|
types={}
|
||||||
className="dialog__bg noselect"
|
genera={}
|
||||||
>
|
image={}
|
||||||
<DialogContent
|
height={}
|
||||||
style={{
|
weight={}
|
||||||
background: `linear-gradient(${finalColor[0]}, ${finalColor[1]})`,
|
genderRatio={}
|
||||||
}}
|
description={}
|
||||||
className="dialog__content"
|
abilities={}
|
||||||
>
|
stats={}
|
||||||
<div className="info__container">
|
evolutionChain={}
|
||||||
<div className="info__container__img">
|
/>
|
||||||
<div className="pokemon__id">
|
</>
|
||||||
#{String(props.id).padStart(3, '0')}
|
|
||||||
</div>
|
|
||||||
<div className="pokemon__name">{props.name}</div>
|
|
||||||
<div
|
|
||||||
className="pokemon__genera"
|
|
||||||
style={{ background: finalColor[0] }}
|
|
||||||
>
|
|
||||||
{props.genere}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<img src={props.image} alt="poke-img" />
|
|
||||||
</div>
|
|
||||||
<div className="info__container__data__type">
|
|
||||||
{props.types.map(type => (
|
|
||||||
<Tooltip
|
|
||||||
title={type}
|
|
||||||
key={type}
|
|
||||||
TransitionComponent={Zoom}
|
|
||||||
arrow
|
|
||||||
>
|
|
||||||
<div className={`poke__type__bg ${type}`}>
|
|
||||||
<img src={findPokeTypeAsset(type)} alt="poke-type" />
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="dimensions">
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
className="info__container__headings"
|
|
||||||
style={{ fontSize: '20px' }}
|
|
||||||
>
|
|
||||||
Height
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
className="info__container__headings"
|
|
||||||
style={{ fontSize: '20px' }}
|
|
||||||
>
|
|
||||||
Weight
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="gender__container">
|
|
||||||
{props.genderRatio === -1 ? (
|
|
||||||
'Genderless'
|
|
||||||
) : (
|
|
||||||
<GenderRate genderRatio={props.genderRatio} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="info__container__data">
|
|
||||||
<div className={'right__box'}>
|
|
||||||
<div>
|
|
||||||
<div className={'info__container__headings'}>About</div>
|
|
||||||
<div className={'desc'}>{props.description}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
67
src/features/InfoDialog/infoDialogSlice.ts
Normal file
67
src/features/InfoDialog/infoDialogSlice.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
import type { Slice, PayloadAction } from '@reduxjs/toolkit';
|
||||||
|
import { buildDevCheckHandler } from '@reduxjs/toolkit/dist/query/core/buildMiddleware/devMiddleware';
|
||||||
|
import { useAppSelector } from '../../app/hooks';
|
||||||
|
import { pokeApi } from '../../app/services/pokeApi';
|
||||||
|
import { PokemonResponseData } from '../../types/api';
|
||||||
|
|
||||||
|
export type InfoDialogStateProps = {
|
||||||
|
isOpen: boolean;
|
||||||
|
skipGetPokemonSpeciesQuery: boolean;
|
||||||
|
skipGetEvolutionChainQuery: boolean;
|
||||||
|
selectedPokemonId: number;
|
||||||
|
pokemonSpeciesIdToFetch: number;
|
||||||
|
evolutionChainIdToFetch: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const initialState: InfoDialogStateProps = {
|
||||||
|
isOpen: false,
|
||||||
|
skipGetPokemonSpeciesQuery: false,
|
||||||
|
skipGetEvolutionChainQuery: false,
|
||||||
|
selectedPokemonId: 0,
|
||||||
|
pokemonSpeciesIdToFetch: 0,
|
||||||
|
evolutionChainIdToFetch: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const infoDialogSlice: Slice<InfoDialogStateProps> = createSlice({
|
||||||
|
name: 'infoDialog',
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
setIsOpen: (state, action: PayloadAction<boolean>) => {
|
||||||
|
state.isOpen = action.payload;
|
||||||
|
},
|
||||||
|
setSkipGetPokemonSpeciesQuery: (state, action: PayloadAction<boolean>) => {
|
||||||
|
state.skipGetPokemonSpeciesQuery = action.payload;
|
||||||
|
},
|
||||||
|
setSkipGetEvolutionChainQuery: (state, action: PayloadAction<boolean>) => {
|
||||||
|
state.skipGetEvolutionChainQuery = action.payload;
|
||||||
|
},
|
||||||
|
setSelectedPokemonId: (state, action: PayloadAction<number>) => {
|
||||||
|
state.selectedPokemonId = action.payload;
|
||||||
|
},
|
||||||
|
setPokemonSpeciesIdToFetch: (state, action: PayloadAction<number>) => {
|
||||||
|
state.pokemonSpeciesIdToFetch = action.payload;
|
||||||
|
},
|
||||||
|
setEvolutionChainIdToFetch: (state, action: PayloadAction<number>) => {
|
||||||
|
state.evolutionChainIdToFetch = action.payload;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const {
|
||||||
|
setIsOpen,
|
||||||
|
setSkipGetPokemonSpeciesQuery,
|
||||||
|
setSkipGetEvolutionChainQuery,
|
||||||
|
setSelectedPokemonId,
|
||||||
|
setPokemonSpeciesIdToFetch,
|
||||||
|
setEvolutionChainIdToFetch,
|
||||||
|
} = infoDialogSlice.actions;
|
||||||
|
|
||||||
|
export default infoDialogSlice.reducer;
|
||||||
|
|
||||||
|
const fetchSelectedPokemonInfo = () => async (dispatch: any, getState: any) => {
|
||||||
|
dispatch(setIsOpen(true));
|
||||||
|
const selectedPokemonId = getState().InfoDialog.selectedPokemonId;
|
||||||
|
const { data: selectedPokemon } =
|
||||||
|
pokeApi.useGetPokemonQuery(selectedPokemonId);
|
||||||
|
};
|
@ -68,7 +68,7 @@ export type PokemonSpeciesResponseData = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type EvolutionChain = {
|
export type EvolutionChain = {
|
||||||
evolves_to: EvolutionChain[];
|
evolves_to: EvolutionChain[];
|
||||||
species: {
|
species: {
|
||||||
name: string;
|
name: string;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user