unstyled move selector
This commit is contained in:
parent
db1b91c40f
commit
7af3fa3382
2
dist/db/order.json
vendored
2
dist/db/order.json
vendored
File diff suppressed because one or more lines are too long
2
dist/db/pokemon/MAMOSWINE.json
vendored
2
dist/db/pokemon/MAMOSWINE.json
vendored
File diff suppressed because one or more lines are too long
@ -3,7 +3,7 @@ import POGOProtos from 'pogo-protos';
|
||||
|
||||
import { ApiService } from 'api/ApiService';
|
||||
|
||||
import { IBaseStatsRank, ICombatMoveStats, IPokemon, TypeEffectiveness, TypeOrder } from 'app/models/Pokemon';
|
||||
import { CombatMoveStats, IBaseStatsRank, IPokemon, TypeEffectiveness, TypeOrder } from 'app/models/Pokemon';
|
||||
|
||||
import { LegacyMoves } from 'common/models/LegacyMoves';
|
||||
|
||||
@ -20,7 +20,7 @@ export const parseGameMaster = async () => {
|
||||
const pokemonTypeEffectiveness : Map<POGOProtos.Enums.PokemonType, Map<POGOProtos.Enums.PokemonType, TypeEffectiveness>> = new Map();
|
||||
const pokemonTypeWeaknesses : Map<POGOProtos.Enums.PokemonType, Map<POGOProtos.Enums.PokemonType, TypeEffectiveness>> = new Map();
|
||||
const pokemonTypes : Map<POGOProtos.Enums.PokemonType, Array<number>> = new Map();
|
||||
const combatMoves : Map<POGOProtos.Enums.PokemonMove, ICombatMoveStats> = new Map();
|
||||
const combatMoves : CombatMoveStats = new Map();
|
||||
|
||||
const pokemonBaseStamina : Array<ICalculateRelativeStats> = [];
|
||||
const pokemonBaseAttack : Array<ICalculateRelativeStats> = [];
|
||||
@ -141,8 +141,18 @@ export const parseGameMaster = async () => {
|
||||
// COMBAT MOVES
|
||||
} else if (entry.template_id.indexOf('COMBAT_V') === 0 && entry.combat_move && entry.combat_move.unique_id) {
|
||||
const combatMoveId = entry.combat_move.unique_id || POGOProtos.Enums.PokemonMove.MOVE_UNSET;
|
||||
const formatMoveName = (moveId : string) => {
|
||||
const fastMove = '_FAST';
|
||||
const fastMoveIndex = moveId.lastIndexOf(fastMove);
|
||||
let moveName = moveId;
|
||||
if (fastMoveIndex + fastMove.length === moveId.length) {
|
||||
moveName = moveName.substr(0, fastMoveIndex);
|
||||
}
|
||||
return moveName.replace(/_/, ' ').toLowerCase();
|
||||
};
|
||||
combatMoves.set(combatMoveId, {
|
||||
id: combatMoveId,
|
||||
name: formatMoveName(POGOProtos.Enums.PokemonMove[combatMoveId]),
|
||||
type: entry.combat_move.type || POGOProtos.Enums.PokemonType.POKEMON_TYPE_NONE,
|
||||
power: entry.combat_move.power || 0,
|
||||
energyDelta: entry.combat_move.energy_delta || 0,
|
||||
|
||||
@ -2,7 +2,7 @@ import POGOProtos from 'pogo-protos';
|
||||
|
||||
import { AjaxRequest } from 'api/AjaxRequest';
|
||||
|
||||
import { IConfig } from 'app/models/Config';
|
||||
import { IConfig, IConfigJson } from 'app/models/Config';
|
||||
import { ILeaguePokemon } from 'app/models/League';
|
||||
import { IPokemon, TypeEffectiveness } from 'app/models/Pokemon';
|
||||
|
||||
@ -28,8 +28,11 @@ export class PokemonService implements IPokemonService {
|
||||
const queryParameters = {
|
||||
};
|
||||
|
||||
const response : IConfig = await this.AjaxRequest.ajaxGet('/dist/db/config.json', queryParameters);
|
||||
return response;
|
||||
const response : IConfigJson = await this.AjaxRequest.ajaxGet('/dist/db/config.json', queryParameters);
|
||||
return {
|
||||
...response,
|
||||
combatMoves: new Map(response.combatMoves),
|
||||
};
|
||||
}
|
||||
|
||||
public async getPokemonList() {
|
||||
|
||||
@ -12,11 +12,12 @@ import { appReducers } from 'app/index';
|
||||
|
||||
import * as ActionsPokemonExplorer from 'app/actions';
|
||||
import * as ActionsPokemonSelectList from 'app/components/PokemonSelectList/actions';
|
||||
import { IndividualValueKey, IPokemonAppDispatch } from 'app/types';
|
||||
import { IndividualValueKey, IPokemonAppDispatch, ITypeCoverage } from 'app/types';
|
||||
|
||||
import { Footer } from 'app/components/Footer';
|
||||
import { Header } from 'app/components/Header';
|
||||
import { LeagueIvExplorer } from 'app/components/LeagueIvExplorer';
|
||||
import { MovesExplorer } from 'app/components/MovesExplorer';
|
||||
import { PokemonDisplay } from 'app/components/PokemonDisplay';
|
||||
import { PokemonSelectList } from 'app/components/PokemonSelectList/PokemonSelectList';
|
||||
import { TypeEffectiveDisplay } from 'app/components/TypeEffectiveDisplay';
|
||||
@ -35,6 +36,7 @@ interface IConnectedPokemonAppProps extends PokemonAppProps, IPokemonAppDispatch
|
||||
export type Navigation = 'pokedex';
|
||||
type SubNavigation = 'pvp' | 'types' | 'moves';
|
||||
interface IState {
|
||||
isInterruption : boolean;
|
||||
activeNavigation : Navigation | null;
|
||||
widgets : { [ key in SubNavigation ] : boolean };
|
||||
}
|
||||
@ -45,6 +47,7 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isInterruption: false,
|
||||
activeNavigation: null,
|
||||
widgets: {
|
||||
pvp: true,
|
||||
@ -98,13 +101,15 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
||||
league,
|
||||
individualValues,
|
||||
leaguePokemon,
|
||||
combatMoves,
|
||||
} = this.props.pokemonExplorerState;
|
||||
const {
|
||||
isInterruption,
|
||||
activeNavigation,
|
||||
widgets,
|
||||
} = this.state;
|
||||
|
||||
const isOverlayShown = activeNavigation === 'pokedex';
|
||||
const isOverlayShown = isInterruption || activeNavigation === 'pokedex';
|
||||
|
||||
const wrapperCss = classNames(
|
||||
styles.wrapper,
|
||||
@ -200,6 +205,12 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
||||
isHighlighted={ isOverlayShown }
|
||||
/>
|
||||
}
|
||||
{ widgets.types && leaguePokemon !== null &&
|
||||
<TypeEffectiveDisplay
|
||||
effectiveness={ leaguePokemon.effectiveness }
|
||||
pokemonName={ leaguePokemon.name }
|
||||
/>
|
||||
}
|
||||
{ widgets.pvp && leaguePokemon !== null &&
|
||||
<LeagueIvExplorer
|
||||
activeLeague={ league }
|
||||
@ -210,13 +221,16 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
||||
handleChangeLeague={ this.handleChangeLeague }
|
||||
/>
|
||||
}
|
||||
{ widgets.moves && leaguePokemon !== null &&
|
||||
<MovesExplorer
|
||||
movesById={ combatMoves }
|
||||
quickMoves={ leaguePokemon.moves.quick }
|
||||
chargeMoves={ leaguePokemon.moves.cinematic }
|
||||
handleToggleDropdownOpen={ this.handleToggleInterruption }
|
||||
handleChangeTypeCoverage={ this.handleChangeTypeCoverage }
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
{ widgets.types && leaguePokemon !== null &&
|
||||
<TypeEffectiveDisplay
|
||||
effectiveness={ leaguePokemon.effectiveness }
|
||||
pokemonName={ leaguePokemon.name }
|
||||
/>
|
||||
}
|
||||
<div className={ leftNavCss }>
|
||||
<button className={ pvpButtonCss } onClick={ this.handlePvpClick }><i className={ pvpCss } /></button>
|
||||
<button className={ badgeButtonCss } onClick={ this.handleTypesClick }><i className={ badgeCss } /></button>
|
||||
@ -231,6 +245,12 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
||||
);
|
||||
}
|
||||
|
||||
private readonly handleToggleInterruption = (isInterruption : boolean) => {
|
||||
this.setState({
|
||||
isInterruption,
|
||||
});
|
||||
}
|
||||
|
||||
private readonly handleOverlayClick = () => {
|
||||
this.setState({
|
||||
activeNavigation: null,
|
||||
@ -327,6 +347,10 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
||||
this.props.dispatch(ActionsPokemonExplorer.maximizeLevel());
|
||||
}
|
||||
|
||||
private readonly handleChangeTypeCoverage = (coverage : ITypeCoverage) => {
|
||||
this.props.dispatch(ActionsPokemonExplorer.setTypeCoverage(coverage));
|
||||
}
|
||||
|
||||
private readonly handleChangeLeagueNavigation = (league : League) => {
|
||||
const {
|
||||
history,
|
||||
|
||||
@ -1,16 +1,18 @@
|
||||
import { action } from 'typesafe-actions';
|
||||
|
||||
import { PokemonExplorerActionTypes, ThunkResult } from 'app/types';
|
||||
import { ITypeCoverage, PokemonExplorerActionTypes, ThunkResult } from 'app/types';
|
||||
|
||||
import { calculateMaxLevelForLeague } from 'app/utils/calculator';
|
||||
|
||||
import { ILeaguePokemon, League } from 'app/models/League';
|
||||
import { IMaxStats } from 'app/models/Pokemon';
|
||||
import { CombatMoveStats, IMaxStats } from 'app/models/Pokemon';
|
||||
|
||||
export const setIsLoading = (isLoading : boolean) => action(PokemonExplorerActionTypes.SET_IS_LOADING, { isLoading });
|
||||
|
||||
export const setMaxPossibleStats = (maxStats : IMaxStats) => action(PokemonExplorerActionTypes.SET_MAX_STATS, { maxStats });
|
||||
|
||||
export const setCombatMoveStats = (combatMoves : CombatMoveStats) => action(PokemonExplorerActionTypes.SET_COMBAT_MOVE_STATS, { combatMoves });
|
||||
|
||||
export const setLeaguePokemon = (leaguePokemon : ILeaguePokemon | null) => action(PokemonExplorerActionTypes.SET_LEAGUE_POKEMON, { leaguePokemon });
|
||||
|
||||
export const setIvLevel = (level : number | null) => action(PokemonExplorerActionTypes.SET_IV_LEVEL, { level });
|
||||
@ -23,11 +25,14 @@ export const setIvDef = (ivDef : number | null) => action(PokemonExplorerActionT
|
||||
|
||||
export const setActiveLeague = (league : League) => action(PokemonExplorerActionTypes.SET_ACTIVE_LEAGUE, { league });
|
||||
|
||||
export const setTypeCoverage = (typeCoverage : ITypeCoverage) => action(PokemonExplorerActionTypes.SET_TYPE_COVERAGE, { typeCoverage });
|
||||
|
||||
export const fetchConfig = (
|
||||
) : ThunkResult<Promise<void>> => {
|
||||
return async (dispatch, getState, extraArguments) => {
|
||||
const config = await extraArguments.services.pokemonService.getConfig();
|
||||
dispatch(setMaxPossibleStats(config.maxPossibleStats));
|
||||
dispatch(setCombatMoveStats(config.combatMoves));
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -176,7 +176,7 @@ export class LeagueIvExplorer extends React.Component<ILeagueIvExplorerProps, IS
|
||||
);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className={ styles.wrapper }>
|
||||
<LeagueSelector
|
||||
activeLeague={ activeLeague }
|
||||
handleLeagueSelect={ handleChangeLeague }
|
||||
@ -252,7 +252,7 @@ export class LeagueIvExplorer extends React.Component<ILeagueIvExplorerProps, IS
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</React.Fragment>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -23,9 +23,9 @@ export interface ILeagueStatsListProps {
|
||||
interface IState {
|
||||
activePokemonId : POGOProtos.Enums.PokemonId;
|
||||
activePokemonForm : POGOProtos.Enums.Form;
|
||||
hasSetActiveStats : boolean;
|
||||
listRef : React.RefObject<FixedSizeList>;
|
||||
activeIndex : number;
|
||||
hasSetActiveStats : boolean;
|
||||
dimensions : {
|
||||
width : number;
|
||||
height : number;
|
||||
@ -96,8 +96,8 @@ export class LeagueStatsList extends React.Component<ILeagueStatsListProps, ISta
|
||||
this.state = {
|
||||
activePokemonId: POGOProtos.Enums.PokemonId.MISSINGNO,
|
||||
activePokemonForm: POGOProtos.Enums.Form.FORM_UNSET,
|
||||
listRef: React.createRef(),
|
||||
hasSetActiveStats: false,
|
||||
listRef: React.createRef(),
|
||||
activeIndex: -1,
|
||||
dimensions: {
|
||||
width: -1,
|
||||
@ -159,7 +159,7 @@ export class LeagueStatsList extends React.Component<ILeagueStatsListProps, ISta
|
||||
activeIvs.ivHp === stats.ivHp &&
|
||||
activeIvs.ivAtk === stats.ivAtk &&
|
||||
activeIvs.ivDef === stats.ivDef,
|
||||
highlight: this.state.activeIndex === index,
|
||||
highlight: this.state.activeIndex === index, // this css class currently does nothing
|
||||
}
|
||||
);
|
||||
const onClick = () => {
|
||||
|
||||
165
src/ts/app/components/MovesDropdown.tsx
Normal file
165
src/ts/app/components/MovesDropdown.tsx
Normal file
@ -0,0 +1,165 @@
|
||||
import POGOProtos from 'pogo-protos';
|
||||
|
||||
import React from 'react';
|
||||
import { ContentRect, default as Measure } from 'react-measure';
|
||||
import { FixedSizeList } from 'react-window';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { CombatMoveStats, IPokemonMove } from 'app/models/Pokemon';
|
||||
|
||||
import { TypeIndicator } from './TypeIndicator';
|
||||
|
||||
import * as styles from 'app/styles/MovesDropdown.scss';
|
||||
|
||||
export interface IMovesDropdownProps {
|
||||
movesById : CombatMoveStats;
|
||||
selectedMove : IPokemonMove | null;
|
||||
options : Array<IPokemonMove>;
|
||||
handleToggleOpen : (open : boolean) => void;
|
||||
handleChangeSelectedOption : (option : IPokemonMove) => void;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
isMenuOpen : boolean;
|
||||
listRef : React.RefObject<FixedSizeList>;
|
||||
dimensions : {
|
||||
width : number;
|
||||
height : number;
|
||||
};
|
||||
}
|
||||
|
||||
interface IRowFactory {
|
||||
index : number;
|
||||
style : React.CSSProperties;
|
||||
}
|
||||
|
||||
export class MovesDropdown extends React.Component<IMovesDropdownProps, IState> {
|
||||
|
||||
constructor(props : IMovesDropdownProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isMenuOpen: false,
|
||||
listRef: React.createRef(),
|
||||
dimensions: {
|
||||
width: -1,
|
||||
height: -1,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {
|
||||
movesById,
|
||||
selectedMove,
|
||||
options,
|
||||
} = this.props;
|
||||
const {
|
||||
isMenuOpen,
|
||||
} = this.state;
|
||||
|
||||
const { width, height } = this.state.dimensions;
|
||||
const onResize = (contentRect : ContentRect) => {
|
||||
if (typeof contentRect.bounds !== 'undefined') {
|
||||
this.setState({ dimensions: contentRect.bounds });
|
||||
}
|
||||
};
|
||||
|
||||
const wrapperCss = classNames(
|
||||
'nes-container',
|
||||
'is-rounded',
|
||||
'nes-select',
|
||||
styles.wrapper,
|
||||
);
|
||||
|
||||
let moveName = 'Select a move';
|
||||
if (selectedMove !== null) {
|
||||
const moveStats = movesById.get(selectedMove.id);
|
||||
if (moveStats) {
|
||||
moveName = moveStats.name;
|
||||
} else {
|
||||
moveName = 'UNKNOWN MOVE';
|
||||
}
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div
|
||||
className={ wrapperCss }
|
||||
onClick={ this.toggleMenu }
|
||||
>
|
||||
{ moveName }
|
||||
</div>
|
||||
{ isMenuOpen &&
|
||||
<div>
|
||||
<Measure
|
||||
bounds={ true }
|
||||
onResize={ onResize }
|
||||
>
|
||||
{
|
||||
({ measureRef }) => (
|
||||
<div ref={ measureRef }>
|
||||
<FixedSizeList
|
||||
ref={ this.state.listRef }
|
||||
height={ height }
|
||||
itemCount={ options.length }
|
||||
itemSize={ 35 }
|
||||
width={ width }
|
||||
>
|
||||
{ this.rowFactory.bind(this) }
|
||||
</FixedSizeList>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</Measure>
|
||||
</div>
|
||||
}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
private readonly toggleMenu = () => {
|
||||
const isMenuOpen = !this.state.isMenuOpen;
|
||||
this.setState({
|
||||
isMenuOpen,
|
||||
});
|
||||
this.props.handleToggleOpen(isMenuOpen);
|
||||
}
|
||||
|
||||
private rowFactory({ index, style } : IRowFactory) {
|
||||
const {
|
||||
movesById,
|
||||
selectedMove,
|
||||
options,
|
||||
} = this.props;
|
||||
const move = options[index];
|
||||
const moveStats = movesById.get(move.id);
|
||||
const css = classNames(
|
||||
'list-item', // global style
|
||||
styles.listItem,
|
||||
{
|
||||
active: selectedMove && selectedMove.id === move.id,
|
||||
}
|
||||
);
|
||||
const onClick = () => {
|
||||
this.props.handleChangeSelectedOption(move);
|
||||
this.toggleMenu();
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{ moveStats &&
|
||||
<a
|
||||
key={ index }
|
||||
style={ style }
|
||||
className={ css }
|
||||
onClick={ onClick }
|
||||
>
|
||||
<span>{ moveStats.name }</span>
|
||||
<TypeIndicator type={ moveStats.type } />
|
||||
</a>
|
||||
}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
153
src/ts/app/components/MovesExplorer.tsx
Normal file
153
src/ts/app/components/MovesExplorer.tsx
Normal file
@ -0,0 +1,153 @@
|
||||
import React from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { CombatMoveStats, ICombatMoveStats, IPokemonMove } from 'app/models/Pokemon';
|
||||
|
||||
import { ITypeCoverage } from 'app/types';
|
||||
|
||||
import { MovesDropdown } from 'app/components/MovesDropdown';
|
||||
import { TypeIndicator } from './TypeIndicator';
|
||||
|
||||
import * as styles from 'app/styles/MovesExplorer.scss';
|
||||
|
||||
export interface IMovesExplorerProps {
|
||||
movesById : CombatMoveStats;
|
||||
quickMoves : Array<IPokemonMove>;
|
||||
chargeMoves : Array<IPokemonMove>;
|
||||
handleToggleDropdownOpen : (isOpen : boolean) => void;
|
||||
handleChangeTypeCoverage : (typeCoverage : ITypeCoverage) => void;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
quickMove : IPokemonMove | null;
|
||||
chargeMove1 : IPokemonMove | null;
|
||||
chargeMove2 : IPokemonMove | null;
|
||||
}
|
||||
|
||||
export class MovesExplorer extends React.Component<IMovesExplorerProps, IState> {
|
||||
|
||||
constructor(props : IMovesExplorerProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
quickMove: null,
|
||||
chargeMove1: null,
|
||||
chargeMove2: null,
|
||||
};
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {
|
||||
movesById,
|
||||
quickMoves,
|
||||
chargeMoves,
|
||||
handleToggleDropdownOpen,
|
||||
} = this.props;
|
||||
const {
|
||||
quickMove,
|
||||
chargeMove1,
|
||||
chargeMove2,
|
||||
} = this.state;
|
||||
|
||||
const wrapperCss = classNames(
|
||||
'nes-container',
|
||||
styles.wrapper,
|
||||
);
|
||||
|
||||
const quickMoveType = this.getMoveType(quickMove);
|
||||
const chargeMove1Type = this.getMoveType(chargeMove1);
|
||||
const chargeMove2Type = this.getMoveType(chargeMove2);
|
||||
|
||||
return (
|
||||
<div className={ wrapperCss }>
|
||||
<MovesDropdown
|
||||
movesById={ movesById }
|
||||
selectedMove={ quickMove }
|
||||
options={ quickMoves }
|
||||
handleToggleOpen={ handleToggleDropdownOpen }
|
||||
handleChangeSelectedOption={ this.handleChangeQuickMove }
|
||||
/>
|
||||
{ quickMove && quickMoveType &&
|
||||
<TypeIndicator type={ quickMoveType } />
|
||||
}
|
||||
<MovesDropdown
|
||||
movesById={ movesById }
|
||||
selectedMove={ chargeMove1 }
|
||||
options={ chargeMoves }
|
||||
handleToggleOpen={ handleToggleDropdownOpen }
|
||||
handleChangeSelectedOption={ this.handleChangeChargeMove1 }
|
||||
/>
|
||||
{ chargeMove1 && chargeMove1Type &&
|
||||
<TypeIndicator type={ chargeMove1Type } />
|
||||
}
|
||||
<MovesDropdown
|
||||
movesById={ movesById }
|
||||
selectedMove={ chargeMove2 }
|
||||
options={ chargeMoves }
|
||||
handleToggleOpen={ handleToggleDropdownOpen }
|
||||
handleChangeSelectedOption={ this.handleChangeChargeMove2 }
|
||||
/>
|
||||
{ chargeMove2 && chargeMove2Type &&
|
||||
<TypeIndicator type={ chargeMove2Type } />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private readonly getMoveType = (move : IPokemonMove | null) => {
|
||||
let moveStats : ICombatMoveStats | null = null;
|
||||
if (move !== null) {
|
||||
moveStats = this.props.movesById.get(move.id) || null;
|
||||
}
|
||||
if (moveStats !== null) {
|
||||
return moveStats.type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private readonly handleChangeQuickMove = (option : IPokemonMove) => {
|
||||
const {
|
||||
chargeMove1,
|
||||
chargeMove2,
|
||||
} = this.state;
|
||||
this.setState({
|
||||
quickMove: option,
|
||||
});
|
||||
this.props.handleChangeTypeCoverage({
|
||||
type1: this.getMoveType(option),
|
||||
type2: this.getMoveType(chargeMove1),
|
||||
type3: this.getMoveType(chargeMove2),
|
||||
});
|
||||
}
|
||||
|
||||
private readonly handleChangeChargeMove1 = (option : IPokemonMove) => {
|
||||
const {
|
||||
quickMove,
|
||||
chargeMove2,
|
||||
} = this.state;
|
||||
this.setState({
|
||||
chargeMove1: option,
|
||||
});
|
||||
this.props.handleChangeTypeCoverage({
|
||||
type1: this.getMoveType(quickMove),
|
||||
type2: this.getMoveType(option),
|
||||
type3: this.getMoveType(chargeMove2),
|
||||
});
|
||||
}
|
||||
|
||||
private readonly handleChangeChargeMove2 = (option : IPokemonMove) => {
|
||||
const {
|
||||
quickMove,
|
||||
chargeMove1,
|
||||
} = this.state;
|
||||
this.setState({
|
||||
chargeMove2: option,
|
||||
});
|
||||
this.props.handleChangeTypeCoverage({
|
||||
type1: this.getMoveType(quickMove),
|
||||
type2: this.getMoveType(chargeMove1),
|
||||
type3: this.getMoveType(option),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,13 @@
|
||||
import { IMaxStats } from 'app/models/Pokemon';
|
||||
import POGOProtos from 'pogo-protos';
|
||||
|
||||
import { CombatMoveStats, ICombatMoveStats, IMaxStats } from 'app/models/Pokemon';
|
||||
|
||||
export interface IConfigJson {
|
||||
maxPossibleStats : IMaxStats;
|
||||
combatMoves : Array<[POGOProtos.Enums.PokemonMove, ICombatMoveStats]>;
|
||||
}
|
||||
|
||||
export interface IConfig {
|
||||
maxPossibleStats : IMaxStats;
|
||||
combatMoves : CombatMoveStats;
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ export interface IPokemonSpecies {
|
||||
genus : string;
|
||||
}
|
||||
|
||||
interface IPokemonMove {
|
||||
export interface IPokemonMove {
|
||||
id : POGOProtos.Enums.PokemonMove;
|
||||
isLegacy : boolean;
|
||||
}
|
||||
@ -103,7 +103,10 @@ export interface IStats {
|
||||
|
||||
export interface ICombatMoveStats {
|
||||
id : POGOProtos.Enums.PokemonMove;
|
||||
name : string;
|
||||
type : POGOProtos.Enums.PokemonType;
|
||||
power : number;
|
||||
energyDelta : number;
|
||||
}
|
||||
|
||||
export type CombatMoveStats = Map<POGOProtos.Enums.PokemonMove, ICombatMoveStats>;
|
||||
|
||||
@ -21,6 +21,12 @@ export const initialState : IPokemonExplorerState = {
|
||||
ivDef: null,
|
||||
},
|
||||
league: League.GREAT,
|
||||
combatMoves: new Map(),
|
||||
typeCoverage: {
|
||||
type1: null,
|
||||
type2: null,
|
||||
type3: null,
|
||||
},
|
||||
};
|
||||
|
||||
const reduceSetIsLoading = (
|
||||
@ -41,6 +47,14 @@ const reduceSetMaxPossibleStats = (
|
||||
},
|
||||
});
|
||||
|
||||
const reduceSetCombatMoveStats = (
|
||||
state : IPokemonExplorerState,
|
||||
action : ReturnType<typeof Actions.setCombatMoveStats>
|
||||
) : IPokemonExplorerState => ({
|
||||
...state,
|
||||
combatMoves: action.payload.combatMoves,
|
||||
});
|
||||
|
||||
const reduceSetLeaguePokemon = (
|
||||
state : IPokemonExplorerState,
|
||||
action : ReturnType<typeof Actions.setLeaguePokemon>
|
||||
@ -101,6 +115,16 @@ const reduceSetActiveLeague = (
|
||||
league: action.payload.league
|
||||
});
|
||||
|
||||
const reduceSetTypeCoverage = (
|
||||
state : IPokemonExplorerState,
|
||||
action : ReturnType<typeof Actions.setTypeCoverage>
|
||||
) : IPokemonExplorerState => ({
|
||||
...state,
|
||||
typeCoverage: {
|
||||
...action.payload.typeCoverage
|
||||
}
|
||||
});
|
||||
|
||||
export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
||||
state : IPokemonExplorerState = initialState,
|
||||
action,
|
||||
@ -110,6 +134,8 @@ export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
||||
return reduceSetIsLoading(state, action as ReturnType<typeof Actions.setIsLoading>);
|
||||
case PokemonExplorerActionTypes.SET_MAX_STATS:
|
||||
return reduceSetMaxPossibleStats(state, action as ReturnType<typeof Actions.setMaxPossibleStats>);
|
||||
case PokemonExplorerActionTypes.SET_COMBAT_MOVE_STATS:
|
||||
return reduceSetCombatMoveStats(state, action as ReturnType<typeof Actions.setCombatMoveStats>);
|
||||
case PokemonExplorerActionTypes.SET_LEAGUE_POKEMON:
|
||||
return reduceSetLeaguePokemon(state, action as ReturnType<typeof Actions.setLeaguePokemon>);
|
||||
case PokemonExplorerActionTypes.SET_IV_LEVEL:
|
||||
@ -122,6 +148,8 @@ export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
||||
return reduceSetIvDef(state, action as ReturnType<typeof Actions.setIvDef>);
|
||||
case PokemonExplorerActionTypes.SET_ACTIVE_LEAGUE:
|
||||
return reduceSetActiveLeague(state, action as ReturnType<typeof Actions.setActiveLeague>);
|
||||
case PokemonExplorerActionTypes.SET_TYPE_COVERAGE:
|
||||
return reduceSetTypeCoverage(state, action as ReturnType<typeof Actions.setTypeCoverage>);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
@import '~styles/Variables.scss';
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
}
|
||||
|
||||
.container {
|
||||
composes: container from './PokemonApp.scss';
|
||||
margin-bottom: 1rem;
|
||||
|
||||
1
src/ts/app/styles/LeagueIvExplorer.scss.d.ts
vendored
1
src/ts/app/styles/LeagueIvExplorer.scss.d.ts
vendored
@ -9,3 +9,4 @@ export const leftColumn: string;
|
||||
export const pokemonInfoWrapper: string;
|
||||
export const pokemonRankValue: string;
|
||||
export const rightColumn: string;
|
||||
export const wrapper: string;
|
||||
|
||||
7
src/ts/app/styles/MovesDropdown.scss
Normal file
7
src/ts/app/styles/MovesDropdown.scss
Normal file
@ -0,0 +1,7 @@
|
||||
.wrapper {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.listItem {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
4
src/ts/app/styles/MovesDropdown.scss.d.ts
vendored
Normal file
4
src/ts/app/styles/MovesDropdown.scss.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
export const listItem: string;
|
||||
export const wrapper: string;
|
||||
3
src/ts/app/styles/MovesExplorer.scss
Normal file
3
src/ts/app/styles/MovesExplorer.scss
Normal file
@ -0,0 +1,3 @@
|
||||
.wrapper {
|
||||
font-size: 1em;
|
||||
}
|
||||
3
src/ts/app/styles/MovesExplorer.scss.d.ts
vendored
Normal file
3
src/ts/app/styles/MovesExplorer.scss.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
export const wrapper: string;
|
||||
@ -77,9 +77,14 @@ $overlay-opacity: 0.7;
|
||||
.displayWrapper {
|
||||
margin: 0 auto;
|
||||
// flex-basis: 30rem;
|
||||
width: 30rem;
|
||||
// width: 30rem;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
flex-flow: column wrap;
|
||||
align-content: center;
|
||||
|
||||
& > * {
|
||||
width: 425px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
@ -90,11 +95,11 @@ $overlay-opacity: 0.7;
|
||||
.rightColumn {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
flex-basis: 45%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.leftColumn {
|
||||
width: 45%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import POGOProtos from 'pogo-protos';
|
||||
|
||||
import { Action } from 'redux';
|
||||
import { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
||||
|
||||
@ -6,7 +8,7 @@ import { IProviderExtraArguments } from 'common/models/IProviderExtraArguments';
|
||||
import { IPokemonSelectListState } from 'app/components/PokemonSelectList/types';
|
||||
|
||||
import { ILeaguePokemon, League } from 'app/models/League';
|
||||
import { IMaxStats } from 'app/models/Pokemon';
|
||||
import { CombatMoveStats, IMaxStats } from 'app/models/Pokemon';
|
||||
|
||||
import { PokemonService } from 'api/PokemonService';
|
||||
|
||||
@ -37,21 +39,31 @@ export interface IIndividualValues {
|
||||
ivDef : number | null;
|
||||
}
|
||||
|
||||
export interface ITypeCoverage {
|
||||
type1 : POGOProtos.Enums.PokemonType | null;
|
||||
type2 : POGOProtos.Enums.PokemonType | null;
|
||||
type3 : POGOProtos.Enums.PokemonType | null;
|
||||
}
|
||||
|
||||
export interface IPokemonExplorerState {
|
||||
isLoading : boolean;
|
||||
leaguePokemon : ILeaguePokemon | null;
|
||||
maxPossibleStats : IMaxStats;
|
||||
individualValues : IIndividualValues;
|
||||
league : League;
|
||||
combatMoves : CombatMoveStats;
|
||||
typeCoverage : ITypeCoverage;
|
||||
}
|
||||
|
||||
export const PokemonExplorerActionTypes = {
|
||||
SET_IS_LOADING: 'POKEMON_EXPLORER/SET_IS_LOADING',
|
||||
SET_MAX_STATS: 'POKEMON_EXPLORER/SET_MAX_STATS',
|
||||
SET_COMBAT_MOVE_STATS: 'POKEMON_EXPLORER/SET_COMBAT_MOVE_STATS',
|
||||
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',
|
||||
SET_ACTIVE_LEAGUE: 'POKEMON_EXPLORER/SET_ACTIVE_LEAGUE',
|
||||
SET_TYPE_COVERAGE: 'POKEMON_EXPLORER/SET_TYPE_COVERAGE',
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user