Implement onClick action in EvolutionSpecies.tsx, and fix all related storybook

develop
Jason Zhu 2023-05-20 15:07:12 +10:00
parent 99fd0577fd
commit 8f217d678a
4 changed files with 144 additions and 4 deletions

View File

@ -1,16 +1,81 @@
import { Provider } from 'react-redux';
import { configureStore, createSlice } from '@reduxjs/toolkit';
import type { Meta, StoryObj } from '@storybook/react';
import EvolutionSpecies from './EvolutionSpecies';
import { InfoDialogStateProps } from 'features/InfoDialog/infoDialogSlice';
const MockedState = {
// Copied from Redux DevTools from browser
infoDialog: {
isOpen: false,
InfoDialogDetails: {
id: 0,
name: '',
genera: '',
image: '',
types: [],
height: 0,
weight: 0,
genderRatio: 0,
description: '',
abilities: [],
stats: [],
evolutionChain: [],
},
},
};
interface MockStoreProps {
InfoDialogState: InfoDialogStateProps;
children: React.ReactNode;
}
const mockSlice = (infoDialogState: {
InfoDialogState: InfoDialogStateProps;
}) => {
return createSlice({
name: 'infoDialog',
initialState: infoDialogState,
reducers: {},
});
};
const mockStore = (infoDialogState: {
InfoDialogState: InfoDialogStateProps;
}) => {
return configureStore({
reducer: {
infoDialog: mockSlice(infoDialogState).reducer,
},
});
};
const Mockstore: React.FC<MockStoreProps> = ({ InfoDialogState, children }) => (
<Provider store={mockStore({ InfoDialogState })}>{children}</Provider>
);
const meta: Meta<typeof EvolutionSpecies> = {
title: 'Component/EvolutionSpecies',
component: EvolutionSpecies,
decorators: [
(story: () => React.ReactNode) => (
<div style={{ padding: '3rem' }}>{story()}</div>
),
],
tags: ['autodocs'],
excludeStories: /.*MockedState$/,
};
export default meta;
type Story = StoryObj<typeof EvolutionSpecies>;
export const Bulbasaur: Story = {
decorators: [
(story: () => React.ReactNode) => (
<Mockstore InfoDialogState={MockedState.infoDialog}>{story()}</Mockstore>
),
],
args: {
types: ['grass', 'poison'],
image_url:
@ -20,6 +85,11 @@ export const Bulbasaur: Story = {
};
export const Magneton: Story = {
decorators: [
(story: () => React.ReactNode) => (
<Mockstore InfoDialogState={MockedState.infoDialog}>{story()}</Mockstore>
),
],
args: {
types: ['electric', 'steel'],
image_url:

View File

@ -3,18 +3,22 @@ import { motion } from 'framer-motion';
import './EvolutionSpecies.css';
import { LazyLoadImage } from 'react-lazy-load-image-component';
import { colorTypeGradients } from 'components/utils';
import { useAppDispatch } from '../../app/hooks';
import { fetchSelectedPokemonInfo } from '../../features/InfoDialog/infoDialogSlice';
export interface EvolutionSpeciesProps {
export type EvolutionSpeciesProps = {
types: string[];
name: string;
image_url: string;
}
};
const EvolutionSpecies = ({
types,
name,
image_url,
}: EvolutionSpeciesProps) => {
const dispatch = useAppDispatch();
const finalColor = colorTypeGradients(types);
return (
@ -47,6 +51,7 @@ const EvolutionSpecies = ({
delayMethod={'debounce'}
effect={'blur'}
className={'evo_img'}
onClick={() => dispatch(fetchSelectedPokemonInfo(name))}
/>
</div>
</div>

View File

@ -1,16 +1,81 @@
import { Provider } from 'react-redux';
import { configureStore, createSlice } from '@reduxjs/toolkit';
import type { Meta, StoryObj } from '@storybook/react';
import InfoDialogComponent from './InfoDialogComponent';
import { InfoDialogStateProps } from 'features/InfoDialog/infoDialogSlice';
const MockedState = {
// Copied from Redux DevTools from browser
infoDialog: {
isOpen: false,
InfoDialogDetails: {
id: 0,
name: '',
genera: '',
image: '',
types: [],
height: 0,
weight: 0,
genderRatio: 0,
description: '',
abilities: [],
stats: [],
evolutionChain: [],
},
},
};
interface MockStoreProps {
InfoDialogState: InfoDialogStateProps;
children: React.ReactNode;
}
const mockSlice = (infoDialogState: {
InfoDialogState: InfoDialogStateProps;
}) => {
return createSlice({
name: 'infoDialog',
initialState: infoDialogState,
reducers: {},
});
};
const mockStore = (infoDialogState: {
InfoDialogState: InfoDialogStateProps;
}) => {
return configureStore({
reducer: {
infoDialog: mockSlice(infoDialogState).reducer,
},
});
};
const Mockstore: React.FC<MockStoreProps> = ({ InfoDialogState, children }) => (
<Provider store={mockStore({ InfoDialogState })}>{children}</Provider>
);
const meta: Meta<typeof InfoDialogComponent> = {
title: 'Component/InfoDialogComponent',
component: InfoDialogComponent,
decorators: [
(story: () => React.ReactNode) => (
<div style={{ padding: '3rem' }}>{story()}</div>
),
],
tags: ['autodocs'],
excludeStories: /.*MockedState$/,
};
export default meta;
type Story = StoryObj<typeof InfoDialogComponent>;
export const Duduo: Story = {
decorators: [
(story: () => React.ReactNode) => (
<Mockstore InfoDialogState={MockedState.infoDialog}>{story()}</Mockstore>
),
],
args: {
openDialog: true,
id: 84,

View File

@ -114,12 +114,12 @@ export const constructPokemonInfoFromResponses = (
export const fetchSelectedPokemonInfo = createAsyncThunk(
'infoDialog/fetchSelectedPokemonInfo',
async (pokemonId: number, thunkAPI) => {
async (pokemonIdOrName: number | string, thunkAPI) => {
const dispatch = thunkAPI.dispatch;
try {
const selectedPokemon = await dispatch(
pokeApi.endpoints.getPokemon.initiate(pokemonId),
pokeApi.endpoints.getPokemon.initiate(pokemonIdOrName),
);
if (selectedPokemon.data) {