From 5ba1d48c7a485df24fc6d5add1d1e027fadecd84 Mon Sep 17 00:00:00 2001 From: Jeff Colombo Date: Sat, 19 Jan 2019 20:34:46 -0500 Subject: [PATCH] set ivs --- src/ts/app/PokemonApp.tsx | 30 +++- .../PokemonExplorer/PokemonExplorer.tsx | 147 +++++++++++++++++- .../app/components/PokemonExplorer/actions.ts | 8 + .../components/PokemonExplorer/reducers.ts | 58 +++++++ .../app/components/PokemonExplorer/types.ts | 13 ++ .../PokemonSelectList/PokemonSelectList.tsx | 6 +- 6 files changed, 254 insertions(+), 8 deletions(-) diff --git a/src/ts/app/PokemonApp.tsx b/src/ts/app/PokemonApp.tsx index 69547a7..83616c9 100644 --- a/src/ts/app/PokemonApp.tsx +++ b/src/ts/app/PokemonApp.tsx @@ -7,6 +7,8 @@ import * as ActionsPokemonExplorer from './components/PokemonExplorer/actions'; import * as ActionsPokemonSelectList from './components/PokemonSelectList/actions'; import { ThunkDispatchPokemonSelectList } from './types'; +import { IndividualValueKey } from './components/PokemonExplorer/types'; + import { PokemonExplorer } from './components/PokemonExplorer/PokemonExplorer'; import { PokemonSelectList } from './components/PokemonSelectList/PokemonSelectList'; @@ -32,6 +34,7 @@ class PokemonApp extends React.Component { pokemonList, } = this.props.pokemonSelectListState; const { + individualValues, leaguePokemon, } = this.props.pokemonExplorerState; @@ -41,19 +44,21 @@ class PokemonApp extends React.Component { isLoading={ this.props.pokemonSelectListState.isLoading } activePokemonIndex={ activePokemonIndex } pokemonList={ pokemonList } - onActivatePokemon={ this.onActivatePokemon } + handleActivatePokemon={ this.handleActivatePokemon } /> { leaguePokemon !== null && } ); } - private readonly onActivatePokemon = (pokemonIndex : number) => { + private readonly handleActivatePokemon = (pokemonIndex : number) => { const { dispatch, pokemonSelectListState } = this.props; const pokemonId = pokemonSelectListState.pokemonList[pokemonIndex].id; @@ -69,6 +74,27 @@ class PokemonApp extends React.Component { }) .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) : PokemonAppProps => { diff --git a/src/ts/app/components/PokemonExplorer/PokemonExplorer.tsx b/src/ts/app/components/PokemonExplorer/PokemonExplorer.tsx index 949c6d8..a0eb401 100644 --- a/src/ts/app/components/PokemonExplorer/PokemonExplorer.tsx +++ b/src/ts/app/components/PokemonExplorer/PokemonExplorer.tsx @@ -2,16 +2,157 @@ import React from 'react'; import { ILeaguePokemon } from 'app/models/Pokemon'; -export interface IPokemonSelectListProps { +import { IIndividualValues, IndividualValueKey } from './types'; + +export interface IPokemonExplorerProps { isLoading : boolean; leaguePokemon : ILeaguePokemon; + individualValues : IIndividualValues; + + handleChangeIndividualValue : (stat : IndividualValueKey, value : number | null) => void; } interface IState { } -export class PokemonExplorer extends React.Component { +export class PokemonExplorer extends React.Component { + 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) => void; + private onChangeAtk : (event : React.ChangeEvent) => void; + private onChangeDef : (event : React.ChangeEvent) => void; + + constructor(props : IPokemonExplorerProps) { + super(props); + + this.onChangeHp = this.onChangeIvFactory('hp'); + this.onChangeAtk = this.onChangeIvFactory('atk'); + this.onChangeDef = this.onChangeIvFactory('def'); + } + public render() { - return (
{ this.props.leaguePokemon.name }
); + const { + individualValues, + leaguePokemon + } = this.props; + + const placeholderLevel = '40'; + const placeholderHp = '15'; + const placeholderAtk = '15'; + const placeholderDef = '15'; + + return ( +
+

+ { this.formatDexNumber(leaguePokemon.dex) } + { leaguePokemon.name } +

+
+
Base Stats
+
{ }
+
{ }
+
{ leaguePokemon.stats.baseStamina }
+
{ leaguePokemon.stats.baseAttack }
+
{ leaguePokemon.stats.baseDefense }
+
+
+
+
Level
+ +
+
+
IVs
+ + + +
+
+
+
{ } Rank
+
CP { }
+
{ } HP
+
{ } ATK
+
{ } DEF
+
+
+ ); + } + + 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) => { + 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) => { + 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); + } + }; } } diff --git a/src/ts/app/components/PokemonExplorer/actions.ts b/src/ts/app/components/PokemonExplorer/actions.ts index 3e227e1..6d2c004 100644 --- a/src/ts/app/components/PokemonExplorer/actions.ts +++ b/src/ts/app/components/PokemonExplorer/actions.ts @@ -7,3 +7,11 @@ import { ILeaguePokemon } from 'app/models/Pokemon'; 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 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 }); diff --git a/src/ts/app/components/PokemonExplorer/reducers.ts b/src/ts/app/components/PokemonExplorer/reducers.ts index 46755f9..5ba31de 100644 --- a/src/ts/app/components/PokemonExplorer/reducers.ts +++ b/src/ts/app/components/PokemonExplorer/reducers.ts @@ -6,6 +6,12 @@ import { IPokemonExplorerState, PokemonExplorerActionTypes } from './types'; export const initialState : IPokemonExplorerState = { isLoading: false, leaguePokemon: null, + individualValues: { + level: null, + hp: null, + atk: null, + def: null, + }, }; const reduceSetIsLoading = ( @@ -24,6 +30,50 @@ const reduceSetLeaguePokemon = ( leaguePokemon: action.payload.leaguePokemon, }); +const reduceSetIvLevel = ( + state : IPokemonExplorerState, + action : ReturnType +) : IPokemonExplorerState => ({ + ...state, + individualValues: { + ...state.individualValues, + level: action.payload.level, + } +}); + +const reduceSetIvHp = ( + state : IPokemonExplorerState, + action : ReturnType +) : IPokemonExplorerState => ({ + ...state, + individualValues: { + ...state.individualValues, + hp: action.payload.hp, + } +}); + +const reduceSetIvAtk = ( + state : IPokemonExplorerState, + action : ReturnType +) : IPokemonExplorerState => ({ + ...state, + individualValues: { + ...state.individualValues, + atk: action.payload.atk, + } +}); + +const reduceSetIvDef = ( + state : IPokemonExplorerState, + action : ReturnType +) : IPokemonExplorerState => ({ + ...state, + individualValues: { + ...state.individualValues, + def: action.payload.def, + } +}); + export const PokemonExplorerReducers : Reducer = ( state : IPokemonExplorerState = initialState, action, @@ -33,6 +83,14 @@ export const PokemonExplorerReducers : Reducer = ( return reduceSetIsLoading(state, action as ReturnType); case PokemonExplorerActionTypes.SET_LEAGUE_POKEMON: return reduceSetLeaguePokemon(state, action as ReturnType); + case PokemonExplorerActionTypes.SET_IV_LEVEL: + return reduceSetIvLevel(state, action as ReturnType); + case PokemonExplorerActionTypes.SET_IV_HP: + return reduceSetIvHp(state, action as ReturnType); + case PokemonExplorerActionTypes.SET_IV_ATK: + return reduceSetIvAtk(state, action as ReturnType); + case PokemonExplorerActionTypes.SET_IV_DEF: + return reduceSetIvDef(state, action as ReturnType); default: return state; } diff --git a/src/ts/app/components/PokemonExplorer/types.ts b/src/ts/app/components/PokemonExplorer/types.ts index 9c6749c..dd57165 100644 --- a/src/ts/app/components/PokemonExplorer/types.ts +++ b/src/ts/app/components/PokemonExplorer/types.ts @@ -1,11 +1,24 @@ 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 { isLoading : boolean; leaguePokemon : ILeaguePokemon | null; + individualValues : IIndividualValues; } export const PokemonExplorerActionTypes = { SET_IS_LOADING: 'POKEMON_EXPLORER/SET_IS_LOADING', 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', }; diff --git a/src/ts/app/components/PokemonSelectList/PokemonSelectList.tsx b/src/ts/app/components/PokemonSelectList/PokemonSelectList.tsx index 352bd5e..9d4d5d9 100644 --- a/src/ts/app/components/PokemonSelectList/PokemonSelectList.tsx +++ b/src/ts/app/components/PokemonSelectList/PokemonSelectList.tsx @@ -11,7 +11,7 @@ export interface IPokemonSelectListProps { activePokemonIndex : number | null; pokemonList : Array; - onActivatePokemon : (index : number) => void; + handleActivatePokemon : (index : number) => void; } interface IState { @@ -51,7 +51,7 @@ export class PokemonSelectList extends React.Component +
this.props.onActivatePokemon(index); + const onClick = () => this.props.handleActivatePokemon(index); return
{ pokemon.name }
; } }