import React from 'react'; import Media from 'react-media'; import { connect } from 'react-redux'; import { RouteComponentProps, withRouter } from 'react-router-dom'; import classNames from 'classnames'; import { appReducers } from 'app/index'; import * as ActionsPokemonApp from 'app/actions'; import * as ActionsPokemonExplorer from 'app/components/PokemonExplorer/actions'; import * as ActionsPokemonSelectList from 'app/components/PokemonSelectList/actions'; import { IPokemonAppDispatch, IRouterProps, Navigation } from 'app/types'; import { convertFormParamToPokemonForm, convertIdParamToPokemonId, convertLeagueParamToLeague } from 'app/utils/navigation'; import { Footer } from 'app/components/Footer'; import { Header } from 'app/components/Header'; import { ConnectedPokemonExplorer } from 'app/components/PokemonExplorer/PokemonExplorer'; import { PokemonSelectList } from 'app/components/PokemonSelectList/PokemonSelectList'; import { MAX_MOBILE_WIDTH, MIN_TABLET_WIDTH } from 'common/models/constants'; import * as PVPogoProtos from 'common/models/PVPogoProtos'; import * as styles from 'app/styles/PokemonApp.scss'; type PokemonAppProps = ReturnType; interface IConnectedPokemonAppProps extends PokemonAppProps, IPokemonAppDispatch, IRouterProps {} class PokemonApp extends React.Component { public async componentWillMount() { const { dispatch, match, } = this.props; const { id, form, league, } = match.params; await Promise.all([ dispatch(ActionsPokemonApp.fetchConfig()), // TODO: move this action to PokemonApp actions dispatch(ActionsPokemonSelectList.fetchPokemonList()) ]); dispatch(ActionsPokemonSelectList.setIsLoading(false)); const pokemonId = convertIdParamToPokemonId(id); const pokemonForm = convertFormParamToPokemonForm(form); if (pokemonId !== null && pokemonForm !== null) { this.handleActivatePokemon(pokemonId, pokemonForm); } const activeLeague = convertLeagueParamToLeague(league); if (activeLeague !== null) { dispatch(ActionsPokemonExplorer.setActiveLeague(activeLeague)); } } public render() { const { navigation, isInterruption, attackTypeEffectiveness, combatMoves, } = this.props.pokemonAppState; const { pokemonList, pokemonListFiltered, filterTerm, } = this.props.pokemonSelectListState; const { leaguePokemon, } = this.props.pokemonExplorerState; const matchParams = this.props.match.params; const activePokemonId = convertIdParamToPokemonId(matchParams.id); const activePokemonForm = convertFormParamToPokemonForm(matchParams.form); const wrapperCss = classNames( styles.wrapper, { [styles.overlaid]: isInterruption, } ); const iconCss = classNames( 'icon', 'pixel', 'sprite', ); const pokedexCss = classNames( iconCss, 'pokedex', { active: navigation === 'pokedex', } ); const pokedexButtonCss = classNames( styles.navigationButton, // { // [styles.activeNavigationButton]: activeNavigation === 'pokedex', // } ); const hamburgerButtonCss = classNames( styles.hamburgerIcon, styles.navigationButton, // { // [styles.activeNavigationButton]: activeNavigation === 'menu', // } ); // react optimization for rendering on pokemon switching // https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with-a-key const uniquePokemonId = leaguePokemon !== null ? `${leaguePokemon.id}~${leaguePokemon.form}` : undefined; return (
); } private readonly handleInterruption = (isInterruption : boolean, navigation : Navigation) => { const { dispatch } = this.props; dispatch(ActionsPokemonApp.setNavigation(isInterruption ? navigation : null)); dispatch(ActionsPokemonApp.setIsInterruption(isInterruption)); if (isInterruption) { dispatch(ActionsPokemonExplorer.setCombatMoveSelectorsOpen({ quickMove: false, chargeMove1: false, chargeMove2: false, })); } } private readonly handleToggleInterruption = (isInterruption : boolean) => { this.props.dispatch(ActionsPokemonApp.setIsInterruption(isInterruption)); if (!isInterruption) { this.props.dispatch(ActionsPokemonApp.setNavigation(null)); } } private readonly handlePokedexClick = () => { this.handleInterruption(true, 'pokedex'); } private readonly handleMenuClick = () => { this.handleInterruption(true, 'menu'); } private readonly handleActivatePokemon = async (pokemonId : PVPogoProtos.PokemonId, form : PVPogoProtos.PokemonForm) => { const { dispatch } = this.props; dispatch(ActionsPokemonExplorer.setIsLoading(true)); try { const leaguePokemon = await dispatch(ActionsPokemonApp.fetchPokemonLeagueStats(pokemonId, form)); dispatch(ActionsPokemonExplorer.reset(leaguePokemon)); } catch (error) { // tslint:disable-next-line:no-console console.error(error); dispatch(ActionsPokemonExplorer.setLeaguePokemon(null)); } dispatch(ActionsPokemonExplorer.setIsLoading(false)); this.handleInterruption(false, 'pokedex'); } private readonly handleChangeFilter = (filterTerm : string) => { this.handleInterruption(true, 'pokedex'); return this.props.dispatch(ActionsPokemonSelectList.filterPokemonList(filterTerm)); } } const mapStateToProps = (state : PokemonAppProps) : PokemonAppProps => { return { pokemonAppState: state.pokemonAppState, pokemonExplorerState: state.pokemonExplorerState, pokemonSelectListState: state.pokemonSelectListState, }; }; export const ConnectedPokemonApp = withRouter(connect(mapStateToProps)(PokemonApp));