diff --git a/generatePokemonData.ts b/generatePokemonData.ts index 84aa9ef..8031bba 100644 --- a/generatePokemonData.ts +++ b/generatePokemonData.ts @@ -175,7 +175,8 @@ Pokemon.forEach((mon) => { fs.mkdir(outPath, {recursive: true}, () => { fs.writeFile(outPath + mon.id + '.json', JSON.stringify(pokemon), (err) => { - if(err) { + if (err) { + /* tslint:disable-next-line:no-console */ return console.log(mon.name, err); } }); @@ -202,7 +203,8 @@ familyOrder.forEach((familyId) => { fs.mkdir(outPath, {recursive: true}, () => { fs.writeFile(outPath + 'order.json', JSON.stringify(pokemonOrder), (err) => { - if(err) { + if (err) { + /* tslint:disable-next-line:no-console */ return console.log('order', err); } }); diff --git a/src/ts/api/PokemonService.ts b/src/ts/api/PokemonService.ts index 4c050fa..6e24c88 100644 --- a/src/ts/api/PokemonService.ts +++ b/src/ts/api/PokemonService.ts @@ -1,24 +1,13 @@ import { AjaxUtils } from 'api/AjaxUtils'; -import { IPokemon } from 'app/models/Pokemon'; +import { ILeaguePokemon, IPokemon, League } from 'app/models/Pokemon'; interface IPokemonJSON extends IPokemon {} +interface ILeaguePokemonJSON extends ILeaguePokemon {} interface IPokemonService {} export class PokemonService implements IPokemonService { - public getPokemonList() { - const queryParameters = { - type: 'no touch', - is_active: true, - }; - - return AjaxUtils.ajaxGet('/dist/db/order.json', queryParameters) - .then((response : Array) => { - return Promise.resolve(this.serializePokemonList(response)); - }); - } - - private serializePokemonList(jsonPokemonList : Array) : Array { + private static serializePokemonList(jsonPokemonList : Array) : Array { const pokemonList = jsonPokemonList.reduce((result : Array, pokemonJson) => { try { if (typeof pokemonJson.name !== 'string') { @@ -46,4 +35,62 @@ export class PokemonService implements IPokemonService { }, []); return pokemonList; } + + private static serializePokemonLeagueStats(jsonPokemonLeagueStats : ILeaguePokemonJSON) : ILeaguePokemon { + let pokemonLeagueStats : ILeaguePokemon; + try { + if (typeof jsonPokemonLeagueStats.name !== 'string') { + throw new Error('pokemon league stats missing name'); + } + if (typeof jsonPokemonLeagueStats.id !== 'string') { + throw new Error('pokemon league stats missing id'); + } + if (typeof jsonPokemonLeagueStats.family !== 'string') { + throw new Error('pokemon league stats missing family'); + } + if (typeof jsonPokemonLeagueStats.dex !== 'number') { + throw new Error('pokemon league stats missing dex'); + } + if (typeof jsonPokemonLeagueStats.stats !== 'object') { + throw new Error('pokemon league stats missing stats'); + } + if (typeof jsonPokemonLeagueStats.pvp !== 'object') { + throw new Error('pokemon league stats missing pvp'); + } + pokemonLeagueStats = { ...jsonPokemonLeagueStats }; + Object.keys(pokemonLeagueStats.pvp).forEach((key) => { + const league = key as League; + if (!Array.isArray(pokemonLeagueStats.pvp[league])) { + throw new Error('pokemon league not an array'); + } + pokemonLeagueStats.pvp[league] = [ ...jsonPokemonLeagueStats.pvp[league] ]; + }); + } catch (e) { + /* tslint:disable-next-line:no-console */ + console.error(jsonPokemonLeagueStats, e.message); + throw e; + } + + return pokemonLeagueStats; + } + + public getPokemonList() { + const queryParameters = { + }; + + return AjaxUtils.ajaxGet('/dist/db/order.json', queryParameters) + .then((response : Array) => { + return Promise.resolve(PokemonService.serializePokemonList(response)); + }); + } + + public getPokemonLeagueStats(pokemonId : string) { + const queryParameters = { + }; + + return AjaxUtils.ajaxGet(`/dist/db/${ pokemonId }.json`, queryParameters) + .then((response : ILeaguePokemonJSON) => { + return Promise.resolve(PokemonService.serializePokemonLeagueStats(response)); + }); + } } diff --git a/src/ts/app/PokemonApp.tsx b/src/ts/app/PokemonApp.tsx index 43a9787..ffe91f4 100644 --- a/src/ts/app/PokemonApp.tsx +++ b/src/ts/app/PokemonApp.tsx @@ -4,10 +4,10 @@ import { Dispatch } from 'redux'; import { appReducers } from './index'; -import * as ActionsPokemonSelectList from './PokemonSelectList/actions'; -import { ThunkDispatchPokemonSelectList } from './PokemonSelectList/types'; +import * as ActionsPokemonApp from './actions'; +import { ThunkDispatchPokemonSelectList } from './types'; -import { PokemonSelectList } from './PokemonSelectList/PokemonSelectList'; +import { PokemonSelectList } from './components/PokemonSelectList'; type PokemonAppProps = ReturnType; @@ -21,7 +21,7 @@ class PokemonApp extends React.Component { } public componentWillMount() { - this.props.dispatch(ActionsPokemonSelectList.fetchPokemonList()); + this.props.dispatch(ActionsPokemonApp.fetchPokemonList()); } public render() { @@ -36,7 +36,8 @@ class PokemonApp extends React.Component { } private readonly onActivatePokemon = (pokemonIndex : number) => { - this.props.dispatch(ActionsPokemonSelectList.setActivePokemonIndex(pokemonIndex)); + this.props.dispatch(ActionsPokemonApp.setActivePokemonIndex(pokemonIndex)); + this.props.dispatch(ActionsPokemonApp.fetchPokemonLeagueStats(this.props.pokemonSelectListState.pokemonList[pokemonIndex].id)); } } diff --git a/src/ts/app/actions.js b/src/ts/app/actions.js new file mode 100644 index 0000000..95a291d --- /dev/null +++ b/src/ts/app/actions.js @@ -0,0 +1,31 @@ +"use strict"; +exports.__esModule = true; +var typesafe_actions_1 = require("typesafe-actions"); +var types_1 = require("./types"); +exports.setPokemonList = function (pokemonList) { return typesafe_actions_1.action(types_1.PokemonSelectListActionTypes.SET_POKEMON_LIST, { pokemonList: pokemonList }); }; +exports.setActivePokemonIndex = function (activePokemonIndex) { return typesafe_actions_1.action(types_1.PokemonSelectListActionTypes.SET_ACTIVE_POKEMON_INDEX, { activePokemonIndex: activePokemonIndex }); }; +exports.setPokemonLeagueStats = function (pokemonId, pokemonLeagueStats) { return typesafe_actions_1.action(types_1.PokemonSelectListActionTypes.SET_POKEMON_LEAGUE_STATS, { pokemonId: pokemonId, pokemonLeagueStats: pokemonLeagueStats }); }; +exports.fetchPokemonList = function () { + return function (dispatch, getState, extraArguments) { + return new Promise(function (resolve, reject) { + extraArguments.services.pokemonService.getPokemonList() + .then(function (pokemonList) { + dispatch(exports.setPokemonList(pokemonList)); + resolve(); + }); + }); + }; +}; +exports.fetchPokemonLeagueStats = function (pokemonId) { + return function (dispatch, getState, extraArguments) { + return new Promise(function (resolve, reject) { + extraArguments.services.pokemonService.getPokemonLeagueStats(pokemonId) + .then(function (pokemonLeagueStats) { + dispatch(exports.setPokemonLeagueStats(pokemonId, pokemonLeagueStats)); + resolve(); + })["catch"](function () { + reject(); + }); + }); + }; +}; diff --git a/src/ts/app/PokemonSelectList/actions.ts b/src/ts/app/actions.ts similarity index 50% rename from src/ts/app/PokemonSelectList/actions.ts rename to src/ts/app/actions.ts index bb75200..4672ebe 100644 --- a/src/ts/app/PokemonSelectList/actions.ts +++ b/src/ts/app/actions.ts @@ -1,6 +1,6 @@ import { action } from 'typesafe-actions'; -import { IPokemon } from 'app/models/Pokemon'; +import { ILeaguePokemon, IPokemon } from 'app/models/Pokemon'; import { PokemonSelectListActionTypes, ThunkResult } from './types'; @@ -8,6 +8,8 @@ export const setPokemonList = (pokemonList : Array) => action(PokemonS export const setActivePokemonIndex = (activePokemonIndex : number) => action(PokemonSelectListActionTypes.SET_ACTIVE_POKEMON_INDEX, { activePokemonIndex }); +export const setPokemonLeagueStats = (pokemonId : string, pokemonLeagueStats : ILeaguePokemon) => action(PokemonSelectListActionTypes.SET_POKEMON_LEAGUE_STATS, { pokemonId, pokemonLeagueStats }); + export const fetchPokemonList = ( ) : ThunkResult> => { return (dispatch, getState, extraArguments) => { @@ -20,3 +22,20 @@ export const fetchPokemonList = ( }); }; }; + +export const fetchPokemonLeagueStats = ( + pokemonId : string +) : ThunkResult> => { + return (dispatch, getState, extraArguments) => { + return new Promise((resolve, reject) => { + extraArguments.services.pokemonService.getPokemonLeagueStats(pokemonId) + .then((pokemonLeagueStats) => { + dispatch(setPokemonLeagueStats(pokemonId, pokemonLeagueStats)); + resolve(); + }) + .catch(() => { + reject(); + }); + }); + }; +}; diff --git a/src/ts/app/components/PokemonExplorer.tsx b/src/ts/app/components/PokemonExplorer.tsx new file mode 100644 index 0000000..e69de29 diff --git a/src/ts/app/PokemonSelectList/PokemonSelectList.tsx b/src/ts/app/components/PokemonSelectList.tsx similarity index 100% rename from src/ts/app/PokemonSelectList/PokemonSelectList.tsx rename to src/ts/app/components/PokemonSelectList.tsx diff --git a/src/ts/app/index.tsx b/src/ts/app/index.tsx index 40a966d..9c8c072 100644 --- a/src/ts/app/index.tsx +++ b/src/ts/app/index.tsx @@ -4,11 +4,11 @@ import { Provider } from 'react-redux'; import * as Redux from 'redux'; import thunk from 'redux-thunk'; -import { IPokemonSelectListExtraArguments } from 'app/PokemonSelectList/types'; +import { IPokemonSelectListExtraArguments } from 'app/types'; import { PokemonService } from 'api/PokemonService'; -import { PokemonSelectListReducers } from './PokemonSelectList/reducers'; +import { PokemonSelectListReducers } from './reducers'; import { ConnectedPokemonApp } from './PokemonApp'; diff --git a/src/ts/app/reducers.js b/src/ts/app/reducers.js new file mode 100644 index 0000000..c217bd5 --- /dev/null +++ b/src/ts/app/reducers.js @@ -0,0 +1,39 @@ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +exports.__esModule = true; +var types_1 = require("./types"); +exports.initialState = { + activePokemonIndex: -1, + pokemonList: [], + pokemonListFiltered: [], + pokemonLeagueStats: {} +}; +var reduceSetPokemonList = function (state, action) { return (__assign({}, state, { pokemonList: action.payload.pokemonList })); }; +var reduceSetActivePokemonIndex = function (state, action) { return (__assign({}, state, { activePokemonIndex: action.payload.activePokemonIndex })); }; +var reduceSetPokemonLeagueStats = function (state, action) { + var _a; + return (__assign({}, state, { pokemonLeagueStats: __assign({}, state.pokemonLeagueStats, (_a = {}, _a[action.payload.pokemonId] = action.payload.pokemonStats, _a)) })); +}; +exports.PokemonSelectListReducers = function (state, action) { + if (state === void 0) { state = exports.initialState; } + switch (action.type) { + case types_1.PokemonSelectListActionTypes.SET_POKEMON_LIST: + return reduceSetPokemonList(state, action); + case types_1.PokemonSelectListActionTypes.SET_ACTIVE_POKEMON_INDEX: + return reduceSetActivePokemonIndex(state, action); + case types_1.PokemonSelectListActionTypes.SET_POKEMON_LEAGUE_STATS: + return reduceSetPokemonLeagueStats(state, action); + default: + return state; + } +}; diff --git a/src/ts/app/PokemonSelectList/reducers.ts b/src/ts/app/reducers.ts similarity index 71% rename from src/ts/app/PokemonSelectList/reducers.ts rename to src/ts/app/reducers.ts index 5fade6b..d7f0954 100644 --- a/src/ts/app/PokemonSelectList/reducers.ts +++ b/src/ts/app/reducers.ts @@ -7,6 +7,7 @@ export const initialState : IPokemonSelectListState = { activePokemonIndex: -1, pokemonList: [], pokemonListFiltered: [], + pokemonLeagueStats: {} }; const reduceSetPokemonList = ( @@ -25,6 +26,17 @@ const reduceSetActivePokemonIndex = ( activePokemonIndex: action.payload.activePokemonIndex, }); +const reduceSetPokemonLeagueStats = ( + state : IPokemonSelectListState, + action : ReturnType +) : IPokemonSelectListState => ({ + ...state, + pokemonLeagueStats: { + ...state.pokemonLeagueStats, + [action.payload.pokemonId] : action.payload.pokemonLeagueStats, + }, +}); + export const PokemonSelectListReducers : Reducer = ( state : IPokemonSelectListState = initialState, action, @@ -34,6 +46,8 @@ export const PokemonSelectListReducers : Reducer = ( return reduceSetPokemonList(state, action as ReturnType); case PokemonSelectListActionTypes.SET_ACTIVE_POKEMON_INDEX: return reduceSetActivePokemonIndex(state, action as ReturnType); + case PokemonSelectListActionTypes.SET_POKEMON_LEAGUE_STATS: + return reduceSetPokemonLeagueStats(state, action as ReturnType); default: return state; } diff --git a/src/ts/app/types.js b/src/ts/app/types.js new file mode 100644 index 0000000..8e0f4ea --- /dev/null +++ b/src/ts/app/types.js @@ -0,0 +1,7 @@ +"use strict"; +exports.__esModule = true; +exports.PokemonSelectListActionTypes = { + SET_POKEMON_LIST: 'POKEMON_APP/SET_POKEMON_LIST', + SET_ACTIVE_POKEMON_INDEX: 'POKEMON_APP/SET_ACTIVE_POKEMON_INDEX', + SET_POKEMON_LEAGUE_STATS: 'POKEMON_APP/SET_POKEMON_LEAGUE_STATS' +}; diff --git a/src/ts/app/PokemonSelectList/types.ts b/src/ts/app/types.ts similarity index 75% rename from src/ts/app/PokemonSelectList/types.ts rename to src/ts/app/types.ts index f9b97d7..b7ca270 100644 --- a/src/ts/app/PokemonSelectList/types.ts +++ b/src/ts/app/types.ts @@ -5,12 +5,13 @@ import { IProviderExtraArguments } from 'common/models/IProviderExtraArguments'; import { PokemonService } from 'api/PokemonService'; -import { IPokemon } from 'app/models/Pokemon'; +import { ILeaguePokemon, IPokemon } from 'app/models/Pokemon'; export interface IPokemonSelectListState { activePokemonIndex : number; pokemonList : Array; pokemonListFiltered : Array; + pokemonLeagueStats : { [id : string] : ILeaguePokemon }; } export interface IPokemonSelectListStore { @@ -29,6 +30,7 @@ export type ThunkResult = ThunkAction; export const PokemonSelectListActionTypes = { - SET_POKEMON_LIST: 'POKEMON_SELECT_LIST/SET_POKEMON_LIST', - SET_ACTIVE_POKEMON_INDEX: 'POKEMON_SELECT_LIST/SET_ACTIVE_POKEMON_INDEX', + SET_POKEMON_LIST: 'POKEMON_APP/SET_POKEMON_LIST', + SET_ACTIVE_POKEMON_INDEX: 'POKEMON_APP/SET_ACTIVE_POKEMON_INDEX', + SET_POKEMON_LEAGUE_STATS: 'POKEMON_APP/SET_POKEMON_LEAGUE_STATS', }; diff --git a/webpack.config.js b/webpack.config.js index b880960..33cfb29 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -17,11 +17,8 @@ const typescriptResolve = { extensions: ['.ts', '.tsx', '.js'], }; -module.exports = function (env, tsLoaderHappyPackMode) { +module.exports = function (env) { env = env || {}; - tsLoaderHappyPackMode = (typeof tsLoaderHappyPackMode === 'undefined') ? true : tsLoaderHappyPackMode; - - console.log('Webpack Environment:', env, 'tsLoaderHappyPackMode:', !!tsLoaderHappyPackMode); const plugins = [ new StyleLintPlugin({ @@ -99,13 +96,7 @@ module.exports = function (env, tsLoaderHappyPackMode) { exclude: /node_modules/, use: [ { loader: 'babel-loader' }, - { - loader: 'ts-loader', - options: { - silent: true, - happyPackMode: tsLoaderHappyPackMode, // setting as true also implies transpileOnly: true, - } - } + { loader: 'ts-loader' }, ] }, {