src/components/templates/Loyalty/loyalty.jsx

import React, {useEffect} from "react";
import {MemoryRouter, Route, Switch} from "react-router-dom";
import {useAsyncState} from "hooks";
import {withTemplate} from "components/hocs";
import {Fragments} from "components";
import {FETCH_LOYALTY} from "utils/api";
import {config, constants, Routes} from "utils";
import css from "./loyalty.module.css";
import INITIAL_DATA from "./initializer";
import CreditBased from "./CreditBased";
import WalletBased from "./WalletBased";
import RedeemForm from "./WalletBased/Rewards/RedeemForm";

const {
  LOYALTY_SYSTEMS: {CREDIT, WALLET},
} = constants;
const {
  Loader,
  Routes: {RouteWithProps},
} = Fragments;

const loyaltySections = config?.theme?.loyalty?.length
  ? config.theme.loyalty
  : null;

/**
 * Fetch loyalty data from '/loyalty' endpoint & returns Loyalty component
 *
 * @author Htin Linn Aung
 * @memberof Templates.Templates/Loyalty
 * @param {object} props
 * @param {object} prop.style - Theme - Theme value from template provider
 * @param props.style
 * @param {object} props.walletProps - props just for wallet configuration
 * @param {object} props.sections - Config - Loyalty Section to render
 * @returns {React.Element} - Fetch loyalty data from '/loyalty' endpoint & returns Loyalty component
 */
const Loyalty = ({style, walletProps}) => {
  const [loyalty, setLoyalty] = useAsyncState({
    fetching: false,
    state: INITIAL_DATA,
  });
  let loyaltySectionId = 0;

  /**
   * Fetch loyalty data from '/loyalty' endpoint and set component states
   *
   * @author Htin Linn Aung
   * @memberof Templates.Templates/Loyalty
   * @async
   * @function fetchLoyalty
   */
  const fetchLoyalty = async () => {
    setLoyalty.setIsFetching();
    try {
      const res = await FETCH_LOYALTY();
      if (res.status === 200) {
        setLoyalty.setState(res.data);
      }
    } catch (e) {
      console.error(e);
    } finally {
      setLoyalty.setNotFetching();
    }
  };

  useEffect(() => {
    fetchLoyalty();
  }, []);

  /**
   * Loyalty section selector
   *
   * @author Htin Linn Aung
   * @memberof Templates.Templates/Loyalty
   * @function selectSection
   * @param {object} section
   * @param {object} location - Memory Router location
   * @param {object} history - Memory Router history
   */
  const selectSection = (section, location, history) => {
    let Component;
    let componentSpecificProps = {};

    switch (section.system) {
      case CREDIT:
        Component = CreditBased;
        break;
      case WALLET:
        Component = WalletBased;
        componentSpecificProps = {
          ...walletProps,
          onClickRedeem: () => history.push(Routes.REDEEM_REWARDS),
        };
        break;
      default:
        Component = CreditBased;
    }
    loyaltySectionId += 1;
    return (
      <Component
        key={loyaltySectionId}
        loyaltyData={loyalty.state}
        loyaltyLayout={section.layout}
        location={location}
        history={history}
        {...componentSpecificProps}
      />
    );
  };

  /**
   * Render all available loyalty sections
   *
   * @author Htin Linn Aung
   * @memberof Templates.Templates/Loyalty
   * @function renderLoyalty
   * @param {object} location - Memory Router location
   * @param {object} history - Memory Router history
   */
  const renderLoyalty = (location, history) => {
    if (loyalty.fetching) {
      return (
        <div className={css.loader}>
          <Loader />
        </div>
      );
    }
    return loyaltySections?.map((section) =>
      selectSection(section, location, history),
    );
  };

  const handleSuccess = (history) => {
    fetchLoyalty();
    history.goBack();
  };

  return (
    <MemoryRouter initialEntries={["/"]} initialIndex={0}>
      <Route
        render={({location, history}) => (
          <div>
            <Switch>
              <RouteWithProps
                exact
                path={Routes.ROOT}
                render={() => (
                  <div className={css.container}>
                    {renderLoyalty(location, history)}
                  </div>
                )}
              />
              <RouteWithProps
                path={Routes.REDEEM_REWARDS}
                component={RedeemForm}
                style={style}
                history={history}
                location={location}
                onSuccess={() => handleSuccess(history)}
              />
            </Switch>
          </div>
        )}
      />
    </MemoryRouter>
  );
};

Loyalty.defaultProps = {
  walletProps: {},
};

export default withTemplate(Loyalty, "loyalty");