pvpokemon/src/ts/app/PokemonApp.tsx
2019-02-19 19:29:32 -05:00

206 lines
7.4 KiB
TypeScript

import POGOProtos from 'pogo-protos';
import React from 'react';
import { connect } from 'react-redux';
import { RouteComponentProps } from 'react-router-dom';
import { League } from 'app/models/League';
import { appReducers } from './index';
import * as ActionsPokemonExplorer from './components/PokemonExplorer/actions';
import * as ActionsPokemonSelectList from './components/PokemonSelectList/actions';
import { IPokemonAppDispatch } from './types';
import { IndividualValueKey } from './components/PokemonExplorer/types';
import { Footer } from './components/Footer';
import { Header } from './components/Header';
import { PokemonExplorer } from './components/PokemonExplorer/PokemonExplorer';
import { PokemonSelectList } from './components/PokemonSelectList/PokemonSelectList';
import { appendQueryString, getCurrentQueryStringVlaues } from 'app/utils/navigation';
import * as styles from './styles/PokemonApp.scss';
type PokemonAppProps = ReturnType<typeof appReducers>;
interface IConnectedPokemonAppProps extends PokemonAppProps, IPokemonAppDispatch {
history : RouteComponentProps['history'];
location : RouteComponentProps['location'];
}
class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
constructor(props : IConnectedPokemonAppProps) {
super(props);
}
public async componentWillMount() {
const {
location,
dispatch
} = this.props;
await Promise.all([
dispatch(ActionsPokemonExplorer.fetchConfig()),
dispatch(ActionsPokemonSelectList.fetchPokemonList())
]);
dispatch(ActionsPokemonSelectList.setIsLoading(false));
const [
pokemonIdValue,
pokemonFormValue,
activeLeagueValue,
] = getCurrentQueryStringVlaues(location, 'id', 'form', 'league');
const pokemonId = pokemonIdValue !== null ? parseInt(pokemonIdValue, 10) : null;
const pokemonForm = pokemonFormValue ? parseInt(pokemonFormValue, 10) : null;
if (pokemonId !== null && typeof POGOProtos.Enums.PokemonId[pokemonId] !== 'undefined' &&
pokemonForm !== null && typeof POGOProtos.Enums.Form[pokemonForm] !== 'undefined'
) {
this.handleActivatePokemon(pokemonId, pokemonForm);
}
const activeLeague = activeLeagueValue ? parseInt(activeLeagueValue, 10) : null;
if (activeLeague !== null && typeof League[activeLeague] !== 'undefined') {
this.handleChangeLeague(activeLeague);
}
}
public render() {
const {
activePokemonId,
activePokemonForm,
pokemonList,
pokemonListFiltered,
filterTerm,
} = this.props.pokemonSelectListState;
const {
league,
individualValues,
leaguePokemon,
} = this.props.pokemonExplorerState;
return (
<div className={ styles.wrapper }>
<Header />
<div className={ styles.body }>
<PokemonSelectList
isLoading={ this.props.pokemonSelectListState.isLoading }
activePokemonId={ activePokemonId }
activePokemonForm={ activePokemonForm }
pokemonList={ filterTerm === '' ? pokemonList : pokemonListFiltered }
filterTerm={ this.props.pokemonSelectListState.filterTerm }
handleActivatePokemon={ this.handleActivatePokemon }
handleChangeFilter={ this.handleChangeFilter }
/>
{ leaguePokemon !== null &&
<PokemonExplorer
isLoading={ this.props.pokemonExplorerState.isLoading }
activeLeague={ league }
leaguePokemon={ leaguePokemon }
individualValues={ individualValues }
handleChangeIndividualValue={ this.handleChangeIndividualValue }
handleMaximizeLevel={ this.handleMaximizeLevel }
handleChangeLeague={ this.handleChangeLeagueNavigation }
/>
}
</div>
<Footer />
</div>
);
}
private readonly handleActivatePokemon = (pokemonId : POGOProtos.Enums.PokemonId, form : POGOProtos.Enums.Form) => {
const { dispatch } = this.props;
dispatch(ActionsPokemonSelectList.fetchPokemonLeagueStats(pokemonId, form))
.then((leaguePokemon) => {
dispatch(ActionsPokemonSelectList.setActivePokemonId(pokemonId, form));
dispatch(ActionsPokemonExplorer.setIvLevel(null));
dispatch(ActionsPokemonExplorer.setIvHp(null));
dispatch(ActionsPokemonExplorer.setIvAtk(null));
dispatch(ActionsPokemonExplorer.setIvDef(null));
dispatch(ActionsPokemonExplorer.setLeaguePokemon(leaguePokemon));
})
.catch((error) => {
// tslint:disable-next-line:no-console
console.error(error);
dispatch(ActionsPokemonExplorer.setLeaguePokemon(null));
})
.then(() => dispatch(ActionsPokemonExplorer.setIsLoading(false)));
}
private readonly handleChangeFilter = (filterTerm : string) => {
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 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 : PokemonAppProps) : PokemonAppProps => {
return {
pokemonExplorerState: state.pokemonExplorerState,
pokemonSelectListState: state.pokemonSelectListState,
};
};
const mapDispatchToProps = (dispatch : IPokemonAppDispatch['dispatch']) : IPokemonAppDispatch => {
return {
dispatch
};
};
const mergeProps = (state : PokemonAppProps, dispatchProps : IPokemonAppDispatch, ownProps : RouteComponentProps) : IConnectedPokemonAppProps => {
return {
...state,
...dispatchProps,
history: ownProps.history,
location: ownProps.location,
};
};
export const ConnectedPokemonApp = connect(mapStateToProps, mapDispatchToProps, mergeProps)(PokemonApp);