containers/Coupons/index.js

import React, { Component } from 'react';

import { connect } from 'react-redux';
import {
  aGetPlacedCoupons,
  aGetPlacedCouponsShop,
  aGetSettledCoupons,
  aGetSettledCouponsShop,
  aSetCouponToWontpayRequest,
  aVoidCouponRequest,
} from '../../reducers/actions';
import {
  getCurrency,
  getSelectedMenuItem,
  getFilterData,
  isFetched,
  isLastRecord,
  hasRecord,
  getSelectedTimezone,
  getActiveModal,
  checkPermisson,
  getBetStatus,
} from '../../selectors/common';
import {
  getGameStatuses,
  getPlacedCoupons,
  getSelectedCoupon,
  getSettledCoupons,
  getPlacedCouponsShop,
  getSettledCouponsShop,
  getShopGameStatuses,
  getCouponStatus,
  getOperatorsFilter,
  getIsLoadingCoupons,
  getCouponSource,
} from '../../selectors/coupons';
import PlacedCoupons from '../../components/MenuItems/Coupons/PlacedCoupons';
import Filter from '../../components/Filter';
import CouponDetails from '../../components/MenuItems/Coupons/CouponDetails';
import { MENU_ITEMS, COUPONS_TYPE, COUPON_PAGES, PERMISSIONS } from '../../constants';
import SettledCoupons from '../../components/MenuItems/Coupons/SettledCoupons';

import { getCountryNewDate, getDateForIntervalFilter, setFilterFromUrl } from '../../utils/common';
import ScrollTable from '../../components/ScrollTable';
import { aClearFilterData } from '../../reducers/cashier';
import { aSetFilters, aSetOpenModal } from '../../reducers/common';
import { aSetSelectedCoupon, aSortSettledCoupons } from '../../reducers/coupons';
import { withRouterHooks } from '../../utils/router';
import { SETTLED_COUPONS_SORT_FIELDS, SORT_DIRECTION } from '../../utils/sort';
import { COUPON_FILTER_KEY_MAPPING, OPERATOR_LABEL_MAPPING } from './constants';
import { aResetExport } from '../../reducers/exporter';
import { getGamesSettings } from '../../selectors/settings';
import { aGetGamesSettings } from '../../reducers/settings';
import Loader from '../../components/Loader';

const mapToProps = (state) => ({
  placedCoupons: getPlacedCoupons(state),
  placedCouponsShop: getPlacedCouponsShop(state),
  settledCoupons: getSettledCoupons(state),
  settledCouponsShop: getSettledCouponsShop(state),
  currency: getCurrency(state),
  selectedMenuItem: getSelectedMenuItem(state),
  selectedCoupon: getSelectedCoupon(state),
  filters: getFilterData(state),
  isFetched: isFetched(state),
  isLastRecord: isLastRecord(state),
  hasRecord: hasRecord(state),
  gameStatuses: getGameStatuses(state),
  shopGameStatuses: getShopGameStatuses(state),
  selectedTimezone: getSelectedTimezone(state),
  activeModal: getActiveModal(state),
  checkPermisson: (payload) => checkPermisson(state, payload),
  betStatus: getBetStatus(state),
  couponStatus: getCouponStatus(state),
  gamesSettings: getGamesSettings(state),
  operators: getOperatorsFilter(state),
  isLoadingCoupons: getIsLoadingCoupons(state),
  couponSource: getCouponSource(state),
});

const actionsToProps = (dispatch) => ({
  setFilterData: (payload) => dispatch(aSetFilters(payload)),
  getPlacedCoupons: (payload) => dispatch(aGetPlacedCoupons(payload)),
  getPlacedCouponsShop: (payload) => dispatch(aGetPlacedCouponsShop(payload)),
  getSettledCoupons: (payload) => dispatch(aGetSettledCoupons(payload)),
  getSettledCouponsShop: (payload) => dispatch(aGetSettledCouponsShop(payload)),
  selectCoupon: (payload) => dispatch(aSetSelectedCoupon(payload)),
  clearFilterData: (payload) => dispatch(aClearFilterData(payload)),
  setOpenModal: (payload) => dispatch(aSetOpenModal(payload)),
  voidCoupon: (payload) => dispatch(aVoidCouponRequest(payload)),
  setCouponToWontpay: (payload) => dispatch(aSetCouponToWontpayRequest(payload)),
  sortSettledCoupons: (payload) => dispatch(aSortSettledCoupons(payload)),
  getGamesSettings: (payload) => dispatch(aGetGamesSettings(payload)),
  resetExport: () => dispatch(aResetExport()),
});

