split pokemon explorer from pokemon app
This commit is contained in:
parent
7cd14f2b58
commit
dd37703417
126
dist/app.css
vendored
126
dist/app.css
vendored
@ -440,69 +440,6 @@
|
|||||||
align-items: start;
|
align-items: start;
|
||||||
align-self: stretch; }
|
align-self: stretch; }
|
||||||
|
|
||||||
.PokemonSelectList__wrapper__2LQMY {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
width: 20em;
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column nowrap;
|
|
||||||
margin: 0 1.5em 0 auto;
|
|
||||||
position: relative; }
|
|
||||||
.PokemonSelectList__wrapper__2LQMY .PokemonSelectList__listWrapper__bBtO6 {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
display: flex;
|
|
||||||
padding: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
height: 340px;
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 2; }
|
|
||||||
.PokemonSelectList__wrapper__2LQMY .PokemonSelectList__listWrapper__bBtO6 > * {
|
|
||||||
width: 100%; }
|
|
||||||
.PokemonSelectList__wrapper__2LQMY .PokemonSelectList__listWrapper__bBtO6.PokemonSelectList__emptyList__1vgpK .PokemonSelectList__emptyState__3sBmb {
|
|
||||||
align-self: center;
|
|
||||||
text-align: center; }
|
|
||||||
.PokemonSelectList__wrapper__2LQMY .PokemonSelectList__listWrapper__bBtO6.PokemonSelectList__emptyList__1vgpK .PokemonSelectList__emptyState__3sBmb > *:first-child {
|
|
||||||
margin: 1em auto; }
|
|
||||||
.PokemonSelectList__wrapper__2LQMY a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
padding: 5px 1em 5px 2em;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-content: space-around;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
display: flex; }
|
|
||||||
.PokemonSelectList__wrapper__2LQMY a .PokemonSelectList__menuIcon__1I2_T {
|
|
||||||
margin: -4px 0 0 0.5em;
|
|
||||||
opacity: 0.5; }
|
|
||||||
.PokemonSelectList__wrapper__2LQMY a.active .PokemonSelectList__menuIcon__1I2_T {
|
|
||||||
opacity: 1; }
|
|
||||||
|
|
||||||
.PokemonSelectList__filterWrapper__1d1Wl {
|
|
||||||
position: relative;
|
|
||||||
margin: 0.1em; }
|
|
||||||
.PokemonSelectList__filterWrapper__1d1Wl .close {
|
|
||||||
position: absolute;
|
|
||||||
top: 1em;
|
|
||||||
right: 1em; }
|
|
||||||
|
|
||||||
.PokemonSelectList__filterInput__1z_s2 {
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
padding-right: 3em; }
|
|
||||||
|
|
||||||
.PokemonSelectList__dex__1QHut,
|
|
||||||
.PokemonSelectList__form__VIw8Q {
|
|
||||||
font-size: 0.8em;
|
|
||||||
text-transform: capitalize; }
|
|
||||||
|
|
||||||
.PokemonSelectList__dex__1QHut {
|
|
||||||
margin-left: auto; }
|
|
||||||
|
|
||||||
.PokemonSelectList__form__VIw8Q {
|
|
||||||
flex: 0 1 100%; }
|
|
||||||
|
|
||||||
.TypeEffectiveDisplay__multiplierWrapper__1E9zx {
|
.TypeEffectiveDisplay__multiplierWrapper__1E9zx {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
@ -567,5 +504,68 @@
|
|||||||
flex-basis: unset;
|
flex-basis: unset;
|
||||||
width: 6.75rem; }
|
width: 6.75rem; }
|
||||||
|
|
||||||
|
.PokemonSelectList__wrapper__2LQMY {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
width: 20em;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
margin: 0 1.5em 0 auto;
|
||||||
|
position: relative; }
|
||||||
|
.PokemonSelectList__wrapper__2LQMY .PokemonSelectList__listWrapper__bBtO6 {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 340px;
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 2; }
|
||||||
|
.PokemonSelectList__wrapper__2LQMY .PokemonSelectList__listWrapper__bBtO6 > * {
|
||||||
|
width: 100%; }
|
||||||
|
.PokemonSelectList__wrapper__2LQMY .PokemonSelectList__listWrapper__bBtO6.PokemonSelectList__emptyList__1vgpK .PokemonSelectList__emptyState__3sBmb {
|
||||||
|
align-self: center;
|
||||||
|
text-align: center; }
|
||||||
|
.PokemonSelectList__wrapper__2LQMY .PokemonSelectList__listWrapper__bBtO6.PokemonSelectList__emptyList__1vgpK .PokemonSelectList__emptyState__3sBmb > *:first-child {
|
||||||
|
margin: 1em auto; }
|
||||||
|
.PokemonSelectList__wrapper__2LQMY a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 5px 1em 5px 2em;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-content: space-around;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
display: flex; }
|
||||||
|
.PokemonSelectList__wrapper__2LQMY a .PokemonSelectList__menuIcon__1I2_T {
|
||||||
|
margin: -4px 0 0 0.5em;
|
||||||
|
opacity: 0.5; }
|
||||||
|
.PokemonSelectList__wrapper__2LQMY a.active .PokemonSelectList__menuIcon__1I2_T {
|
||||||
|
opacity: 1; }
|
||||||
|
|
||||||
|
.PokemonSelectList__filterWrapper__1d1Wl {
|
||||||
|
position: relative;
|
||||||
|
margin: 0.1em; }
|
||||||
|
.PokemonSelectList__filterWrapper__1d1Wl .close {
|
||||||
|
position: absolute;
|
||||||
|
top: 1em;
|
||||||
|
right: 1em; }
|
||||||
|
|
||||||
|
.PokemonSelectList__filterInput__1z_s2 {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
padding-right: 3em; }
|
||||||
|
|
||||||
|
.PokemonSelectList__dex__1QHut,
|
||||||
|
.PokemonSelectList__form__VIw8Q {
|
||||||
|
font-size: 0.8em;
|
||||||
|
text-transform: capitalize; }
|
||||||
|
|
||||||
|
.PokemonSelectList__dex__1QHut {
|
||||||
|
margin-left: auto; }
|
||||||
|
|
||||||
|
.PokemonSelectList__form__VIw8Q {
|
||||||
|
flex: 0 1 100%; }
|
||||||
|
|
||||||
|
|
||||||
/*# sourceMappingURL=main.tmp.css.map*/
|
/*# sourceMappingURL=main.tmp.css.map*/
|
||||||
1116
dist/main-bundle.js
vendored
1116
dist/main-bundle.js
vendored
File diff suppressed because it is too large
Load Diff
@ -10,35 +10,28 @@ import { League } from 'app/models/League';
|
|||||||
|
|
||||||
import { appReducers } from 'app/index';
|
import { appReducers } from 'app/index';
|
||||||
|
|
||||||
import * as ActionsPokemonExplorer from 'app/actions';
|
import * as ActionsPokemonApp from 'app/actions';
|
||||||
|
import * as ActionsPokemonExplorer from 'app/components/PokemonExplorer/actions';
|
||||||
import * as ActionsPokemonSelectList from 'app/components/PokemonSelectList/actions';
|
import * as ActionsPokemonSelectList from 'app/components/PokemonSelectList/actions';
|
||||||
import { CombatMoveSelectorsOpen, IndividualValueKey, IPokemonAppDispatch, SelectedCombatMoves } from 'app/types';
|
import { IPokemonAppDispatch, IRouterProps } from 'app/types';
|
||||||
|
|
||||||
import { Footer } from 'app/components/Footer';
|
import { Footer } from 'app/components/Footer';
|
||||||
import { Header } from 'app/components/Header';
|
import { Header } from 'app/components/Header';
|
||||||
import { LeagueIvExplorer } from 'app/components/LeagueIvExplorer';
|
import { ConnectedPokemonExplorer } from 'app/components/PokemonExplorer/PokemonExplorer';
|
||||||
import { MovesExplorer } from 'app/components/MovesExplorer';
|
|
||||||
import { PokemonDisplay } from 'app/components/PokemonDisplay';
|
|
||||||
import { PokemonSelectList } from 'app/components/PokemonSelectList/PokemonSelectList';
|
import { PokemonSelectList } from 'app/components/PokemonSelectList/PokemonSelectList';
|
||||||
import { TypeEffectiveDisplay } from 'app/components/TypeEffectiveDisplay';
|
|
||||||
|
|
||||||
import { appendQueryString, getCurrentQueryStringVlaues } from 'app/utils/navigation';
|
import { getCurrentQueryStringVlaues } from 'app/utils/navigation';
|
||||||
|
|
||||||
import * as styles from 'app/styles/PokemonApp.scss';
|
import * as styles from 'app/styles/PokemonApp.scss';
|
||||||
|
|
||||||
type PokemonAppProps = ReturnType<typeof appReducers>;
|
type PokemonAppProps = ReturnType<typeof appReducers>;
|
||||||
|
|
||||||
interface IConnectedPokemonAppProps extends PokemonAppProps, IPokemonAppDispatch {
|
interface IConnectedPokemonAppProps extends PokemonAppProps, IPokemonAppDispatch, IRouterProps {}
|
||||||
history : RouteComponentProps['history'];
|
|
||||||
location : RouteComponentProps['location'];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// TODO: this should be on PokemonAppState
|
||||||
export type Navigation = 'pokedex';
|
export type Navigation = 'pokedex';
|
||||||
type SubNavigation = 'pvp' | 'types' | 'moves';
|
|
||||||
interface IState {
|
interface IState {
|
||||||
isInterruption : boolean;
|
|
||||||
activeNavigation : Navigation | null;
|
activeNavigation : Navigation | null;
|
||||||
widgets : { [ key in SubNavigation ] : boolean };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
||||||
@ -47,13 +40,7 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isInterruption: false,
|
|
||||||
activeNavigation: null,
|
activeNavigation: null,
|
||||||
widgets: {
|
|
||||||
pvp: true,
|
|
||||||
types: false,
|
|
||||||
moves: false,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +51,8 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
dispatch(ActionsPokemonExplorer.fetchConfig()),
|
dispatch(ActionsPokemonApp.fetchConfig()),
|
||||||
|
// TODO: move this action to PokemonApp actions
|
||||||
dispatch(ActionsPokemonSelectList.fetchPokemonList())
|
dispatch(ActionsPokemonSelectList.fetchPokemonList())
|
||||||
]);
|
]);
|
||||||
dispatch(ActionsPokemonSelectList.setIsLoading(false));
|
dispatch(ActionsPokemonSelectList.setIsLoading(false));
|
||||||
@ -90,6 +78,11 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
|
const {
|
||||||
|
isInterruption,
|
||||||
|
attackTypeEffectiveness,
|
||||||
|
combatMoves,
|
||||||
|
} = this.props.pokemonAppState;
|
||||||
const {
|
const {
|
||||||
activePokemonId,
|
activePokemonId,
|
||||||
activePokemonForm,
|
activePokemonForm,
|
||||||
@ -98,36 +91,16 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
|||||||
filterTerm,
|
filterTerm,
|
||||||
} = this.props.pokemonSelectListState;
|
} = this.props.pokemonSelectListState;
|
||||||
const {
|
const {
|
||||||
league,
|
|
||||||
individualValues,
|
|
||||||
leaguePokemon,
|
|
||||||
combatMoves,
|
|
||||||
selectedCombatMoves,
|
|
||||||
combatMoveSelectorsOpen,
|
|
||||||
} = this.props.pokemonExplorerState;
|
|
||||||
const {
|
|
||||||
isInterruption,
|
|
||||||
activeNavigation,
|
activeNavigation,
|
||||||
widgets,
|
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const isOverlayShown = isInterruption || activeNavigation === 'pokedex';
|
|
||||||
|
|
||||||
const wrapperCss = classNames(
|
const wrapperCss = classNames(
|
||||||
styles.wrapper,
|
styles.wrapper,
|
||||||
{
|
{
|
||||||
[styles.overlaid]: isOverlayShown,
|
[styles.overlaid]: isInterruption,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const leftNavCss = classNames(
|
|
||||||
styles.leftNavigation,
|
|
||||||
);
|
|
||||||
|
|
||||||
const displayWrapperCss = classNames(
|
|
||||||
styles.displayWrapper,
|
|
||||||
);
|
|
||||||
|
|
||||||
const iconCss = classNames(
|
const iconCss = classNames(
|
||||||
'icon',
|
'icon',
|
||||||
'pixel',
|
'pixel',
|
||||||
@ -147,43 +120,6 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
|||||||
// }
|
// }
|
||||||
);
|
);
|
||||||
|
|
||||||
const pvpCss = classNames(
|
|
||||||
iconCss,
|
|
||||||
'pvp',
|
|
||||||
{
|
|
||||||
active: widgets.pvp,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const pvpButtonCss = classNames(
|
|
||||||
// {
|
|
||||||
// [styles.activeNavigationButton]: widgets.pvp,
|
|
||||||
// }
|
|
||||||
);
|
|
||||||
const badgeCss = classNames(
|
|
||||||
iconCss,
|
|
||||||
'badge',
|
|
||||||
{
|
|
||||||
active: widgets.types,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const badgeButtonCss = classNames(
|
|
||||||
// {
|
|
||||||
// [styles.activeNavigationButton]: widgets.types,
|
|
||||||
// }
|
|
||||||
);
|
|
||||||
const tmCss = classNames(
|
|
||||||
iconCss,
|
|
||||||
'tm',
|
|
||||||
{
|
|
||||||
active: widgets.moves,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const tmButtonCss = classNames(
|
|
||||||
// {
|
|
||||||
// [styles.activeNavigationButton]: widgets.moves,
|
|
||||||
// }
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ wrapperCss }>
|
<div className={ wrapperCss }>
|
||||||
<Header>
|
<Header>
|
||||||
@ -199,114 +135,45 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
|||||||
/>
|
/>
|
||||||
<button className={ pokedexButtonCss } onClick={ this.handlePokedexClick }><i className={ pokedexCss } /></button>
|
<button className={ pokedexButtonCss } onClick={ this.handlePokedexClick }><i className={ pokedexCss } /></button>
|
||||||
</Header>
|
</Header>
|
||||||
<div className={ styles.body }>
|
<ConnectedPokemonExplorer
|
||||||
<div className={ displayWrapperCss }>
|
isOverlaid={ isInterruption }
|
||||||
{ leaguePokemon !== null &&
|
attackTypeEffectiveness={ attackTypeEffectiveness }
|
||||||
<PokemonDisplay
|
combatMoves={ combatMoves }
|
||||||
leaguePokemon={ leaguePokemon }
|
toggleInterruption={ this.handleToggleInterruption }
|
||||||
isHighlighted={ isOverlayShown }
|
history={ this.props.history }
|
||||||
|
location={ this.props.location }
|
||||||
/>
|
/>
|
||||||
}
|
|
||||||
{ widgets.types && leaguePokemon !== null &&
|
|
||||||
<TypeEffectiveDisplay
|
|
||||||
effectiveness={ leaguePokemon.effectiveness }
|
|
||||||
pokemonName={ leaguePokemon.name }
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
{ widgets.pvp && leaguePokemon !== null &&
|
|
||||||
<LeagueIvExplorer
|
|
||||||
activeLeague={ league }
|
|
||||||
leaguePokemon={ leaguePokemon }
|
|
||||||
individualValues={ individualValues }
|
|
||||||
handleChangeIndividualValue={ this.handleChangeIndividualValue }
|
|
||||||
handleMaximizeLevel={ this.handleMaximizeLevel }
|
|
||||||
handleChangeLeague={ this.handleChangeLeague }
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
{ widgets.moves && leaguePokemon !== null &&
|
|
||||||
<MovesExplorer
|
|
||||||
movesById={ combatMoves }
|
|
||||||
quickMoves={ leaguePokemon.moves.quick }
|
|
||||||
chargeMoves={ leaguePokemon.moves.cinematic }
|
|
||||||
selectedMoves={ selectedCombatMoves }
|
|
||||||
attackTypeEffectiveness={ null }
|
|
||||||
combatMoveSelectorsOpen={ combatMoveSelectorsOpen }
|
|
||||||
handleToggleDropdownOpen={ this.handleToggleDropdownOpen }
|
|
||||||
handleChangeSelectedMove={ this.handleChangeSelectedMove }
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div className={ leftNavCss }>
|
|
||||||
<button className={ pvpButtonCss } onClick={ this.handlePvpClick }><i className={ pvpCss } /></button>
|
|
||||||
<button className={ badgeButtonCss } onClick={ this.handleTypesClick }><i className={ badgeCss } /></button>
|
|
||||||
<button className={ tmButtonCss } onClick={ this.handleMovesClick }><i className={ tmCss } /></button>
|
|
||||||
</div>
|
|
||||||
{ isOverlayShown &&
|
|
||||||
<div className={ styles.overlay } onClick={ this.handleOverlayClick } />
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly handleToggleDropdownOpen = (menu : keyof CombatMoveSelectorsOpen, isOpen : boolean) => {
|
private readonly handleSearchInterruption = (isInterruption : boolean) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
isInterruption: isOpen,
|
activeNavigation: isInterruption ? 'pokedex' : null,
|
||||||
});
|
});
|
||||||
const combatMoveSelectorsOpen : CombatMoveSelectorsOpen = {
|
this.props.dispatch(ActionsPokemonApp.setIsInterruption(isInterruption));
|
||||||
...this.props.pokemonExplorerState.combatMoveSelectorsOpen,
|
|
||||||
[menu]: isOpen, // 3/10/2019: TyepScript is not checking this!
|
|
||||||
};
|
|
||||||
this.props.dispatch(ActionsPokemonExplorer.setCombatMoveSelectorsOpen(combatMoveSelectorsOpen));
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly handleOverlayClick = () => {
|
if (isInterruption) {
|
||||||
this.setState({
|
|
||||||
activeNavigation: null,
|
|
||||||
isInterruption: false,
|
|
||||||
});
|
|
||||||
this.props.dispatch(ActionsPokemonExplorer.setCombatMoveSelectorsOpen({
|
this.props.dispatch(ActionsPokemonExplorer.setCombatMoveSelectorsOpen({
|
||||||
quickMove: false,
|
quickMove: false,
|
||||||
chargeMove1: false,
|
chargeMove1: false,
|
||||||
chargeMove2: false,
|
chargeMove2: false,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly handleToggleInterruption = (isInterruption : boolean) => {
|
||||||
|
this.props.dispatch(ActionsPokemonApp.setIsInterruption(isInterruption));
|
||||||
|
if (!isInterruption) {
|
||||||
|
this.setState({
|
||||||
|
activeNavigation: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly handlePokedexClick = () => {
|
private readonly handlePokedexClick = () => {
|
||||||
this.setState({
|
this.handleSearchInterruption(true);
|
||||||
activeNavigation: this.state.activeNavigation !== 'pokedex' ? 'pokedex' : null,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly handlePvpClick = () => {
|
|
||||||
const widgets = this.state.widgets;
|
|
||||||
this.setState({
|
|
||||||
widgets: {
|
|
||||||
...widgets,
|
|
||||||
pvp: !widgets.pvp
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly handleTypesClick = () => {
|
|
||||||
const widgets = this.state.widgets;
|
|
||||||
this.setState({
|
|
||||||
widgets: {
|
|
||||||
...widgets,
|
|
||||||
types: !widgets.types
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly handleMovesClick = () => {
|
|
||||||
const widgets = this.state.widgets;
|
|
||||||
this.setState({
|
|
||||||
widgets: {
|
|
||||||
...widgets,
|
|
||||||
moves: !widgets.moves
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly handleActivatePokemon = (pokemonId : POGOProtos.Enums.PokemonId, form : POGOProtos.Enums.Form) => {
|
private readonly handleActivatePokemon = (pokemonId : POGOProtos.Enums.PokemonId, form : POGOProtos.Enums.Form) => {
|
||||||
@ -335,56 +202,10 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly handleChangeFilter = (filterTerm : string) => {
|
private readonly handleChangeFilter = (filterTerm : string) => {
|
||||||
this.setState({
|
this.handleSearchInterruption(true);
|
||||||
activeNavigation: 'pokedex',
|
|
||||||
});
|
|
||||||
return this.props.dispatch(ActionsPokemonSelectList.filterPokemonList(filterTerm));
|
return this.props.dispatch(ActionsPokemonSelectList.filterPokemonList(filterTerm));
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly handleMaximizeLevel = () => {
|
|
||||||
this.props.dispatch(ActionsPokemonExplorer.maximizeLevel());
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly handleChangeSelectedMove = (moves : SelectedCombatMoves) => {
|
|
||||||
this.props.dispatch(ActionsPokemonExplorer.setSelectedCombatMoves(moves));
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly handleChangeLeagueNavigation = (league : League) => {
|
|
||||||
const {
|
|
||||||
history,
|
|
||||||
location,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
history.push({
|
|
||||||
search: appendQueryString(location, { league: league.toString() })
|
|
||||||
});
|
|
||||||
|
|
||||||
this.handleChangeLeague(league);
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly handleChangeLeague = (league : League) => {
|
private readonly handleChangeLeague = (league : League) => {
|
||||||
this.props.dispatch(ActionsPokemonExplorer.setActiveLeague(league));
|
this.props.dispatch(ActionsPokemonExplorer.setActiveLeague(league));
|
||||||
}
|
}
|
||||||
@ -392,6 +213,7 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
|
|||||||
|
|
||||||
const mapStateToProps = (state : PokemonAppProps) : PokemonAppProps => {
|
const mapStateToProps = (state : PokemonAppProps) : PokemonAppProps => {
|
||||||
return {
|
return {
|
||||||
|
pokemonAppState: state.pokemonAppState,
|
||||||
pokemonExplorerState: state.pokemonExplorerState,
|
pokemonExplorerState: state.pokemonExplorerState,
|
||||||
pokemonSelectListState: state.pokemonSelectListState,
|
pokemonSelectListState: state.pokemonSelectListState,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,71 +1,23 @@
|
|||||||
import { action } from 'typesafe-actions';
|
import { action } from 'typesafe-actions';
|
||||||
|
|
||||||
import { CombatMoveSelectorsOpen, PokemonExplorerActionTypes, SelectedCombatMoves, ThunkResult } from 'app/types';
|
import { PokemonAppActionTypes, ThunkResult } from 'app/types';
|
||||||
|
|
||||||
import { calculateMaxLevelForLeague } from 'app/utils/calculator';
|
import { AttackTypeEffectiveness } from 'app/models/Config';
|
||||||
|
|
||||||
import { ILeaguePokemon, League } from 'app/models/League';
|
|
||||||
import { CombatMoveStats, 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 setIsInterruption = (isInterruption : boolean) => action(PokemonAppActionTypes.SET_IS_INTERRUPTION, { isInterruption });
|
||||||
|
export const setMaxPossibleStats = (maxStats : IMaxStats) => action(PokemonAppActionTypes.SET_MAX_STATS, { maxStats });
|
||||||
|
|
||||||
export const setMaxPossibleStats = (maxStats : IMaxStats) => action(PokemonExplorerActionTypes.SET_MAX_STATS, { maxStats });
|
export const setAttackTypeEffectiveness = (attackTypeEffectiveness : AttackTypeEffectiveness) => action(PokemonAppActionTypes.SET_COMBAT_MOVE_STATS, { attackTypeEffectiveness });
|
||||||
|
|
||||||
export const setCombatMoveStats = (combatMoves : CombatMoveStats) => action(PokemonExplorerActionTypes.SET_COMBAT_MOVE_STATS, { combatMoves });
|
export const setCombatMoveStats = (combatMoves : CombatMoveStats) => action(PokemonAppActionTypes.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 });
|
|
||||||
|
|
||||||
export const setIvHp = (ivHp : number | null) => action(PokemonExplorerActionTypes.SET_IV_HP, { ivHp });
|
|
||||||
|
|
||||||
export const setIvAtk = (ivAtk : number | null) => action(PokemonExplorerActionTypes.SET_IV_ATK, { ivAtk });
|
|
||||||
|
|
||||||
export const setIvDef = (ivDef : number | null) => action(PokemonExplorerActionTypes.SET_IV_DEF, { ivDef });
|
|
||||||
|
|
||||||
export const setActiveLeague = (league : League) => action(PokemonExplorerActionTypes.SET_ACTIVE_LEAGUE, { league });
|
|
||||||
|
|
||||||
export const setSelectedCombatMoves = (moves : SelectedCombatMoves) => action(PokemonExplorerActionTypes.SET_SELECTED_COMBAT_MOVES, { moves });
|
|
||||||
|
|
||||||
export const setCombatMoveSelectorsOpen = (selectorsOpen : CombatMoveSelectorsOpen) => action(PokemonExplorerActionTypes.SET_COMBAT_MOVE_SELECTORS_OPEN, { selectorsOpen });
|
|
||||||
|
|
||||||
export const fetchConfig = (
|
export const fetchConfig = (
|
||||||
) : ThunkResult<Promise<void>> => {
|
) : ThunkResult<Promise<void>> => {
|
||||||
return async (dispatch, getState, extraArguments) => {
|
return async (dispatch, getState, extraArguments) => {
|
||||||
const config = await extraArguments.services.pokemonService.getConfig();
|
const config = await extraArguments.services.pokemonService.getConfig();
|
||||||
dispatch(setMaxPossibleStats(config.maxPossibleStats));
|
dispatch(setMaxPossibleStats(config.maxPossibleStats));
|
||||||
|
dispatch(setAttackTypeEffectiveness(config.attackTypeEffectiveness));
|
||||||
dispatch(setCombatMoveStats(config.combatMoves));
|
dispatch(setCombatMoveStats(config.combatMoves));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const maximizeLevel = (
|
|
||||||
) : ThunkResult<Promise<void>> => {
|
|
||||||
return async (dispatch, getState, extraArguments) => {
|
|
||||||
const pokemonExplorerState = getState().pokemonExplorerState;
|
|
||||||
const {
|
|
||||||
ivHp,
|
|
||||||
ivAtk,
|
|
||||||
ivDef,
|
|
||||||
} = pokemonExplorerState.individualValues;
|
|
||||||
|
|
||||||
if (pokemonExplorerState.leaguePokemon !== null) {
|
|
||||||
const pokemonLeagueValues = pokemonExplorerState.leaguePokemon.pvp[pokemonExplorerState.league];
|
|
||||||
const statsSet = pokemonLeagueValues.some((stats) => {
|
|
||||||
if (((ivHp === null) || (stats.ivHp === ivHp)) &&
|
|
||||||
((ivAtk === null) || (stats.ivAtk === ivAtk)) &&
|
|
||||||
((ivDef === null) || (stats.ivDef === ivDef))
|
|
||||||
) {
|
|
||||||
dispatch(setIvHp(stats.ivHp));
|
|
||||||
dispatch(setIvAtk(stats.ivAtk));
|
|
||||||
dispatch(setIvDef(stats.ivDef));
|
|
||||||
dispatch(setIvLevel(stats.level));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
if (!statsSet && ivHp !== null && ivAtk !== null && ivDef !== null) {
|
|
||||||
dispatch(setIvLevel(calculateMaxLevelForLeague(pokemonExplorerState.leaguePokemon.stats, ivHp, ivAtk, ivDef, pokemonExplorerState.league)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { IIndividualValues, IndividualValueKey } from '../types';
|
import { IIndividualValues, IndividualValueKey } from 'app/components/PokemonExplorer/types';
|
||||||
|
|
||||||
import * as styles from 'app/styles/IvForm.scss';
|
import * as styles from 'app/styles/IvForm.scss';
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { IBestWorstStats, ILeaguePokemon, League, MaxCpByLeague } from 'app/mode
|
|||||||
import { Grade, IStats } from 'app/models/Pokemon';
|
import { Grade, IStats } from 'app/models/Pokemon';
|
||||||
import { calculateCp, calculateStatAtLevel } from 'app/utils/calculator';
|
import { calculateCp, calculateStatAtLevel } from 'app/utils/calculator';
|
||||||
|
|
||||||
import { IIndividualValues, IndividualValueKey } from 'app/types';
|
import { IIndividualValues, IndividualValueKey } from 'app/components/PokemonExplorer/types';
|
||||||
|
|
||||||
import { IvForm } from './IvForm';
|
import { IvForm } from './IvForm';
|
||||||
import { LeagueSelector } from './LeagueSelector';
|
import { LeagueSelector } from './LeagueSelector';
|
||||||
|
|||||||
@ -6,8 +6,8 @@ import { FixedSizeList } from 'react-window';
|
|||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { IIndividualValues } from 'app/components/PokemonExplorer/types';
|
||||||
import { Grade, IStats } from 'app/models/Pokemon';
|
import { Grade, IStats } from 'app/models/Pokemon';
|
||||||
import { IIndividualValues } from 'app/types';
|
|
||||||
|
|
||||||
import * as styles from 'app/styles/LeagueStatsList.scss';
|
import * as styles from 'app/styles/LeagueStatsList.scss';
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import classNames from 'classnames';
|
|||||||
import { AttackTypeEffectiveness } from 'app/models/Config';
|
import { AttackTypeEffectiveness } from 'app/models/Config';
|
||||||
import { CombatMoveStats, ICombatMoveStats, IPokemonMove } from 'app/models/Pokemon';
|
import { CombatMoveStats, ICombatMoveStats, IPokemonMove } from 'app/models/Pokemon';
|
||||||
|
|
||||||
import { CombatMoveSelectorsOpen, SelectedCombatMoves } from 'app/types';
|
import { CombatMoveSelectorsOpen, SelectedCombatMoves } from 'app/components/PokemonExplorer/types';
|
||||||
|
|
||||||
import { MovesDropdown } from 'app/components/MovesDropdown';
|
import { MovesDropdown } from 'app/components/MovesDropdown';
|
||||||
import { TypeIndicator } from './TypeIndicator';
|
import { TypeIndicator } from './TypeIndicator';
|
||||||
@ -21,7 +21,7 @@ export interface IMovesExplorerProps {
|
|||||||
chargeMove1 : IPokemonMove | null;
|
chargeMove1 : IPokemonMove | null;
|
||||||
chargeMove2 : IPokemonMove | null;
|
chargeMove2 : IPokemonMove | null;
|
||||||
};
|
};
|
||||||
attackTypeEffectiveness : AttackTypeEffectiveness | null;
|
attackTypeEffectiveness : AttackTypeEffectiveness;
|
||||||
combatMoveSelectorsOpen : CombatMoveSelectorsOpen;
|
combatMoveSelectorsOpen : CombatMoveSelectorsOpen;
|
||||||
handleToggleDropdownOpen : (menu : keyof CombatMoveSelectorsOpen, isOpen : boolean) => void;
|
handleToggleDropdownOpen : (menu : keyof CombatMoveSelectorsOpen, isOpen : boolean) => void;
|
||||||
handleChangeSelectedMove : (moves : SelectedCombatMoves) => void;
|
handleChangeSelectedMove : (moves : SelectedCombatMoves) => void;
|
||||||
|
|||||||
298
src/ts/app/components/PokemonExplorer/PokemonExplorer.tsx
Normal file
298
src/ts/app/components/PokemonExplorer/PokemonExplorer.tsx
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { RouteComponentProps } from 'react-router-dom';
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { AttackTypeEffectiveness } from 'app/models/Config';
|
||||||
|
import { League } from 'app/models/League';
|
||||||
|
import { CombatMoveStats } from 'app/models/Pokemon';
|
||||||
|
|
||||||
|
import * as ActionsPokemonExplorer from 'app/components/PokemonExplorer/actions';
|
||||||
|
import {
|
||||||
|
CombatMoveSelectorsOpen,
|
||||||
|
IndividualValueKey,
|
||||||
|
IPokemonExplorerDispatch,
|
||||||
|
IPokemonExplorerStore,
|
||||||
|
SelectedCombatMoves
|
||||||
|
} from 'app/components/PokemonExplorer/types';
|
||||||
|
import { IRouterProps } from 'app/types';
|
||||||
|
|
||||||
|
import { LeagueIvExplorer } from 'app/components/LeagueIvExplorer';
|
||||||
|
import { MovesExplorer } from 'app/components/MovesExplorer';
|
||||||
|
import { PokemonDisplay } from 'app/components/PokemonDisplay';
|
||||||
|
import { TypeEffectiveDisplay } from 'app/components/TypeEffectiveDisplay';
|
||||||
|
|
||||||
|
import { appendQueryString } from 'app/utils/navigation';
|
||||||
|
|
||||||
|
import * as styles from 'app/styles/PokemonApp.scss';
|
||||||
|
|
||||||
|
// TODO: better way to expose IRouterProps than just passing them in???
|
||||||
|
interface IPokemonExplorerProps extends IRouterProps {
|
||||||
|
isOverlaid : boolean;
|
||||||
|
attackTypeEffectiveness : AttackTypeEffectiveness;
|
||||||
|
combatMoves : CombatMoveStats;
|
||||||
|
toggleInterruption : (isInterruption : boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IConnectedPokemonExplorerProps extends IPokemonExplorerStore, IPokemonExplorerDispatch, IPokemonExplorerProps {}
|
||||||
|
|
||||||
|
type SubNavigation = 'pvp' | 'types' | 'moves';
|
||||||
|
interface IState {
|
||||||
|
widgets : { [ key in SubNavigation ] : boolean };
|
||||||
|
}
|
||||||
|
|
||||||
|
class PokemonExplorer extends React.Component<IConnectedPokemonExplorerProps, IState> {
|
||||||
|
|
||||||
|
constructor(props : IConnectedPokemonExplorerProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
widgets: {
|
||||||
|
pvp: true,
|
||||||
|
types: false,
|
||||||
|
moves: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const {
|
||||||
|
combatMoves,
|
||||||
|
attackTypeEffectiveness,
|
||||||
|
} = this.props;
|
||||||
|
const {
|
||||||
|
league,
|
||||||
|
individualValues,
|
||||||
|
leaguePokemon,
|
||||||
|
selectedCombatMoves,
|
||||||
|
combatMoveSelectorsOpen,
|
||||||
|
} = this.props.pokemonExplorerState;
|
||||||
|
const {
|
||||||
|
widgets,
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
const isOverlayShown = this.props.isOverlaid || combatMoveSelectorsOpen.quickMove || combatMoveSelectorsOpen.chargeMove1 || combatMoveSelectorsOpen.chargeMove2;
|
||||||
|
|
||||||
|
const leftNavCss = classNames(
|
||||||
|
styles.leftNavigation,
|
||||||
|
);
|
||||||
|
|
||||||
|
const displayWrapperCss = classNames(
|
||||||
|
styles.displayWrapper,
|
||||||
|
);
|
||||||
|
|
||||||
|
const iconCss = classNames(
|
||||||
|
'icon',
|
||||||
|
'pixel',
|
||||||
|
'sprite',
|
||||||
|
);
|
||||||
|
|
||||||
|
const pvpCss = classNames(
|
||||||
|
iconCss,
|
||||||
|
'pvp',
|
||||||
|
{
|
||||||
|
active: widgets.pvp,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const pvpButtonCss = classNames(
|
||||||
|
// {
|
||||||
|
// [styles.activeNavigationButton]: widgets.pvp,
|
||||||
|
// }
|
||||||
|
);
|
||||||
|
const badgeCss = classNames(
|
||||||
|
iconCss,
|
||||||
|
'badge',
|
||||||
|
{
|
||||||
|
active: widgets.types,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const badgeButtonCss = classNames(
|
||||||
|
// {
|
||||||
|
// [styles.activeNavigationButton]: widgets.types,
|
||||||
|
// }
|
||||||
|
);
|
||||||
|
const tmCss = classNames(
|
||||||
|
iconCss,
|
||||||
|
'tm',
|
||||||
|
{
|
||||||
|
active: widgets.moves,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const tmButtonCss = classNames(
|
||||||
|
// {
|
||||||
|
// [styles.activeNavigationButton]: widgets.moves,
|
||||||
|
// }
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={ styles.body }>
|
||||||
|
<div className={ displayWrapperCss }>
|
||||||
|
{ leaguePokemon !== null &&
|
||||||
|
<PokemonDisplay
|
||||||
|
leaguePokemon={ leaguePokemon }
|
||||||
|
isHighlighted={ isOverlayShown }
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
{ widgets.types && leaguePokemon !== null &&
|
||||||
|
<TypeEffectiveDisplay
|
||||||
|
effectiveness={ leaguePokemon.effectiveness }
|
||||||
|
pokemonName={ leaguePokemon.name }
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
{ widgets.pvp && leaguePokemon !== null &&
|
||||||
|
<LeagueIvExplorer
|
||||||
|
activeLeague={ league }
|
||||||
|
leaguePokemon={ leaguePokemon }
|
||||||
|
individualValues={ individualValues }
|
||||||
|
handleChangeIndividualValue={ this.handleChangeIndividualValue }
|
||||||
|
handleMaximizeLevel={ this.handleMaximizeLevel }
|
||||||
|
handleChangeLeague={ this.handleChangeLeague }
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
{ widgets.moves && leaguePokemon !== null &&
|
||||||
|
<MovesExplorer
|
||||||
|
movesById={ combatMoves }
|
||||||
|
quickMoves={ leaguePokemon.moves.quick }
|
||||||
|
chargeMoves={ leaguePokemon.moves.cinematic }
|
||||||
|
selectedMoves={ selectedCombatMoves }
|
||||||
|
attackTypeEffectiveness={ attackTypeEffectiveness }
|
||||||
|
combatMoveSelectorsOpen={ combatMoveSelectorsOpen }
|
||||||
|
handleToggleDropdownOpen={ this.handleToggleDropdownOpen }
|
||||||
|
handleChangeSelectedMove={ this.handleChangeSelectedMove }
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className={ leftNavCss }>
|
||||||
|
<button className={ pvpButtonCss } onClick={ this.handlePvpClick }><i className={ pvpCss } /></button>
|
||||||
|
<button className={ badgeButtonCss } onClick={ this.handleTypesClick }><i className={ badgeCss } /></button>
|
||||||
|
<button className={ tmButtonCss } onClick={ this.handleMovesClick }><i className={ tmCss } /></button>
|
||||||
|
</div>
|
||||||
|
{ isOverlayShown &&
|
||||||
|
<div className={ styles.overlay } onClick={ this.handleOverlayClick } />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly handleToggleDropdownOpen = (menu : keyof CombatMoveSelectorsOpen, isOpen : boolean) => {
|
||||||
|
const combatMoveSelectorsOpen : CombatMoveSelectorsOpen = {
|
||||||
|
...this.props.pokemonExplorerState.combatMoveSelectorsOpen,
|
||||||
|
[menu]: isOpen, // 3/10/2019: TyepScript is not checking this!
|
||||||
|
};
|
||||||
|
this.props.dispatch(ActionsPokemonExplorer.setCombatMoveSelectorsOpen(combatMoveSelectorsOpen));
|
||||||
|
this.props.toggleInterruption(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly handleOverlayClick = () => {
|
||||||
|
this.props.dispatch(ActionsPokemonExplorer.setCombatMoveSelectorsOpen({
|
||||||
|
quickMove: false,
|
||||||
|
chargeMove1: false,
|
||||||
|
chargeMove2: false,
|
||||||
|
}));
|
||||||
|
this.props.toggleInterruption(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly handlePvpClick = () => {
|
||||||
|
const widgets = this.state.widgets;
|
||||||
|
this.setState({
|
||||||
|
widgets: {
|
||||||
|
...widgets,
|
||||||
|
pvp: !widgets.pvp
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly handleTypesClick = () => {
|
||||||
|
const widgets = this.state.widgets;
|
||||||
|
this.setState({
|
||||||
|
widgets: {
|
||||||
|
...widgets,
|
||||||
|
types: !widgets.types
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly handleMovesClick = () => {
|
||||||
|
const widgets = this.state.widgets;
|
||||||
|
this.setState({
|
||||||
|
widgets: {
|
||||||
|
...widgets,
|
||||||
|
moves: !widgets.moves
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly handleMaximizeLevel = () => {
|
||||||
|
this.props.dispatch(ActionsPokemonExplorer.maximizeLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly handleChangeSelectedMove = (moves : SelectedCombatMoves) => {
|
||||||
|
this.props.dispatch(ActionsPokemonExplorer.setSelectedCombatMoves(moves));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make this not overwrite other query parameters
|
||||||
|
private readonly handleChangeLeagueNavigation = (league : League) => {
|
||||||
|
const {
|
||||||
|
history,
|
||||||
|
location,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
history.push({
|
||||||
|
search: appendQueryString(location, { league: league.toString() })
|
||||||
|
});
|
||||||
|
|
||||||
|
this.handleChangeLeague(league);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly handleChangeLeague = (league : League) => {
|
||||||
|
this.props.dispatch(ActionsPokemonExplorer.setActiveLeague(league));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state : IPokemonExplorerStore) : IPokemonExplorerStore => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch : IPokemonExplorerDispatch['dispatch']) : IPokemonExplorerDispatch => {
|
||||||
|
return {
|
||||||
|
dispatch
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mergeProps = (state : IPokemonExplorerStore, dispatchProps : IPokemonExplorerDispatch, ownProps : IPokemonExplorerProps) : IConnectedPokemonExplorerProps => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
...dispatchProps,
|
||||||
|
...ownProps,
|
||||||
|
history: ownProps.history,
|
||||||
|
location: ownProps.location,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ConnectedPokemonExplorer = connect(mapStateToProps, mapDispatchToProps, mergeProps)(PokemonExplorer);
|
||||||
62
src/ts/app/components/PokemonExplorer/actions.ts
Normal file
62
src/ts/app/components/PokemonExplorer/actions.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { action } from 'typesafe-actions';
|
||||||
|
|
||||||
|
import {
|
||||||
|
CombatMoveSelectorsOpen,
|
||||||
|
PokemonExplorerActionTypes,
|
||||||
|
SelectedCombatMoves,
|
||||||
|
ThunkResult
|
||||||
|
} from 'app/components/PokemonExplorer/types';
|
||||||
|
|
||||||
|
import { calculateMaxLevelForLeague } from 'app/utils/calculator';
|
||||||
|
|
||||||
|
import { ILeaguePokemon, League } from 'app/models/League';
|
||||||
|
|
||||||
|
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 = (ivHp : number | null) => action(PokemonExplorerActionTypes.SET_IV_HP, { ivHp });
|
||||||
|
|
||||||
|
export const setIvAtk = (ivAtk : number | null) => action(PokemonExplorerActionTypes.SET_IV_ATK, { ivAtk });
|
||||||
|
|
||||||
|
export const setIvDef = (ivDef : number | null) => action(PokemonExplorerActionTypes.SET_IV_DEF, { ivDef });
|
||||||
|
|
||||||
|
export const setActiveLeague = (league : League) => action(PokemonExplorerActionTypes.SET_ACTIVE_LEAGUE, { league });
|
||||||
|
|
||||||
|
export const setSelectedCombatMoves = (moves : SelectedCombatMoves) => action(PokemonExplorerActionTypes.SET_SELECTED_COMBAT_MOVES, { moves });
|
||||||
|
|
||||||
|
export const setCombatMoveSelectorsOpen = (selectorsOpen : CombatMoveSelectorsOpen) => action(PokemonExplorerActionTypes.SET_COMBAT_MOVE_SELECTORS_OPEN, { selectorsOpen });
|
||||||
|
|
||||||
|
export const maximizeLevel = (
|
||||||
|
) : ThunkResult<Promise<void>> => {
|
||||||
|
return async (dispatch, getState, extraArguments) => {
|
||||||
|
const pokemonExplorerState = getState().pokemonExplorerState;
|
||||||
|
const {
|
||||||
|
ivHp,
|
||||||
|
ivAtk,
|
||||||
|
ivDef,
|
||||||
|
} = pokemonExplorerState.individualValues;
|
||||||
|
|
||||||
|
if (pokemonExplorerState.leaguePokemon !== null) {
|
||||||
|
const pokemonLeagueValues = pokemonExplorerState.leaguePokemon.pvp[pokemonExplorerState.league];
|
||||||
|
const statsSet = pokemonLeagueValues.some((stats) => {
|
||||||
|
if (((ivHp === null) || (stats.ivHp === ivHp)) &&
|
||||||
|
((ivAtk === null) || (stats.ivAtk === ivAtk)) &&
|
||||||
|
((ivDef === null) || (stats.ivDef === ivDef))
|
||||||
|
) {
|
||||||
|
dispatch(setIvHp(stats.ivHp));
|
||||||
|
dispatch(setIvAtk(stats.ivAtk));
|
||||||
|
dispatch(setIvDef(stats.ivDef));
|
||||||
|
dispatch(setIvLevel(stats.level));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
if (!statsSet && ivHp !== null && ivAtk !== null && ivDef !== null) {
|
||||||
|
dispatch(setIvLevel(calculateMaxLevelForLeague(pokemonExplorerState.leaguePokemon.stats, ivHp, ivAtk, ivDef, pokemonExplorerState.league)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
144
src/ts/app/components/PokemonExplorer/reducers.ts
Normal file
144
src/ts/app/components/PokemonExplorer/reducers.ts
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import { Reducer } from 'redux';
|
||||||
|
|
||||||
|
import { League } from 'app/models/League';
|
||||||
|
|
||||||
|
import * as Actions from 'app/components/PokemonExplorer/actions';
|
||||||
|
import { IPokemonExplorerState, PokemonExplorerActionTypes } from 'app/components/PokemonExplorer/types';
|
||||||
|
|
||||||
|
export const initialState : IPokemonExplorerState = {
|
||||||
|
isLoading: false,
|
||||||
|
leaguePokemon: null,
|
||||||
|
individualValues: {
|
||||||
|
level: null,
|
||||||
|
ivHp: null,
|
||||||
|
ivAtk: null,
|
||||||
|
ivDef: null,
|
||||||
|
},
|
||||||
|
league: League.GREAT,
|
||||||
|
selectedCombatMoves: {
|
||||||
|
quickMove: null,
|
||||||
|
chargeMove1: null,
|
||||||
|
chargeMove2: null,
|
||||||
|
},
|
||||||
|
combatMoveSelectorsOpen: {
|
||||||
|
quickMove: false,
|
||||||
|
chargeMove1: false,
|
||||||
|
chargeMove2: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const reduceSetIsLoading = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setIsLoading>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
isLoading: action.payload.isLoading,
|
||||||
|
});
|
||||||
|
|
||||||
|
const reduceSetLeaguePokemon = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setLeaguePokemon>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
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,
|
||||||
|
ivHp: action.payload.ivHp,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const reduceSetIvAtk = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setIvAtk>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
individualValues: {
|
||||||
|
...state.individualValues,
|
||||||
|
ivAtk: action.payload.ivAtk,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const reduceSetIvDef = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setIvDef>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
individualValues: {
|
||||||
|
...state.individualValues,
|
||||||
|
ivDef: action.payload.ivDef,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const reduceSetActiveLeague = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setActiveLeague>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
league: action.payload.league
|
||||||
|
});
|
||||||
|
|
||||||
|
const reduceSetSelectedCombatMoves = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setSelectedCombatMoves>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
selectedCombatMoves: {
|
||||||
|
...action.payload.moves
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const reduceSetCombatMoveSelectorsOpen = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setCombatMoveSelectorsOpen>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
combatMoveSelectorsOpen: {
|
||||||
|
...action.payload.selectorsOpen
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
||||||
|
state : IPokemonExplorerState = initialState,
|
||||||
|
action,
|
||||||
|
) : IPokemonExplorerState => {
|
||||||
|
switch (action.type) {
|
||||||
|
case PokemonExplorerActionTypes.SET_IS_LOADING:
|
||||||
|
return reduceSetIsLoading(state, action as ReturnType<typeof Actions.setIsLoading>);
|
||||||
|
case PokemonExplorerActionTypes.SET_LEAGUE_POKEMON:
|
||||||
|
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>);
|
||||||
|
case PokemonExplorerActionTypes.SET_ACTIVE_LEAGUE:
|
||||||
|
return reduceSetActiveLeague(state, action as ReturnType<typeof Actions.setActiveLeague>);
|
||||||
|
case PokemonExplorerActionTypes.SET_SELECTED_COMBAT_MOVES:
|
||||||
|
return reduceSetSelectedCombatMoves(state, action as ReturnType<typeof Actions.setSelectedCombatMoves>);
|
||||||
|
case PokemonExplorerActionTypes.SET_COMBAT_MOVE_SELECTORS_OPEN:
|
||||||
|
return reduceSetCombatMoveSelectorsOpen(state, action as ReturnType<typeof Actions.setCombatMoveSelectorsOpen>);
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
66
src/ts/app/components/PokemonExplorer/types.ts
Normal file
66
src/ts/app/components/PokemonExplorer/types.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { Action } from 'redux';
|
||||||
|
import { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
||||||
|
|
||||||
|
import { IProviderExtraArguments } from 'common/models/IProviderExtraArguments';
|
||||||
|
|
||||||
|
import { ILeaguePokemon, League } from 'app/models/League';
|
||||||
|
import { IPokemonMove } from 'app/models/Pokemon';
|
||||||
|
|
||||||
|
import { PokemonService } from 'api/PokemonService';
|
||||||
|
|
||||||
|
export type IndividualValueKey = 'level' | 'hp' | 'atk' | 'def';
|
||||||
|
export interface IIndividualValues {
|
||||||
|
level : number | null;
|
||||||
|
ivHp : number | null;
|
||||||
|
ivAtk : number | null;
|
||||||
|
ivDef : number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
type MoveTypes = 'quickMove' | 'chargeMove1' | 'chargeMove2';
|
||||||
|
|
||||||
|
export type SelectedCombatMoves = {
|
||||||
|
[ key in MoveTypes ] : IPokemonMove | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CombatMoveSelectorsOpen = {
|
||||||
|
[ key in MoveTypes ] : boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface IPokemonExplorerState {
|
||||||
|
isLoading : boolean;
|
||||||
|
leaguePokemon : ILeaguePokemon | null;
|
||||||
|
individualValues : IIndividualValues;
|
||||||
|
league : League;
|
||||||
|
selectedCombatMoves : SelectedCombatMoves;
|
||||||
|
combatMoveSelectorsOpen : CombatMoveSelectorsOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
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',
|
||||||
|
SET_ACTIVE_LEAGUE: 'POKEMON_EXPLORER/SET_ACTIVE_LEAGUE',
|
||||||
|
SET_SELECTED_COMBAT_MOVES: 'POKEMON_EXPLORER/SET_SELECTED_COMBAT_MOVES',
|
||||||
|
SET_COMBAT_MOVE_SELECTORS_OPEN: 'POKEMON_EXPLORER/SET_COMBAT_MOVE_SELECTORS_OPEN',
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface IPokemonExplorerStore {
|
||||||
|
pokemonExplorerState : IPokemonExplorerState;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPokemonExplorerServices {
|
||||||
|
pokemonService : PokemonService;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPokemonExplorerExtraArguments extends IProviderExtraArguments {
|
||||||
|
services : IPokemonExplorerServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ThunkResult<R> = ThunkAction<R, IPokemonExplorerStore, IPokemonExplorerExtraArguments, Action>;
|
||||||
|
type ThunkDispatchPokemonExplorer = ThunkDispatch<IPokemonExplorerStore, IPokemonExplorerExtraArguments, Action>;
|
||||||
|
export interface IPokemonExplorerDispatch {
|
||||||
|
dispatch : ThunkDispatchPokemonExplorer;
|
||||||
|
}
|
||||||
@ -9,12 +9,14 @@ import { IPokemonAppExtraArguments } from 'app/types';
|
|||||||
|
|
||||||
import { PokemonService } from 'api/PokemonService';
|
import { PokemonService } from 'api/PokemonService';
|
||||||
|
|
||||||
|
import { PokemonExplorerReducers } from 'app/components/PokemonExplorer/reducers';
|
||||||
import { PokemonSelectListReducers } from 'app/components/PokemonSelectList/reducers';
|
import { PokemonSelectListReducers } from 'app/components/PokemonSelectList/reducers';
|
||||||
import { PokemonExplorerReducers } from 'app/reducers';
|
import { PokemonAppReducers } from 'app/reducers';
|
||||||
|
|
||||||
import { ConnectedPokemonApp } from './PokemonApp';
|
import { ConnectedPokemonApp } from './PokemonApp';
|
||||||
|
|
||||||
export const appReducers = Redux.combineReducers({
|
export const appReducers = Redux.combineReducers({
|
||||||
|
pokemonAppState: PokemonAppReducers,
|
||||||
pokemonSelectListState: PokemonSelectListReducers,
|
pokemonSelectListState: PokemonSelectListReducers,
|
||||||
pokemonExplorerState: PokemonExplorerReducers,
|
pokemonExplorerState: PokemonExplorerReducers,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,172 +1,67 @@
|
|||||||
import { Reducer } from 'redux';
|
import { Reducer } from 'redux';
|
||||||
|
|
||||||
import { League } from 'app/models/League';
|
|
||||||
|
|
||||||
import * as Actions from 'app/actions';
|
import * as Actions from 'app/actions';
|
||||||
import { IPokemonExplorerState, PokemonExplorerActionTypes } from 'app/types';
|
import { IPokemonAppState, PokemonAppActionTypes } from 'app/types';
|
||||||
|
|
||||||
export const initialState : IPokemonExplorerState = {
|
export const initialState : IPokemonAppState = {
|
||||||
isLoading: false,
|
isInterruption: false,
|
||||||
leaguePokemon: null,
|
|
||||||
maxPossibleStats: {
|
maxPossibleStats: {
|
||||||
baseStamina: 0,
|
baseStamina: 0,
|
||||||
baseAttack: 0,
|
baseAttack: 0,
|
||||||
baseDefense: 0,
|
baseDefense: 0,
|
||||||
level: 0,
|
level: 0,
|
||||||
},
|
},
|
||||||
individualValues: {
|
attackTypeEffectiveness: new Map(),
|
||||||
level: null,
|
|
||||||
ivHp: null,
|
|
||||||
ivAtk: null,
|
|
||||||
ivDef: null,
|
|
||||||
},
|
|
||||||
league: League.GREAT,
|
|
||||||
combatMoves: new Map(),
|
combatMoves: new Map(),
|
||||||
selectedCombatMoves: {
|
|
||||||
quickMove: null,
|
|
||||||
chargeMove1: null,
|
|
||||||
chargeMove2: null,
|
|
||||||
},
|
|
||||||
combatMoveSelectorsOpen: {
|
|
||||||
quickMove: false,
|
|
||||||
chargeMove1: false,
|
|
||||||
chargeMove2: false,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const reduceSetIsLoading = (
|
const reduceSetInterruption = (
|
||||||
state : IPokemonExplorerState,
|
state : IPokemonAppState,
|
||||||
action : ReturnType<typeof Actions.setIsLoading>
|
action : ReturnType<typeof Actions.setIsInterruption>
|
||||||
) : IPokemonExplorerState => ({
|
) : IPokemonAppState => ({
|
||||||
...state,
|
...state,
|
||||||
isLoading: action.payload.isLoading,
|
isInterruption: action.payload.isInterruption,
|
||||||
});
|
});
|
||||||
|
|
||||||
const reduceSetMaxPossibleStats = (
|
const reduceSetMaxPossibleStats = (
|
||||||
state : IPokemonExplorerState,
|
state : IPokemonAppState,
|
||||||
action : ReturnType<typeof Actions.setMaxPossibleStats>
|
action : ReturnType<typeof Actions.setMaxPossibleStats>
|
||||||
) : IPokemonExplorerState => ({
|
) : IPokemonAppState => ({
|
||||||
...state,
|
...state,
|
||||||
maxPossibleStats: {
|
maxPossibleStats: {
|
||||||
...action.payload.maxStats,
|
...action.payload.maxStats,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const reduceSetAttackTypeEffectiveness = (
|
||||||
|
state : IPokemonAppState,
|
||||||
|
action : ReturnType<typeof Actions.setAttackTypeEffectiveness>
|
||||||
|
) : IPokemonAppState => ({
|
||||||
|
...state,
|
||||||
|
attackTypeEffectiveness: action.payload.attackTypeEffectiveness,
|
||||||
|
});
|
||||||
|
|
||||||
const reduceSetCombatMoveStats = (
|
const reduceSetCombatMoveStats = (
|
||||||
state : IPokemonExplorerState,
|
state : IPokemonAppState,
|
||||||
action : ReturnType<typeof Actions.setCombatMoveStats>
|
action : ReturnType<typeof Actions.setCombatMoveStats>
|
||||||
) : IPokemonExplorerState => ({
|
) : IPokemonAppState => ({
|
||||||
...state,
|
...state,
|
||||||
combatMoves: action.payload.combatMoves,
|
combatMoves: action.payload.combatMoves,
|
||||||
});
|
});
|
||||||
|
|
||||||
const reduceSetLeaguePokemon = (
|
export const PokemonAppReducers : Reducer<IPokemonAppState> = (
|
||||||
state : IPokemonExplorerState,
|
state : IPokemonAppState = initialState,
|
||||||
action : ReturnType<typeof Actions.setLeaguePokemon>
|
|
||||||
) : IPokemonExplorerState => ({
|
|
||||||
...state,
|
|
||||||
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,
|
|
||||||
ivHp: action.payload.ivHp,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const reduceSetIvAtk = (
|
|
||||||
state : IPokemonExplorerState,
|
|
||||||
action : ReturnType<typeof Actions.setIvAtk>
|
|
||||||
) : IPokemonExplorerState => ({
|
|
||||||
...state,
|
|
||||||
individualValues: {
|
|
||||||
...state.individualValues,
|
|
||||||
ivAtk: action.payload.ivAtk,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const reduceSetIvDef = (
|
|
||||||
state : IPokemonExplorerState,
|
|
||||||
action : ReturnType<typeof Actions.setIvDef>
|
|
||||||
) : IPokemonExplorerState => ({
|
|
||||||
...state,
|
|
||||||
individualValues: {
|
|
||||||
...state.individualValues,
|
|
||||||
ivDef: action.payload.ivDef,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const reduceSetActiveLeague = (
|
|
||||||
state : IPokemonExplorerState,
|
|
||||||
action : ReturnType<typeof Actions.setActiveLeague>
|
|
||||||
) : IPokemonExplorerState => ({
|
|
||||||
...state,
|
|
||||||
league: action.payload.league
|
|
||||||
});
|
|
||||||
|
|
||||||
const reduceSetSelectedCombatMoves = (
|
|
||||||
state : IPokemonExplorerState,
|
|
||||||
action : ReturnType<typeof Actions.setSelectedCombatMoves>
|
|
||||||
) : IPokemonExplorerState => ({
|
|
||||||
...state,
|
|
||||||
selectedCombatMoves: {
|
|
||||||
...action.payload.moves
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const reduceSetCombatMoveSelectorsOpen = (
|
|
||||||
state : IPokemonExplorerState,
|
|
||||||
action : ReturnType<typeof Actions.setCombatMoveSelectorsOpen>
|
|
||||||
) : IPokemonExplorerState => ({
|
|
||||||
...state,
|
|
||||||
combatMoveSelectorsOpen: {
|
|
||||||
...action.payload.selectorsOpen
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
|
||||||
state : IPokemonExplorerState = initialState,
|
|
||||||
action,
|
action,
|
||||||
) : IPokemonExplorerState => {
|
) : IPokemonAppState => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case PokemonExplorerActionTypes.SET_IS_LOADING:
|
case PokemonAppActionTypes.SET_IS_INTERRUPTION:
|
||||||
return reduceSetIsLoading(state, action as ReturnType<typeof Actions.setIsLoading>);
|
return reduceSetInterruption(state, action as ReturnType<typeof Actions.setIsInterruption>);
|
||||||
case PokemonExplorerActionTypes.SET_MAX_STATS:
|
case PokemonAppActionTypes.SET_MAX_STATS:
|
||||||
return reduceSetMaxPossibleStats(state, action as ReturnType<typeof Actions.setMaxPossibleStats>);
|
return reduceSetMaxPossibleStats(state, action as ReturnType<typeof Actions.setMaxPossibleStats>);
|
||||||
case PokemonExplorerActionTypes.SET_COMBAT_MOVE_STATS:
|
case PokemonAppActionTypes.SET_ATTACK_TYPE_EFFECTIVENESS:
|
||||||
|
return reduceSetAttackTypeEffectiveness(state, action as ReturnType<typeof Actions.setAttackTypeEffectiveness>);
|
||||||
|
case PokemonAppActionTypes.SET_COMBAT_MOVE_STATS:
|
||||||
return reduceSetCombatMoveStats(state, action as ReturnType<typeof Actions.setCombatMoveStats>);
|
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:
|
|
||||||
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>);
|
|
||||||
case PokemonExplorerActionTypes.SET_ACTIVE_LEAGUE:
|
|
||||||
return reduceSetActiveLeague(state, action as ReturnType<typeof Actions.setActiveLeague>);
|
|
||||||
case PokemonExplorerActionTypes.SET_SELECTED_COMBAT_MOVES:
|
|
||||||
return reduceSetSelectedCombatMoves(state, action as ReturnType<typeof Actions.setSelectedCombatMoves>);
|
|
||||||
case PokemonExplorerActionTypes.SET_COMBAT_MOVE_SELECTORS_OPEN:
|
|
||||||
return reduceSetCombatMoveSelectorsOpen(state, action as ReturnType<typeof Actions.setCombatMoveSelectorsOpen>);
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +1,35 @@
|
|||||||
import POGOProtos from 'pogo-protos';
|
import { RouteComponentProps } from 'react-router-dom';
|
||||||
|
|
||||||
import { Action } from 'redux';
|
import { Action } from 'redux';
|
||||||
import { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
import { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
||||||
|
|
||||||
import { IProviderExtraArguments } from 'common/models/IProviderExtraArguments';
|
import { IProviderExtraArguments } from 'common/models/IProviderExtraArguments';
|
||||||
|
|
||||||
|
import { IPokemonExplorerStore } from 'app/components/PokemonExplorer/types';
|
||||||
import { IPokemonSelectListState } from 'app/components/PokemonSelectList/types';
|
import { IPokemonSelectListState } from 'app/components/PokemonSelectList/types';
|
||||||
|
import { AttackTypeEffectiveness } from 'app/models/Config';
|
||||||
import { ILeaguePokemon, League } from 'app/models/League';
|
import { CombatMoveStats, IMaxStats } from 'app/models/Pokemon';
|
||||||
import { CombatMoveStats, IMaxStats, IPokemonMove } from 'app/models/Pokemon';
|
|
||||||
|
|
||||||
import { PokemonService } from 'api/PokemonService';
|
import { PokemonService } from 'api/PokemonService';
|
||||||
|
|
||||||
export interface IPokemonAppStore {
|
export interface IPokemonAppState {
|
||||||
pokemonSelectListState : IPokemonSelectListState;
|
isInterruption : boolean;
|
||||||
pokemonExplorerState : IPokemonExplorerState;
|
maxPossibleStats : IMaxStats;
|
||||||
|
attackTypeEffectiveness : AttackTypeEffectiveness;
|
||||||
|
combatMoves : CombatMoveStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const PokemonAppActionTypes = {
|
||||||
|
SET_IS_INTERRUPTION: 'POKEMON_APP/SET_IS_INTERRUPTION',
|
||||||
|
SET_MAX_STATS: 'POKEMON_APP/SET_MAX_STATS',
|
||||||
|
SET_ATTACK_TYPE_EFFECTIVENESS: 'POKEMON_APP/SET_ATTACK_TYPE_EFFECTIVENESS',
|
||||||
|
SET_COMBAT_MOVE_STATS: 'POKEMON_APP/SET_COMBAT_MOVE_STATS',
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface IPokemonAppStore extends IPokemonExplorerStore {
|
||||||
|
pokemonSelectListState : IPokemonSelectListState;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: do i need to import/extend a service from PokemonExplorer?
|
||||||
export interface IPokemonAppServices {
|
export interface IPokemonAppServices {
|
||||||
pokemonService : PokemonService;
|
pokemonService : PokemonService;
|
||||||
}
|
}
|
||||||
@ -25,51 +38,13 @@ export interface IPokemonAppExtraArguments extends IProviderExtraArguments {
|
|||||||
services : IPokemonAppServices;
|
services : IPokemonAppServices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IRouterProps {
|
||||||
|
history : RouteComponentProps['history'];
|
||||||
|
location : RouteComponentProps['location'];
|
||||||
|
}
|
||||||
|
|
||||||
export type ThunkResult<R> = ThunkAction<R, IPokemonAppStore, IPokemonAppExtraArguments, Action>;
|
export type ThunkResult<R> = ThunkAction<R, IPokemonAppStore, IPokemonAppExtraArguments, Action>;
|
||||||
type ThunkDispatchPokemonApp = ThunkDispatch<IPokemonAppStore, IPokemonAppExtraArguments, Action>;
|
type ThunkDispatchPokemonApp = ThunkDispatch<IPokemonAppStore, IPokemonAppExtraArguments, Action>;
|
||||||
export interface IPokemonAppDispatch {
|
export interface IPokemonAppDispatch {
|
||||||
dispatch : ThunkDispatchPokemonApp;
|
dispatch : ThunkDispatchPokemonApp;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IndividualValueKey = 'level' | 'hp' | 'atk' | 'def';
|
|
||||||
export interface IIndividualValues {
|
|
||||||
level : number | null;
|
|
||||||
ivHp : number | null;
|
|
||||||
ivAtk : number | null;
|
|
||||||
ivDef : number | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
type MoveTypes = 'quickMove' | 'chargeMove1' | 'chargeMove2';
|
|
||||||
|
|
||||||
export type SelectedCombatMoves = {
|
|
||||||
[ key in MoveTypes ] : IPokemonMove | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CombatMoveSelectorsOpen = {
|
|
||||||
[ key in MoveTypes ] : boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface IPokemonExplorerState {
|
|
||||||
isLoading : boolean;
|
|
||||||
leaguePokemon : ILeaguePokemon | null;
|
|
||||||
maxPossibleStats : IMaxStats;
|
|
||||||
individualValues : IIndividualValues;
|
|
||||||
league : League;
|
|
||||||
combatMoves : CombatMoveStats;
|
|
||||||
selectedCombatMoves : SelectedCombatMoves;
|
|
||||||
combatMoveSelectorsOpen : CombatMoveSelectorsOpen;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_SELECTED_COMBAT_MOVES: 'POKEMON_EXPLORER/SET_SELECTED_COMBAT_MOVES',
|
|
||||||
SET_COMBAT_MOVE_SELECTORS_OPEN: 'POKEMON_EXPLORER/SET_COMBAT_MOVE_SELECTORS_OPEN',
|
|
||||||
};
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user