teamdigitale/italia-app

View on GitHub
ts/features/messages/store/reducers/messageGetStatus.ts

Summary

Maintainability
B
4 hrs
Test Coverage
import { getType } from "typesafe-actions";
import {
  SuccessGetMessageDataActionType,
  getMessageDataAction,
  reloadAllMessages,
  resetGetMessageDataAction
} from "../actions";
import { Action } from "../../../../store/actions/types";
import { GlobalState } from "../../../../store/reducers/types";
import { startApplicationInitialization } from "../../../../store/actions/application";
import { UIMessageId } from "../../types";

export type MessageGetStatusFailurePhaseType =
  | "none"
  | "paginatedMessage"
  | "serviceDetails"
  | "messageDetails"
  | "preconditions"
  | "thirdPartyMessageDetails"
  | "readStatusUpdate";

type IdleState = {
  status: "idle";
};

type BlockedOrErrorState = {
  status: "blocked" | "error";
  failurePhase: MessageGetStatusFailurePhaseType;
};

type LoadingOrRetryState = {
  status: "loading" | "retry";
  data: {
    messageId: UIMessageId;
    fromPushNotification: boolean;
  };
};

type SuccessState = {
  status: "success";
  successData: SuccessGetMessageDataActionType;
};

export type MessageGetStatus =
  | IdleState
  | BlockedOrErrorState
  | LoadingOrRetryState
  | SuccessState;

export const INITIAL_STATE: MessageGetStatus = {
  status: "idle"
};

export const messageGetStatusReducer = (
  state: MessageGetStatus = INITIAL_STATE,
  action: Action
): MessageGetStatus => {
  switch (action.type) {
    case getType(getMessageDataAction.request):
      return {
        status: "loading",
        data: {
          messageId: action.payload.messageId,
          fromPushNotification: action.payload.fromPushNotification
        }
      };
    case getType(startApplicationInitialization):
      const fastLoginSessionExpired =
        !!(action.payload && action.payload.handleSessionExpiration) &&
        isLoadingStatus(state);
      return fastLoginSessionExpired
        ? {
            ...state,
            status: "retry"
          }
        : state;
    case getType(getMessageDataAction.failure):
      return {
        status: action.payload.blockedFromPushNotificationOpt
          ? "blocked"
          : "error",
        failurePhase: action.payload.phase
      };
    case getType(getMessageDataAction.success):
      return {
        status: "success",
        successData: action.payload
      };
    case getType(resetGetMessageDataAction):
    case getType(reloadAllMessages.request):
      return INITIAL_STATE;
  }
  return state;
};

const isLoadingStatus = (
  messageGetStatus: MessageGetStatus
): messageGetStatus is LoadingOrRetryState =>
  messageGetStatus.status === "loading";
const isRetryStatus = (
  messageGetStatus: MessageGetStatus
): messageGetStatus is LoadingOrRetryState =>
  messageGetStatus.status === "retry";
const isSuccessStatus = (
  messageGetStatus: MessageGetStatus
): messageGetStatus is SuccessState => messageGetStatus.status === "success";

export const showSpinnerFromMessageGetStatusSelector = (state: GlobalState) =>
  state.entities.messages.messageGetStatus.status !== "error";

export const thirdPartyMessageDetailsErrorSelector = (state: GlobalState) =>
  state.entities.messages.messageGetStatus.status === "error" &&
  state.entities.messages.messageGetStatus.failurePhase ===
    "thirdPartyMessageDetails";

export const messageSuccessDataSelector = (state: GlobalState) =>
  isSuccessStatus(state.entities.messages.messageGetStatus)
    ? state.entities.messages.messageGetStatus.successData
    : undefined;

export const blockedFromPushNotificationSelector = (state: GlobalState) =>
  state.entities.messages.messageGetStatus.status === "blocked";

export const retryDataAfterFastLoginSessionExpirationSelector = (
  state: GlobalState
) =>
  isRetryStatus(state.entities.messages.messageGetStatus)
    ? state.entities.messages.messageGetStatus.data
    : undefined;