/**
 * @class
 * @property {object} props
 * @property {Array} props.placedCoupons All placed coupons data
 * @property {Array} props.settledCoupons All settled coupons data
 * @property {string} props.currency Currency sign
 * @property {object} props.selectedMenuItem Placed or settled coupons
 * @property {object} props.selectedCoupon Selected coupon data
 * @property {object} props.filters Filters data
 * @property {boolean} props.isFetched
 * @property {Function} props.setFilterData Filter coupons
 * @property {Function} props.getPlacedCoupons Get coupons API
 * @property {Function} props.selectCoupon Change selected coupon
 * @property {Function} props.clearFilterData Clear filter data
 */
class Coupons extends Component {
  constructor(props) {
    super(props);
    /**
     * @member {Array}
     * @description Filtering fields settings
     */

    this.state = {
      sort: {
        direction: SORT_DIRECTION.DESC,
        field: SETTLED_COUPONS_SORT_FIELDS.PLACED_DATE,
      },
    };

    this.filterFields = [
      {
        className: 'user__username',
        text: 'Coupon ID',
        field: 'filter.couponId',
      },
      {
        text: 'Client ID',
        field: 'filter.clientId',
      },
      {
        text: 'Round ID',
        field: 'filter.roundId',
      },
      {
        text: 'Game',
        // eslint-disable-next-line sonarjs/no-duplicate-string
        field: 'filter.game',
        dropdown: props.gameStatuses,
      },
      {
        text: 'Placed date',
        // eslint-disable-next-line sonarjs/no-duplicate-string
        fields: ['filter.startPlacedDate', 'filter.endPlacedDate'],
        dateInterval: true,
      },
      {
        text: 'Bonus',
        field: 'filter.isBonus',
        bonus: true,
      },
    ];

    /**
     * @member {boolean}
     * @description Is settlet coupons selected
     */
    this.isSettled = false;
    /**
     * @member {object}
     */
    this.defaultFilter = {
      'filter.startPlacedDate': '',
      'filter.endPlacedDate': '',
      'filter.couponId': '',
      'filter.clientId': '',
      'filter.roundId': '',
    };

    /**
     * @member {object}
     */
    this.filters = props.filters
      ? {
          ...props.filters,
          'filter.startPlacedDate': setFilterFromUrl(this.props.location.search, 'filter.startPlacedDate'),
          'filter.endPlacedDate': setFilterFromUrl(this.props.location.search, 'filter.endPlacedDate'),
        }
      : this.defaultFilter;
    /**
     * @member {boolean}
     */
    this.initialApiCall = !!props.filters;
  }

  componentDidMount() {
    const path = this.props.location.pathname;
    const isSettledCouponsMobilePage = path === MENU_ITEMS.COUPONS.COUPONS_SETTLED_VIEW.path;
    const hasExportCouponPermission = this.props.checkPermisson(PERMISSIONS.EXPORT_COUPONS);

    if (isSettledCouponsMobilePage && hasExportCouponPermission) {
      this.props.getGamesSettings();
    }
  }

