2019-03-11 21:42:32 -04:00

190 lines
6.6 KiB
TypeScript

import POGOProtos from 'pogo-protos';
import React from 'react';
import { ContentRect, default as Measure } from 'react-measure';
import { FixedSizeList } from 'react-window';
import classNames from 'classnames';
import { IIndividualValues } from 'app/components/PokemonExplorer/types';
import { Grade, IStats } from 'app/models/Pokemon';
import * as styles from 'app/styles/LeagueStatsList.scss';
export interface ILeagueStatsListProps {
activePokemonId : POGOProtos.Enums.PokemonId;
activePokemonForm : POGOProtos.Enums.Form;
activeIndividualValues : IIndividualValues;
leagueStatsList : Array<IStats>;
handleActivateLeagueStats : (stats : IStats) => void;
}
interface IState {
activePokemonId : POGOProtos.Enums.PokemonId;
activePokemonForm : POGOProtos.Enums.Form;
hasSetActiveStats : boolean;
listRef : React.RefObject<FixedSizeList>;
activeIndex : number;
dimensions : {
width : number;
height : number;
};
}
interface IRowFactory {
index : number;
style : React.CSSProperties;
}
export class LeagueStatsList extends React.Component<ILeagueStatsListProps, IState> {
public static getDerivedStateFromProps(nextProps : ILeagueStatsListProps, previousState : IState) {
const nextState : IState = {
...previousState,
activePokemonId: nextProps.activePokemonId,
activePokemonForm: nextProps.activePokemonForm,
activeIndex: -1,
};
const activeIvs = nextProps.activeIndividualValues;
if (nextProps.activePokemonId !== previousState.activePokemonId || nextProps.activePokemonForm !== previousState.activePokemonForm) {
if (previousState.listRef.current !== null) {
previousState.listRef.current.scrollToItem(0);
}
} else if (activeIvs.level !== null && activeIvs.ivHp !== null && activeIvs.ivAtk !== null && activeIvs.ivDef !== null) {
let activeIndex = previousState.activeIndex;
if (activeIndex === -1) {
// there is no current index, wich means the user is entering in the IVs by hand
// now we will look through the list to see if we can find a match
nextProps.leagueStatsList.some((stats, index) => {
if (activeIvs.ivHp === stats.ivHp &&
activeIvs.ivAtk === stats.ivAtk &&
activeIvs.ivDef === stats.ivDef &&
activeIvs.level === stats.level
) {
activeIndex = index;
return true;
}
return false;
});
}
if (activeIndex > -1 && !previousState.hasSetActiveStats) {
// the current IVs belong to the stats at the active index, so scroll to active stats
if (previousState.listRef.current !== null) {
previousState.listRef.current.scrollToItem(activeIndex, 'center');
}
}
if (activeIndex === -1) {
if (previousState.listRef.current !== null) {
previousState.listRef.current.scrollToItem(0);
}
}
nextState.activeIndex = activeIndex;
}
return nextState;
}
constructor(props : ILeagueStatsListProps) {
super(props);
this.state = {
activePokemonId: POGOProtos.Enums.PokemonId.MISSINGNO,
activePokemonForm: POGOProtos.Enums.Form.FORM_UNSET,
hasSetActiveStats: false,
listRef: React.createRef(),
activeIndex: -1,
dimensions: {
width: -1,
height: -1,
}
};
}
public render() {
const { width, height } = this.state.dimensions;
const onResize = (contentRect : ContentRect) => {
if (typeof contentRect.bounds !== 'undefined') {
this.setState({ dimensions: contentRect.bounds });
}
};
return (
<div className={ styles.selectList }>
<Measure
bounds={ true }
onResize={ onResize }
>
{
({ measureRef }) => (
<div ref={ measureRef }>
<FixedSizeList
ref={ this.state.listRef }
height={ height }
itemCount={ this.props.leagueStatsList.length }
itemSize={ 35 }
width={ width }
>
{ this.rowFactory.bind(this) }
</FixedSizeList>
</div>
)
}
</Measure>
</div>
);
}
private padString(value : string, length : number) {
let output = value;
for (let i = length - value.length; i > 0; i--) {
output += String.fromCharCode(160);
}
return output;
}
private rowFactory({ index, style } : IRowFactory) {
const activeIvs = this.props.activeIndividualValues;
const stats = this.props.leagueStatsList[index];
const css = classNames(
'list-item', // global style
styles.listItem,
{
active: activeIvs.level === stats.level &&
activeIvs.ivHp === stats.ivHp &&
activeIvs.ivAtk === stats.ivAtk &&
activeIvs.ivDef === stats.ivDef,
highlight: this.state.activeIndex === index, // this css class currently does nothing
}
);
const onClick = () => {
this.props.handleActivateLeagueStats(stats);
this.setState({
hasSetActiveStats: true,
activeIndex: index
});
};
return (
<a
key={ index }
style={ style }
className={ css }
onClick={ onClick }
>
<span>{ Grade[stats.speciesGrade] }</span>
<span>{ this.padString(stats.cp.toString(), 4) }</span>
<span>{ this.padString(stats.level.toString(), 4) }</span>
<span>{ this.padString(stats.ivHp.toString(), 2) }</span>
<span>{ this.padString(stats.ivAtk.toString(), 2) }</span>
<span>{ this.padString(stats.ivDef.toString(), 2) }</span>
</a>
);
}
}