import React from 'react';
import { connect } from 'react-redux';
import Constants from '../../constants';
import { parseNum, roundNum } from '../../utils/parser';
import {
placebetRequest, toggleSelectedOdds, openModal, setStakes, toggleBetslip,
closePlaceBetErrorMessage, closeSlipConfirmation,
setSelectedBetType, setBackUpLoginProps, closeBetSlip, clearAllSelections,
} from '../../reducers';
import {
getMarkets,
getMatches,
getGameType,
getWinCap,
getRoundId,
} from '../../store/bets';
import {
getBetslipSettings, getConfigs, getFreeBets,
getUser,
getSelectedBetType,
getPlacebetBackupLogin,
getPrevCombinationTypes,
getPrevCombinations,
} from '../../store/common';
import {
getNumberOfSelections, getSelectedOdds, getSingleStakes, getMultipleStake, getOtherStake,
getCombiStakes, getPlaceBetErrorMgs, getIsLoadingPlaceBet, getBetSlipConfimation,
getPlacebetDisabled, getBonusPercentages, getBonusOddsThreshold, getTurboRoundDuration,
getPlacebetAfterLogin,
} from '../../store/placebet';
import BetslipView from '../../components/Betslip/BetslipView';
import BetslipHandler from './BetslipHandler';
const mapToProps = (state) => ({
markets: getMarkets(state),
numberOfSelections: getNumberOfSelections(state),
betslipSettings: getBetslipSettings(state),
singleStakes: getSingleStakes(state),
multipleStake: getMultipleStake(state),
otherStake: getOtherStake(state),
combiStakes: getCombiStakes(state),
matches: getMatches(state),
placeBetErrorMgs: getPlaceBetErrorMgs(state),
isLoadingPlaceBet: getIsLoadingPlaceBet(state),
betSlipConfimation: getBetSlipConfimation(state),
placebetDisabled: getPlacebetDisabled(state),
bonusPercentages: getBonusPercentages(state),
bonusOddsThreshold: getBonusOddsThreshold(state),
config: getConfigs(state),
odds: getSelectedOdds(state),
freeBets: getFreeBets(state),
gameType: getGameType(state),
turboRoundDuration: getTurboRoundDuration(state),
selectedBetType: getSelectedBetType(state),
user: getUser(state),
placebetBackupLogin: getPlacebetBackupLogin(state),
prevCombinationTypes: getPrevCombinationTypes(state),
prevCombinations: getPrevCombinations(state),
selectedOdds: getSelectedOdds(state),
winCap: getWinCap(state),
placebetAfterLogin: getPlacebetAfterLogin(state),
roundId: getRoundId(state),
});
const actionsToProps = (dispatch) => ({
placebetRequest: (payload) => dispatch(placebetRequest(payload)),
toggleSelectedOdds: (payload) => dispatch(toggleSelectedOdds(payload)),
openModal: (payload) => dispatch(openModal(payload)),
setStakes: (payload) => dispatch(setStakes(payload)),
toggleBetslip: (payload) => dispatch(toggleBetslip(payload)),
closePlaceBetErrorMessage: (payload) => dispatch(closePlaceBetErrorMessage(payload)),
closeSlipConfirmation: (payload) => dispatch(closeSlipConfirmation(payload)),
setSelectedBetType: (payload) => dispatch(setSelectedBetType(payload)),
setBackUpLoginProps: (payload) => dispatch(setBackUpLoginProps(payload)),
closeBetSlip: (payload) => dispatch(closeBetSlip(payload)),
clearAllSelections: (payload) => dispatch(clearAllSelections(payload)),
});
/**
* @class
* @augments BetslipHandler
* @property {object} props
* @property {Array} props.markets All markets data
* @property {number} props.numberOfSelections Number of selected odds
* @property {object} props.betslipSettings Config info from API
* @property {Array} props.singleStakes Amounts in inputs on single betslip type
* @property {string} props.multipleStake Amount in input on multiple betslip type
* @property {string} props.otherStake Amount in input on split betslip type or free bets bet type
* @property {Array} props.combiStakes Amounts in inputs on combination betslip type
* @property {Array} props.matches Matches informations
* @property {string} props.placeBetErrorMgs Error message from API
* @property {boolean} props.isLoadingPlaceBet Represent is placebet API fetch
* @property {boolean} props.betSlipConfimation Indicate when confirmation modal sholud show
* @property {boolean} props.placebetDisabled Indicate when placebet button should be disabled
* @property {number} props.bonusPercentages Config form API
* @property {string} props.bonusOddsThreshold Config form API
* @property {object} props.config Contain currency sign
* @property {object} props.odds Contain all odds
* @property {Array} props.freeBets Free bets information
* @property {Array} props.gameType FGame type Classic/Turbo
*
* @property {Function} props.placebet Placebet API call
* @property {Function} props.toggleSelectedOdds Toggle selected odds
* @property {Function} props.openModal Open modal
* @property {Function} props.setStakes Change stakes in betslip
* @property {Function} props.toggleBetslip Toggle betslip modal
* @property {Function} props.closePlaceBetErrorMessage Remove placebet error message
* @property {Function} props.closeSlipConfirmation Remove placebet confirmation modal
* @property {Function} props.kickOff Get turbo live data
*/
class Betslip extends BetslipHandler {
constructor(props) {
super(props);
/**
* @member {object}
* @description Initial setup for calculations
* @property {number} [totalStake=0]
* @property {number} [potWinMax=0]
* @property {number} [potWinMin=0]
* @property {number} [bonusAmt=0]
*/
this.setup = {
totalStake: 0,
potWinMax: 0,
potWinMin: 0,
bonusAmt: 0,
};
/**
* @member {object}
* @property {string} type Indicate one of bet type
* @property {number} numOfSplitBets Number of split bets
* @property {Array} maxOdd Array of all maximum odds per combination.
* For split bet only one odd
* @property {Array} minOdd Array of all minimum odds per combination.
* For split bet only one odd
* @property {Array} maxPotWin Array of all maximum potential win per combination.
* For split bet only one odd
* @property {Array} minPotWin Array of all minimum potential win combination.
* For split bet only one odd
* @property {boolean} minStakeErr Is all inserted stakes bigger than minimum stake
* @property {boolean} maxStakeErr Is all inserted stakes less than minimum stake
* @property {number} stakeInFocus Index of input field in focus
* @property {boolean} rerender Forse rerender
* @property {boolean} showButtons Indicate are stake buttons showen
* @property {boolean} openNewPlacedBetsModal Indicate is confirmation modal showen
* @property {object} systemManager Precalculated data from library
* @property {object} settings Settings for calculations
*/
this.state = {
type: Constants.BET_TYPE.NO_BET,
selectedType: Constants.BET_TYPE.NO_BET,
numOfSplitBets: 0,
maxOdd: [],
minOdd: [],
maxPotWin: [],
minPotWin: [],
minStakeErr: false,
maxStakeErr: false,
maxPotWinPayoutErr: false,
stakeInFocus: 0,
rerender: false,
showButtons: false,
openNewPlacedBetsModal: false,
systemManager: {},
settings: this.setup,
stakeHasChanges: false,
ticker: 0,
};
/**
* @member {Array<string>}
* @description Array of combination inputs label
*/
this.combinationTypes = [];
/**
* @member {Array<string>}
* @description Array of number of bets per combination
*/
this.combinations = [];
this.tickerInterval = setInterval(this.checkCalc, 1000);
}
/**
* Calculate bet type on component mount
*
* @returns {void}
*/
componentDidMount() {
this.changeBetType(this.props.selectedBetType);
}
/**
* Setup settings when selected type change, calculate bet type on odd remove
*
* @param {object} prevProps
* @returns {void}
*/
componentDidUpdate(prevProps) {
if (this.props.selectedBetType !== prevProps.selectedBetType) {
// eslint-disable-next-line react/no-did-update-set-state
this.setState({
settings: this.setupPlacebet(
this.props.singleStakes,
this.props.combiStakes,
this.props.multipleStake,
this.props.otherStake,
),
stakeInFocus: 0,
showButtons: false,
});
this.changeBetType(this.props.selectedBetType);
if (this.state.minStakeErr === true
|| this.state.maxStakeErr === true
|| this.state.maxPotWinPayoutErr === true
|| this.props.placeBetErrorMgs) {
this.closeError();
}
}
if (this.props.numberOfSelections !== prevProps.numberOfSelections) {
this.changeBetType(
this.props.selectedBetType,
this.props.numberOfSelections < prevProps.numberOfSelections,
);
}
}
/**
* Open modal view placed bets on component unmount if bet is placed
*
* @returns {void}
*/
componentWillUnmount() {
this.isUnmounted = true;
if (this.props.betSlipConfimation || this.state.openNewPlacedBetsModal) {
this.props.openModal({
modal: Constants.MODALS.VIEW_PLACED_BETS,
});
}
this.closeError();
this.clearAllTimeouts();
clearInterval(this.tickerInterval);
}
thereIsStake = () => this.props.multipleStake > 0 || this.props.singleStakes.length > 0
|| this.props.combiStakes.length > 0;
thereAreSelections = () => this.props.selectedOdds.length > 0;
getBetType = () => {
if (this.props.selectedOdds.length === 1) {
return Constants.BET_TYPE.SINGLE;
}
const matches = {};
this.props.selectedOdds.map((selection) => {
const matchId = selection.matchId;
matches[matchId] = true;
});
if (Object.keys(matches).length < this.props.selectedOdds.length) {
return Constants.BET_TYPE.SPLIT_COLUMN;
}
return this.props.combiStakes.length > 0
? Constants.BET_TYPE.COMBINATION : Constants.BET_TYPE.MULTIPLE;
}
checkCalc = () => {
if (this.state.selectedType === Constants.BET_TYPE.NO_BET
&& this.thereIsStake() && this.thereAreSelections()) {
this.updateCalc();
this.setState({ selectedType: this.props.selectedBetType });
}
}
/**
* Render
*
* @see module:Betslip/BetslipView
* @returns {view}
*/
render() {
const selectedBetType = this.props.selectedBetType;
const combinationTypes = this.props.prevCombinationTypes || this.combinationTypes;
const combinations = this.props.prevCombinations || this.combinations;
const potWinMin = roundNum(this.state.settings.potWinMin);
const potWinMax = roundNum(this.state.settings.potWinMax);
const potWin = potWinMax > 0
? potWinMin === potWinMax
? parseNum(potWinMax * 100) : `${parseNum(potWinMin * 100)} to ${parseNum(potWinMax * 100)}`
: 0;
const placeBetErrorMgs = this.state.minStakeErr
? (this.props.selectedBetType === Constants.BET_TYPE.COMBINATION
|| this.props.selectedBetType === Constants.BET_TYPE.SPLIT_COLUMN)
? `Minimum stake per combination is: ${parseNum(this.props.betslipSettings.minStakePerSelection * 100)} ${this.props.config.currencySymbol}`
: `Minimum stake is: ${parseNum(this.props.betslipSettings.minStake * 100)} ${this.props.config.currencySymbol}`
: this.state.maxStakeErr
? `Total Stake Cannot Be Higher Than: ${parseNum(this.props.betslipSettings.maxStake * 100)} ${this.props.config.currencySymbol}`
: this.props.placeBetErrorMgs;
return (
<BetslipView
{...this.props}
{...this.state}
combinationTypes={combinationTypes}
combinations={combinations}
potWin={potWin}
totalStake={this.state.settings.totalStake}
placeBetErrorMgs={placeBetErrorMgs}
bonusAmt={this.state.settings.bonusAmt}
percentage={this.state.settings.percentage}
getFreeBetsAmount={this.getFreeBetsAmount}
placebet={this.placebet}
changeStakeInput={this.changeStakeInput}
addButton={this.addButton}
freeBets={this.props.freeBets}
openOtherTypes={this.openOtherTypes}
openFreeBetType={this.openFreeBetType}
selectSingleBet={this.selectSingleBet}
selectMultipleBet={this.selectMultipleBet}
setInputInFocus={this.setInputInFocus}
setInputOutOfFocus={this.setInputOutOfFocus}
clearAllSelections={this.clearAllSelections}
closeConfirmation={this.closeSlipConfirmation}
clearSelection={this.clearSelection}
closeError={this.closeError}
toggleBetslipModal={this.toggleBetslipModal}
clearStake={this.clearStake}
selectedBetType={selectedBetType}
haveLiveMatches={this.props.haveLiveMatches}
isWinCap={this.state.maxPotWinPayoutErr}
winCap={this.props.winCap}
toggleBetslip={this.toggleBetslipModal}
/>
);
}
}
export default connect(
mapToProps,
actionsToProps,
)(Betslip);