  componentDidUpdate(prevProps) {
    if (prevProps.location.pathname !== this.props.location.pathname) {
      this.filters = this.defaultFilter;
      const path = this.props.location.pathname;
      const isSettledCouponsMobilePage = path === MENU_ITEMS.COUPONS.COUPONS_SETTLED_VIEW.path;
      const hasExportCouponPermission = this.props.checkPermisson(PERMISSIONS.EXPORT_COUPONS);

      if (!isSettledCouponsMobilePage) {
        this.filterFields = this.filterFields.filter(
          (obj) =>
            obj.field !== COUPON_FILTER_KEY_MAPPING.STATUS &&
            obj.field !== COUPON_FILTER_KEY_MAPPING.STAKE &&
            obj.field !== COUPON_FILTER_KEY_MAPPING.WON_AMOUNT
        );
      } else if (
        hasExportCouponPermission &&
        (prevProps.gamesSettings === null || prevProps.gamesSettings !== this.props.gamesSettings)
      ) {
        this.props.getGamesSettings();
      }

      this.setState({
        sort: {
          direction: SORT_DIRECTION.DESC,
          field: SETTLED_COUPONS_SORT_FIELDS.PLACED_DATE,
        },
      });
    }
  }

  getValueEndPlacedDate = (endPlacedDateFilter) => {
    if (!endPlacedDateFilter) {
      const dateWithTimezone = getCountryNewDate(this.props.selectedTimezone, new Date());
      return getDateForIntervalFilter(dateWithTimezone).replace(' ', 'T');
    }

    const endPlacedDate = new Date(endPlacedDateFilter);
    const now = getCountryNewDate(this.props.selectedTimezone, new Date());

    if (endPlacedDate.getTime() > now.getTime()) {
      return getDateForIntervalFilter(now).replace(' ', 'T');
    }

    return endPlacedDateFilter;
  };

  /**
   * Get coupons API call
   *
   * @function
   * @param {object} payload Filter data
   * @returns {void}
   */
  getCoupons = (payload) => {
    const defaultSort = { direction: SORT_DIRECTION.DESC, field: SETTLED_COUPONS_SORT_FIELDS.PLACED_DATE };
    const { sort = defaultSort, ...filters } = payload || {};

    if (payload && JSON.stringify(filters) !== JSON.stringify(this.defaultFilter)) {
      this.setState({ sort });

      filters['filter.endPlacedDate'] = this.getValueEndPlacedDate(filters['filter.endPlacedDate']);

      if (this.isSettled && this.couponsPage === COUPON_PAGES.SETTLED_COUPON_MOBILE) {
        this.props.getSettledCoupons({
          ...filters,
          sort,
          type: COUPONS_TYPE.SETTLED,
        });
      } else if (this.isSettled && this.couponsPage === COUPON_PAGES.SETTLED_COUPON_SHOP) {
        this.props.getSettledCouponsShop({
          ...filters,
          sort,
          type: COUPONS_TYPE.SETTLED,
        });
      } else if (!this.isSettled && this.couponsPage === COUPON_PAGES.PLACED_COUPON_MOBILE) {
        this.props.getPlacedCoupons({
          ...filters,
          type: COUPONS_TYPE.PLACED,
        });
      } else if (!this.isSettled && this.couponsPage === COUPON_PAGES.PLACED_COUPON_SHOP) {
        this.props.getPlacedCouponsShop({
          ...filters,
          type: COUPONS_TYPE.PLACED,
        });
      }
    }
  };

  /**
   * Sort table by columns
   * @param {string} field sort field
   * @param {string} direction direction of sort ASC or DESC
   * @function
   * @returns {void}
   */
  sortColumn = (field, direction) => {
    this.setState({ sort: { field, direction } });
    this.props.sortSettledCoupons({ field, direction, isShop: this.isShop });
  };

