teamdigitale/italia-app

View on GitHub
ts/features/wallet/onboarding/bancomatPay/screens/add-account/AddBPayScreen.tsx

Summary

Maintainability
F
3 days
Test Coverage
import * as pot from "@pagopa/ts-commons/lib/pot";
import * as AR from "fp-ts/lib/Array";
import { pipe } from "fp-ts/lib/function";
import * as O from "fp-ts/lib/Option";
import * as React from "react";
import { connect } from "react-redux";
import { Dispatch } from "redux";
import { BPay } from "../../../../../../../definitions/pagopa/BPay";
import BaseScreenComponent from "../../../../../../components/screens/BaseScreenComponent";
import { profileSelector } from "../../../../../../store/reducers/profile";
import { GlobalState } from "../../../../../../store/reducers/types";
import {
  getValueOrElse,
  isError,
  isLoading,
  isReady
} from "../../../../../../common/model/RemoteValue";
import {
  addBPayToWalletAction,
  walletAddBPayCancel,
  walletAddBPayCompleted
} from "../../store/actions";
import {
  onboardingBPayAddingResultSelector,
  onboardingBPayChosenPanSelector
} from "../../store/reducers/addingBPay";
import { onboardingBPayFoundAccountsSelector } from "../../store/reducers/foundBpay";
import AddBPayComponent from "./AddBPayComponent";
import LoadAddBPayComponent from "./LoadAddBPayComponent";

type Props = ReturnType<typeof mapStateToProps> &
  ReturnType<typeof mapDispatchToProps> &
  Pick<React.ComponentProps<typeof BaseScreenComponent>, "contextualHelp">;

type NextAction = {
  index: number;
  skip: boolean;
};
/**
 * This screen is displayed when BPay are found and ready to be added in wallet
 * @constructor
 */
const AddBPayScreen = (props: Props): React.ReactElement | null => {
  // next could be skip or not (a pan should be added)
  const [currentAction, setNextAction] = React.useState<NextAction>({
    index: 0,
    skip: false
  });
  const { isAddingReady, bPayAccounts, onCompleted } = props;

  const currentIndex = currentAction.index;

  React.useEffect(() => {
    // call onCompleted when the end of bpay pans has been reached
    // and the adding phase has been completed (or it was skipped step)
    if (
      currentIndex >= bPayAccounts.length &&
      (currentAction.skip || isAddingReady)
    ) {
      onCompleted();
    }
  }, [currentAction, isAddingReady, bPayAccounts, onCompleted, currentIndex]);

  const nextPan = (skip: boolean) => {
    const nextIndex = currentIndex + 1;
    setNextAction({ index: nextIndex, skip });
  };

  const handleOnContinue = () => {
    if (currentIndex < props.bPayAccounts.length) {
      props.addBPay(props.bPayAccounts[currentIndex]);
    }
    nextPan(false);
  };

  const currentPan = AR.lookup(currentIndex, [...props.bPayAccounts]);

  return props.loading || props.isAddingResultError ? (
    <LoadAddBPayComponent
      isLoading={!props.isAddingResultError}
      onCancel={props.onCancel}
      onRetry={() =>
        pipe(props.selectedBPay, O.fromNullable, O.map(props.onRetry))
      }
    />
  ) : O.isSome(currentPan) ? (
    <AddBPayComponent
      account={currentPan.value}
      accountsNumber={props.bPayAccounts.length}
      currentIndex={currentIndex}
      handleContinue={handleOnContinue}
      handleSkip={() => nextPan(true)}
      contextualHelp={props.contextualHelp}
    />
  ) : null; // this should not happen
};

const mapDispatchToProps = (dispatch: Dispatch) => ({
  addBPay: (bPay: BPay) => dispatch(addBPayToWalletAction.request(bPay)),
  onCompleted: () => dispatch(walletAddBPayCompleted()),
  onCancel: () => dispatch(walletAddBPayCancel()),
  onRetry: (bPay: BPay) => dispatch(addBPayToWalletAction.request(bPay))
});

const mapStateToProps = (state: GlobalState) => {
  const remoteBPay = onboardingBPayFoundAccountsSelector(state);
  const addingResult = onboardingBPayAddingResultSelector(state);
  const bPayAccounts = getValueOrElse(remoteBPay, []);
  return {
    isAddingReady: isReady(addingResult),
    loading: isLoading(addingResult),
    isAddingResultError: isError(addingResult),
    remoteBPay,
    selectedBPay: onboardingBPayChosenPanSelector(state),
    bPayAccounts,
    profile: pot.toUndefined(profileSelector(state))
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(AddBPayScreen);