set ivs
This commit is contained in:
parent
f887b3e13e
commit
5ba1d48c7a
@ -7,6 +7,8 @@ import * as ActionsPokemonExplorer from './components/PokemonExplorer/actions';
|
|||||||
import * as ActionsPokemonSelectList from './components/PokemonSelectList/actions';
|
import * as ActionsPokemonSelectList from './components/PokemonSelectList/actions';
|
||||||
import { ThunkDispatchPokemonSelectList } from './types';
|
import { ThunkDispatchPokemonSelectList } from './types';
|
||||||
|
|
||||||
|
import { IndividualValueKey } from './components/PokemonExplorer/types';
|
||||||
|
|
||||||
import { PokemonExplorer } from './components/PokemonExplorer/PokemonExplorer';
|
import { PokemonExplorer } from './components/PokemonExplorer/PokemonExplorer';
|
||||||
import { PokemonSelectList } from './components/PokemonSelectList/PokemonSelectList';
|
import { PokemonSelectList } from './components/PokemonSelectList/PokemonSelectList';
|
||||||
|
|
||||||
@ -32,6 +34,7 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
|
|||||||
pokemonList,
|
pokemonList,
|
||||||
} = this.props.pokemonSelectListState;
|
} = this.props.pokemonSelectListState;
|
||||||
const {
|
const {
|
||||||
|
individualValues,
|
||||||
leaguePokemon,
|
leaguePokemon,
|
||||||
} = this.props.pokemonExplorerState;
|
} = this.props.pokemonExplorerState;
|
||||||
|
|
||||||
@ -41,19 +44,21 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
|
|||||||
isLoading={ this.props.pokemonSelectListState.isLoading }
|
isLoading={ this.props.pokemonSelectListState.isLoading }
|
||||||
activePokemonIndex={ activePokemonIndex }
|
activePokemonIndex={ activePokemonIndex }
|
||||||
pokemonList={ pokemonList }
|
pokemonList={ pokemonList }
|
||||||
onActivatePokemon={ this.onActivatePokemon }
|
handleActivatePokemon={ this.handleActivatePokemon }
|
||||||
/>
|
/>
|
||||||
{ leaguePokemon !== null &&
|
{ leaguePokemon !== null &&
|
||||||
<PokemonExplorer
|
<PokemonExplorer
|
||||||
isLoading={ this.props.pokemonExplorerState.isLoading }
|
isLoading={ this.props.pokemonExplorerState.isLoading }
|
||||||
leaguePokemon={ leaguePokemon }
|
leaguePokemon={ leaguePokemon }
|
||||||
|
individualValues={ individualValues }
|
||||||
|
handleChangeIndividualValue={ this.handleChangeIndividualValue }
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly onActivatePokemon = (pokemonIndex : number) => {
|
private readonly handleActivatePokemon = (pokemonIndex : number) => {
|
||||||
const { dispatch, pokemonSelectListState } = this.props;
|
const { dispatch, pokemonSelectListState } = this.props;
|
||||||
const pokemonId = pokemonSelectListState.pokemonList[pokemonIndex].id;
|
const pokemonId = pokemonSelectListState.pokemonList[pokemonIndex].id;
|
||||||
|
|
||||||
@ -69,6 +74,27 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
|
|||||||
})
|
})
|
||||||
.then(() => dispatch(ActionsPokemonExplorer.setIsLoading(false)));
|
.then(() => dispatch(ActionsPokemonExplorer.setIsLoading(false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly handleChangeIndividualValue = (stat : IndividualValueKey, value : number | null) => {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
|
||||||
|
switch (stat) {
|
||||||
|
case 'level':
|
||||||
|
dispatch(ActionsPokemonExplorer.setIvLevel(value));
|
||||||
|
break;
|
||||||
|
case 'hp':
|
||||||
|
dispatch(ActionsPokemonExplorer.setIvHp(value));
|
||||||
|
break;
|
||||||
|
case 'atk':
|
||||||
|
dispatch(ActionsPokemonExplorer.setIvAtk(value));
|
||||||
|
break;
|
||||||
|
case 'def':
|
||||||
|
dispatch(ActionsPokemonExplorer.setIvDef(value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state : ReturnType<typeof appReducers>) : PokemonAppProps => {
|
const mapStateToProps = (state : ReturnType<typeof appReducers>) : PokemonAppProps => {
|
||||||
|
|||||||
@ -2,16 +2,157 @@ import React from 'react';
|
|||||||
|
|
||||||
import { ILeaguePokemon } from 'app/models/Pokemon';
|
import { ILeaguePokemon } from 'app/models/Pokemon';
|
||||||
|
|
||||||
export interface IPokemonSelectListProps {
|
import { IIndividualValues, IndividualValueKey } from './types';
|
||||||
|
|
||||||
|
export interface IPokemonExplorerProps {
|
||||||
isLoading : boolean;
|
isLoading : boolean;
|
||||||
leaguePokemon : ILeaguePokemon;
|
leaguePokemon : ILeaguePokemon;
|
||||||
|
individualValues : IIndividualValues;
|
||||||
|
|
||||||
|
handleChangeIndividualValue : (stat : IndividualValueKey, value : number | null) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonExplorer extends React.Component<IPokemonSelectListProps, IState> {
|
export class PokemonExplorer extends React.Component<IPokemonExplorerProps, IState> {
|
||||||
|
private readonly MIN_LEVEL = 1;
|
||||||
|
private readonly MAX_LEVEL = 40;
|
||||||
|
private readonly MIN_IV = 0;
|
||||||
|
private readonly MAX_IV = 15;
|
||||||
|
|
||||||
|
private onChangeHp : (event : React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
|
private onChangeAtk : (event : React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
|
private onChangeDef : (event : React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
|
|
||||||
|
constructor(props : IPokemonExplorerProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.onChangeHp = this.onChangeIvFactory('hp');
|
||||||
|
this.onChangeAtk = this.onChangeIvFactory('atk');
|
||||||
|
this.onChangeDef = this.onChangeIvFactory('def');
|
||||||
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return (<div>{ this.props.leaguePokemon.name }</div>);
|
const {
|
||||||
|
individualValues,
|
||||||
|
leaguePokemon
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const placeholderLevel = '40';
|
||||||
|
const placeholderHp = '15';
|
||||||
|
const placeholderAtk = '15';
|
||||||
|
const placeholderDef = '15';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="pokemon-explorer">
|
||||||
|
<h2 className="pokemon-info">
|
||||||
|
<span>{ this.formatDexNumber(leaguePokemon.dex) }</span>
|
||||||
|
{ leaguePokemon.name }
|
||||||
|
</h2>
|
||||||
|
<div className="pokemon-base-stats">
|
||||||
|
<div>Base Stats</div>
|
||||||
|
<div className="pokemon-type type-1">{ }</div>
|
||||||
|
<div className="pokemon-type type-2">{ }</div>
|
||||||
|
<div>{ leaguePokemon.stats.baseStamina }</div>
|
||||||
|
<div>{ leaguePokemon.stats.baseAttack }</div>
|
||||||
|
<div>{ leaguePokemon.stats.baseDefense }</div>
|
||||||
|
</div>
|
||||||
|
<div className="pokemon-individual-stats">
|
||||||
|
<div>
|
||||||
|
<h5>Level</h5>
|
||||||
|
<input
|
||||||
|
name="level"
|
||||||
|
type="number"
|
||||||
|
min={ this.MIN_LEVEL }
|
||||||
|
max={ this.MAX_LEVEL }
|
||||||
|
maxLength={ 2 }
|
||||||
|
onChange={ this.onChangeLevel }
|
||||||
|
value={ individualValues.level || '' }
|
||||||
|
placeholder={ placeholderLevel }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h5>IVs</h5>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
name="hp"
|
||||||
|
type="number"
|
||||||
|
min={ this.MIN_IV }
|
||||||
|
max={ this.MAX_IV }
|
||||||
|
maxLength={ 2 }
|
||||||
|
onChange={ this.onChangeHp }
|
||||||
|
value={ individualValues.hp || '' }
|
||||||
|
placeholder={ placeholderHp }
|
||||||
|
/> HP
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
name="atk"
|
||||||
|
type="number"
|
||||||
|
min={ this.MIN_IV }
|
||||||
|
max={ this.MAX_IV }
|
||||||
|
maxLength={ 2 }
|
||||||
|
onChange={ this.onChangeAtk }
|
||||||
|
value={ individualValues.atk || '' }
|
||||||
|
placeholder={ placeholderAtk }
|
||||||
|
/> ATK
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
name="def"
|
||||||
|
type="number"
|
||||||
|
min={ this.MIN_IV }
|
||||||
|
max={ this.MAX_IV }
|
||||||
|
maxLength={ 2 }
|
||||||
|
onChange={ this.onChangeDef }
|
||||||
|
value={ individualValues.def || '' }
|
||||||
|
placeholder={ placeholderDef }
|
||||||
|
/> DEF
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="league-pokemon-rank">
|
||||||
|
<div className="league-pokemon-stat pokemon-rank"><span>{ }</span> Rank</div>
|
||||||
|
<div className="league-pokemon-stat pokemon-cp">CP <span>{ }</span></div>
|
||||||
|
<div className="league-pokemon-stat"><span>{ }</span> HP</div>
|
||||||
|
<div className="league-pokemon-stat"><span>{ }</span> ATK</div>
|
||||||
|
<div className="league-pokemon-stat"><span>{ }</span> DEF</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private formatDexNumber(dex : number) {
|
||||||
|
let prefix : string = '#';
|
||||||
|
if (dex < 100) {
|
||||||
|
prefix += '0';
|
||||||
|
}
|
||||||
|
if (dex < 10) {
|
||||||
|
prefix += '0';
|
||||||
|
}
|
||||||
|
return prefix + dex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly onChangeLevel = (event : React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const raw = event.currentTarget.value;
|
||||||
|
const value = parseInt(raw, 10);
|
||||||
|
if (raw === '' + value && value >= this.MIN_LEVEL && value <= this.MAX_LEVEL) {
|
||||||
|
this.props.handleChangeIndividualValue('level', value);
|
||||||
|
} else if (raw === '') {
|
||||||
|
this.props.handleChangeIndividualValue('level', null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly onChangeIvFactory = (type : IndividualValueKey) => {
|
||||||
|
return (event : React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const raw = event.currentTarget.value;
|
||||||
|
const value = parseInt(raw, 10);
|
||||||
|
if (raw === '' + value && value >= this.MIN_IV && value <= this.MAX_IV) {
|
||||||
|
this.props.handleChangeIndividualValue(type, value);
|
||||||
|
} else if (raw === '') {
|
||||||
|
this.props.handleChangeIndividualValue(type, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,3 +7,11 @@ import { ILeaguePokemon } from 'app/models/Pokemon';
|
|||||||
export const setIsLoading = (isLoading : boolean) => action(PokemonExplorerActionTypes.SET_IS_LOADING, { isLoading });
|
export const setIsLoading = (isLoading : boolean) => action(PokemonExplorerActionTypes.SET_IS_LOADING, { isLoading });
|
||||||
|
|
||||||
export const setLeaguePokemon = (leaguePokemon : ILeaguePokemon | null) => action(PokemonExplorerActionTypes.SET_LEAGUE_POKEMON, { leaguePokemon });
|
export const setLeaguePokemon = (leaguePokemon : ILeaguePokemon | null) => action(PokemonExplorerActionTypes.SET_LEAGUE_POKEMON, { leaguePokemon });
|
||||||
|
|
||||||
|
export const setIvLevel = (level : number | null) => action(PokemonExplorerActionTypes.SET_IV_LEVEL, { level });
|
||||||
|
|
||||||
|
export const setIvHp = (hp : number | null) => action(PokemonExplorerActionTypes.SET_IV_HP, { hp });
|
||||||
|
|
||||||
|
export const setIvAtk = (atk : number | null) => action(PokemonExplorerActionTypes.SET_IV_ATK, { atk });
|
||||||
|
|
||||||
|
export const setIvDef = (def : number | null) => action(PokemonExplorerActionTypes.SET_IV_DEF, { def });
|
||||||
|
|||||||
@ -6,6 +6,12 @@ import { IPokemonExplorerState, PokemonExplorerActionTypes } from './types';
|
|||||||
export const initialState : IPokemonExplorerState = {
|
export const initialState : IPokemonExplorerState = {
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
leaguePokemon: null,
|
leaguePokemon: null,
|
||||||
|
individualValues: {
|
||||||
|
level: null,
|
||||||
|
hp: null,
|
||||||
|
atk: null,
|
||||||
|
def: null,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reduceSetIsLoading = (
|
const reduceSetIsLoading = (
|
||||||
@ -24,6 +30,50 @@ const reduceSetLeaguePokemon = (
|
|||||||
leaguePokemon: action.payload.leaguePokemon,
|
leaguePokemon: action.payload.leaguePokemon,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const reduceSetIvLevel = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setIvLevel>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
individualValues: {
|
||||||
|
...state.individualValues,
|
||||||
|
level: action.payload.level,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const reduceSetIvHp = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setIvHp>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
individualValues: {
|
||||||
|
...state.individualValues,
|
||||||
|
hp: action.payload.hp,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const reduceSetIvAtk = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setIvAtk>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
individualValues: {
|
||||||
|
...state.individualValues,
|
||||||
|
atk: action.payload.atk,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const reduceSetIvDef = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setIvDef>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
individualValues: {
|
||||||
|
...state.individualValues,
|
||||||
|
def: action.payload.def,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
||||||
state : IPokemonExplorerState = initialState,
|
state : IPokemonExplorerState = initialState,
|
||||||
action,
|
action,
|
||||||
@ -33,6 +83,14 @@ export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
|||||||
return reduceSetIsLoading(state, action as ReturnType<typeof Actions.setIsLoading>);
|
return reduceSetIsLoading(state, action as ReturnType<typeof Actions.setIsLoading>);
|
||||||
case PokemonExplorerActionTypes.SET_LEAGUE_POKEMON:
|
case PokemonExplorerActionTypes.SET_LEAGUE_POKEMON:
|
||||||
return reduceSetLeaguePokemon(state, action as ReturnType<typeof Actions.setLeaguePokemon>);
|
return reduceSetLeaguePokemon(state, action as ReturnType<typeof Actions.setLeaguePokemon>);
|
||||||
|
case PokemonExplorerActionTypes.SET_IV_LEVEL:
|
||||||
|
return reduceSetIvLevel(state, action as ReturnType<typeof Actions.setIvLevel>);
|
||||||
|
case PokemonExplorerActionTypes.SET_IV_HP:
|
||||||
|
return reduceSetIvHp(state, action as ReturnType<typeof Actions.setIvHp>);
|
||||||
|
case PokemonExplorerActionTypes.SET_IV_ATK:
|
||||||
|
return reduceSetIvAtk(state, action as ReturnType<typeof Actions.setIvAtk>);
|
||||||
|
case PokemonExplorerActionTypes.SET_IV_DEF:
|
||||||
|
return reduceSetIvDef(state, action as ReturnType<typeof Actions.setIvDef>);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,24 @@
|
|||||||
import { ILeaguePokemon } from 'app/models/Pokemon';
|
import { ILeaguePokemon } from 'app/models/Pokemon';
|
||||||
|
|
||||||
|
export type IndividualValueKey = 'level' | 'hp' | 'atk' | 'def';
|
||||||
|
export interface IIndividualValues {
|
||||||
|
level : number | null;
|
||||||
|
hp : number | null;
|
||||||
|
atk : number | null;
|
||||||
|
def : number | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IPokemonExplorerState {
|
export interface IPokemonExplorerState {
|
||||||
isLoading : boolean;
|
isLoading : boolean;
|
||||||
leaguePokemon : ILeaguePokemon | null;
|
leaguePokemon : ILeaguePokemon | null;
|
||||||
|
individualValues : IIndividualValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PokemonExplorerActionTypes = {
|
export const PokemonExplorerActionTypes = {
|
||||||
SET_IS_LOADING: 'POKEMON_EXPLORER/SET_IS_LOADING',
|
SET_IS_LOADING: 'POKEMON_EXPLORER/SET_IS_LOADING',
|
||||||
SET_LEAGUE_POKEMON: 'POKEMON_EXPLORER/SET_LEAGUE_POKEMON',
|
SET_LEAGUE_POKEMON: 'POKEMON_EXPLORER/SET_LEAGUE_POKEMON',
|
||||||
|
SET_IV_LEVEL: 'POKEMON_EXPLORER/SET_IV_LEVEL',
|
||||||
|
SET_IV_HP: 'POKEMON_EXPLORER/SET_IV_HP',
|
||||||
|
SET_IV_ATK: 'POKEMON_EXPLORER/SET_IV_ATK',
|
||||||
|
SET_IV_DEF: 'POKEMON_EXPLORER/SET_IV_DEF',
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export interface IPokemonSelectListProps {
|
|||||||
activePokemonIndex : number | null;
|
activePokemonIndex : number | null;
|
||||||
pokemonList : Array<IPokemon>;
|
pokemonList : Array<IPokemon>;
|
||||||
|
|
||||||
onActivatePokemon : (index : number) => void;
|
handleActivatePokemon : (index : number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
@ -51,7 +51,7 @@ export class PokemonSelectList extends React.Component<IPokemonSelectListProps,
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ classes } style={ { height: '400px' } }>
|
<div id="pokemon-select-list" className={ classes } style={ { height: '400px' } }>
|
||||||
<Measure
|
<Measure
|
||||||
bounds={ true }
|
bounds={ true }
|
||||||
onResize={ onResize }
|
onResize={ onResize }
|
||||||
@ -80,7 +80,7 @@ export class PokemonSelectList extends React.Component<IPokemonSelectListProps,
|
|||||||
const css = classNames({
|
const css = classNames({
|
||||||
active: this.props.activePokemonIndex === index
|
active: this.props.activePokemonIndex === index
|
||||||
});
|
});
|
||||||
const onClick = () => this.props.onActivatePokemon(index);
|
const onClick = () => this.props.handleActivatePokemon(index);
|
||||||
return <div key={ index } style={ style } className={ css } onClick={ onClick }>{ pokemon.name }</div>;
|
return <div key={ index } style={ style } className={ css } onClick={ onClick }>{ pokemon.name }</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user