  getAdditionalFilters = (props) => [
    {
      text: 'Status',
      field: COUPON_FILTER_KEY_MAPPING.STATUS,
      dropdown: [
        { id: '', label: 'Any' },
        ...props.couponStatus.map((s) => {
          const label = s.toLowerCase();
          const labelWithCapitalizedWord = `${label.charAt(0).toUpperCase()}${label.slice(1)}`;
          return { id: s, label: labelWithCapitalizedWord };
        }),
      ],
    },
    {
      text: 'Stake Amount',
      field: COUPON_FILTER_KEY_MAPPING.STAKE,
      operatorText: 'Stake Condition',
      operatorField: COUPON_FILTER_KEY_MAPPING.STAKE_OPERATOR,
      inputWithOperator: true,
      minimumValue: 1,
      maximumValue: this.props.gamesSettings?.couponMaxStake / 100,
      operators: [
        { id: 'any-stake-operator', label: 'Any', value: '' },
        ...props.operators.map((operator, index) => ({
          id: index,
          label: OPERATOR_LABEL_MAPPING[operator] || operator,
          value: operator,
        })),
      ],
      formatValue: (value) => (typeof value === 'number' ? value * 100 : 0),
      getValue: (value) => (typeof value === 'number' ? value / 100 : 0),
      isValid: (filterValue) => {
        if (filterValue[COUPON_FILTER_KEY_MAPPING.STAKE]) {
          return (
            filterValue[COUPON_FILTER_KEY_MAPPING.STAKE_OPERATOR] !== '' &&
            filterValue[COUPON_FILTER_KEY_MAPPING.STAKE] >= 1 &&
            filterValue[COUPON_FILTER_KEY_MAPPING.STAKE] <= this.props.gamesSettings?.couponMaxStake
          );
        }
        return true;
      },
    },
    {
      text: 'Won Amount',
      field: COUPON_FILTER_KEY_MAPPING.WON_AMOUNT,
      operatorText: 'Won Amount Condition',
      operatorField: COUPON_FILTER_KEY_MAPPING.WON_AMOUNT_OPERATOR,
      inputWithOperator: true,
      minimumValue: 1,
      maximumValue: this.props.gamesSettings?.winCap / 100,
      operators: [
        { id: 'any-won-amount-operator', label: 'Any', value: '' },
        ...props.operators.map((operator, index) => ({
          id: index,
          label: OPERATOR_LABEL_MAPPING[operator] || operator,
          value: operator,
        })),
      ],
      formatValue: (value) => (typeof value === 'number' ? value * 100 : 0),
      getValue: (value) => (typeof value === 'number' ? value / 100 : 0),
      isValid: (filterValue) => {
        if (filterValue[COUPON_FILTER_KEY_MAPPING.WON_AMOUNT]) {
          return (
            filterValue[COUPON_FILTER_KEY_MAPPING.WON_AMOUNT_OPERATOR] !== '' &&
            filterValue[COUPON_FILTER_KEY_MAPPING.WON_AMOUNT] >= 1 &&
            filterValue[COUPON_FILTER_KEY_MAPPING.WON_AMOUNT] <= this.props.gamesSettings?.winCap
          );
        }
        return true;
      },
    },
  ];

  /**
   * Load more coupons
   *
   * @function
   * @returns {void}
   */
  loadMore = () => {
    const filters = this.props.filters || this.filters;
    this.getCoupons({ ...filters, sort: this.state.sort });
  };

