components/Tickets/TicketList.js

/**
 * @module Tickets/TicketsList
 */
import React, { Component } from 'react';
import Constants, { SVG_ICONS } from '../../constants';
import SVGComponent from '../SVG/SVGComponent';
import { handleType, getTicketOdds } from '../../utils/common';
import { parseBigNums, parseNum } from '../../utils/parser';

const scrollElement = 'scroll-area';
/**
 * @typedef {object} props
 * @property {number} scrollTo
 * @property {boolean} betsPending
 * @property {Array} tickets
 * @property {Array} ticketDates
 * @property {Function} getTickets
 * @property {Function} selectTicket
 * @property {Function} changePage
 * @property {Function} setScrollPosition
 * @property {boolean} ticketsUpdated
 */
export default class TicketsList extends Component {
  /**
   * Add scroll listener
   *
   * @returns {void}
   */
  componentDidMount() {
    this.scrollArea = document.getElementById(scrollElement);
    this.bottomNav = document.getElementById('bottom-nav');
    if (this.scrollArea) {
      this.scrollArea.scrollTop = this.props.scrollTo;
      this.scrollArea.addEventListener('scroll', this.handleScroll);
    }
  }

  /**
   * update element\'s position when new tickets are fetched
   *
   * @param {object} prevProps
   * @returns {void}
   */
  componentDidUpdate(prevProps) {
    if ((this.props.betsPending !== prevProps.betsPending) && !this.props.ticketsUpdated) {
      this.scrollArea.scrollTop = this.props.scrollTo;
    }
  }

  /**
   * Remove scroll listener
   *
   * @returns {void}
   */
  componentWillUnmount() {
    this.scrollArea.removeEventListener('scroll', this.handleScroll);
    this.scrollArea.scrollTop = 0;
    this.props.setScrollPosition();
  }

  /**
   * Get more tickets on scroll
   *
   * @function
   * @returns {void}
   */
  handleScroll = () => {
    const element = document.getElementById(scrollElement);
    if ((
      Math.abs(element.scrollHeight - element.scrollTop - element.clientHeight) <= 1)
      && !this.props.betsPending) {
      this.props.setScrollPosition();
      this.props.getTickets();
    }
  }

  /**
   * Select tickets for more details
   *
   * @function
   * @param {object} ticket
   * @returns {void}
   */
  selectTicket = (ticket) => {
    this.props.selectTicket({ selectedTicket: ticket });
    this.props.changePage({ page: Constants.PAGES.TICKET_DETAILS });
  }

  /**
   * Render tiket view as one row
   *
   * @function
   * @returns {void}
   */
  renderTiceket = () => (
    this.props.ticketDates.map((date) => (
      this.props.tickets[date]
      && (
        <React.Fragment key={date}>
          <div className="bet-history__date">{date}</div>
          {this.props.tickets[date].map((ticket) => (
            <div
              onClick={this.selectTicket.bind(this, ticket)}
              className="bet-history__row"
              key={ticket.id}
            >
              <div className="bet-history__gutter">
                {ticket.bonus
                  ? <div className="tile c-yellow">B</div>
                  : null}
              </div>
              <div className="bet-history__wrap">
                <div className="bet-history__item">
                  <div className="bet-history__item-c1">
                    {handleType(ticket)}
                  </div>
                  <div className="bet-history__item-c2">
                    {parseBigNums(getTicketOdds(ticket))}
                  </div>
                  <div className="bet-history__item-c3">
                    {`${parseNum(ticket.stake)} ${this.props.currencySymbol}`}
                  </div>
                </div>
                <div className="bet-history__item">
                  <div className="bet-history__item-c4">
                    <span className="bet-history__item-label">
                      {ticket.bets[0].match}
                      {ticket.bets[1]
                        && `, ${ticket.bets[1].match} ${ticket.bets[2] ? '...' : ''}`}
                    </span>
                  </div>
                  <div className="bet-history__item-c5">
                    {ticket.win
                      ? (
                        <span className="bet-history__item-win">
                          {`Win: ${parseNum(ticket.win)} ${this.props.currencySymbol}`}
                        </span>
                      )
                      : null}
                  </div>
                </div>
              </div>
              <div className="bet-history__dots">
                {parseInt(ticket.status) === 0
                  ? <div className="loading-dots" />
                  : (
                    <div className={`tile ${Constants.TICKET_STATUS_COLOR[ticket.status]}`}>
                      {Constants.TICKET_CLASS_STATUS[ticket.status]}
                    </div>
                  )}
              </div>
              <div className="bet-history__arrow">
                <SVGComponent
                  className="icon-arrow"
                  src={`${SVG_ICONS.utility}#icon__arrow`}
                />
              </div>
            </div>
          ))}
        </React.Fragment>
      )
    ))
  )

  /**
   * Render ticket table view
   *
   * @function
   * @returns {void}
   */
  renderTable = () => (
    (this.props.noMoreBets && !this.props.ticketDates.length)
      ? (
        <div className="scroll-area__txt">
          <div className="scroll-area__icon mr-4" />
          <span>{'You don\'t have any bet placed yet!'}</span>
        </div>
      )
      : (
        <>
          <div className="bet-history">
            {this.props.ticketDates
              && (
                <div className="bet-history__row heading">
                  <div className="bet-history__gutter" />
                  <div className="bet-history__bet">Bet</div>
                  <div className="bet-history__odds">Odds</div>
                  <div className="bet-history__stake">Stake</div>
                  <div className="bet-history__status">Status</div>
                  <div className="bet-history__arrow" />
                </div>,
                this.renderTiceket()
              )}
          </div>
          {this.props.betsPending
            && (
              <div className="loading-wrap sm">
                <div className="loading-item" />
              </div>
            )}
        </>
      )
  );

  /**
   * Render
   *
   * @returns {view}
   */
  render() {
    return (
      <>
        <div className="bet__heading">Bet History</div>
        <div className="scroll-area" id={scrollElement}>
          <div>
            {this.renderTable()}
          </div>
        </div>
      </>
    );
  }
}