  /**
   * Render
   *
   * @returns {view}
   */
  render() {
    const path = this.props.location.pathname;
    let additionalFilters = [];
    const hasExportCouponPermission = this.props.checkPermisson(PERMISSIONS.EXPORT_COUPONS);
    this.isSettled =
      path === MENU_ITEMS.COUPONS.COUPONS_SETTLED_VIEW.path ||
      path === MENU_ITEMS.COUPONS.SHOP_COUPONS_SETTLED_VIEW.path;

    if (path === MENU_ITEMS.COUPONS.COUPONS_PLACED_VIEW.path) {
      this.placedCouponsData = this.props.placedCoupons;
      this.couponsPage = COUPON_PAGES.PLACED_COUPON_MOBILE;
    } else if (path === MENU_ITEMS.COUPONS.SHOP_COUPONS_PLACED_VIEW.path) {
      this.placedCouponsData = this.props.placedCouponsShop;
      this.couponsPage = COUPON_PAGES.PLACED_COUPON_SHOP;
    } else if (path === MENU_ITEMS.COUPONS.COUPONS_SETTLED_VIEW.path) {
      this.settledCouponsData = this.props.settledCoupons;
      this.couponsPage = COUPON_PAGES.SETTLED_COUPON_MOBILE;
      if (hasExportCouponPermission) {
        additionalFilters = this.getAdditionalFilters(this.props);
      }
    } else if (path === MENU_ITEMS.COUPONS.SHOP_COUPONS_SETTLED_VIEW.path) {
      this.settledCouponsData = this.props.settledCouponsShop;
      this.couponsPage = COUPON_PAGES.SETTLED_COUPON_SHOP;
    }

    const gameField = this.filterFields.find((l) => l.text === 'Game');
    if (this.couponsPage === COUPON_PAGES.PLACED_COUPON_SHOP || this.couponsPage === COUPON_PAGES.SETTLED_COUPON_SHOP) {
      gameField.dropdown = this.props.shopGameStatuses;
      this.isShop = true;
    } else {
      gameField.dropdown = this.props.gameStatuses;
      this.isShop = false;
    }
    const selectedItem = {
      3:
        this.props.filters &&
        gameField.dropdown.find((x) => parseInt(x.id) === parseInt(this.props.filters['filter.game'])),
    };

    return (
      <>
        {this.props.isLoadingCoupons && <Loader />}
        <div className="user">
          <Filter
            filterFields={[...this.filterFields, ...additionalFilters]}
            info
            setFilterData={this.props.setFilterData}
            search={this.getCoupons}
            selectedMenuItem={this.props.location.pathname}
            filters={this.filters}
            defaultFilter={this.defaultFilter}
            initialApiCall={this.initialApiCall}
            filtersProps={this.props.filters}
            selectedItem={selectedItem}
            clearFilterData={this.props.clearFilterData}
            selectedTimezone={this.props.selectedTimezone}
            dateFilterFields={this.filterFields[4]?.fields}
            isSettledCouponsForMobile={this.couponsPage === COUPON_PAGES.SETTLED_COUPON_MOBILE}
            resetExport={this.props.resetExport}
            checkPermission={this.props.checkPermisson}
          />
          <ScrollTable
            loadMore={this.loadMore}
            isFetched={this.props.isFetched || this.props.isLoadingCoupons}
            isLastRecord={this.props.isLastRecord}
          >
            {!this.isSettled ? (
              <PlacedCoupons
                placedCoupons={this.placedCouponsData}
                currency={this.props.currency}
                selectedCouponId={this.props.selectedCoupon && this.props.selectedCoupon.id}
                selectCoupon={this.props.selectCoupon}
                hasRecord={this.props.hasRecord}
                selectedTimezone={this.props.selectedTimezone}
                gameStatuses={this.props.gameStatuses}
                shopGameStatuses={this.props.shopGameStatuses}
                isShop={this.isShop}
              />
            ) : (
              <SettledCoupons
                placedCoupons={this.settledCouponsData}
                currency={this.props.currency}
                selectedCouponId={this.props.selectedCoupon && this.props.selectedCoupon.id}
                selectCoupon={this.props.selectCoupon}
                hasRecord={this.props.hasRecord}
                selectedTimezone={this.props.selectedTimezone}
                gameStatuses={this.props.gameStatuses}
                shopGameStatuses={this.props.shopGameStatuses}
                isShop={this.isShop}
                setOpenModal={this.props.setOpenModal}
                activeModal={this.props.activeModal}
                voidCouponRequest={this.props.voidCoupon}
                setCouponToWontpayRequest={this.props.setCouponToWontpay}
                checkPermisson={this.props.checkPermisson}
                betStatus={this.props.betStatus}
                sort={this.state.sort}
                onSortColumn={this.sortColumn}
              />
            )}
          </ScrollTable>
        </div>
        {this.props.selectedCoupon && (
          <CouponDetails
            selectedCoupon={this.props.selectedCoupon}
            currency={this.props.currency}
            settled={this.isSettled}
            betStatus={this.props.betStatus}
            couponSource={this.props.couponSource}
          />
        )}
      </>
    );
  }
}

export default connect(mapToProps, actionsToProps)(withRouterHooks(Coupons));