@mxenabled/connect-widget 0.19.5 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js CHANGED
@@ -5236,7 +5236,8 @@ const ActionTypes$2 = {
5236
5236
  MFA_CONNECT_SUBMIT_ERROR: "connect/mfa_connect_submit_error",
5237
5237
  MFA_CONNECT_SUBMIT_SUCCESS: "connect/mfa_connect_submit_success",
5238
5238
  LOGIN_ERROR_START_OVER: "connect/login_error_start_over",
5239
- CONNECT_GO_BACK: "connect/go_back"
5239
+ CONNECT_GO_BACK: "connect/go_back",
5240
+ REJECT_ADDITIONAL_PRODUCT: "connect/reject_additional_product"
5240
5241
  };
5241
5242
  const loadConnect$1 = (config = {}) => ({ type: ActionTypes$2.LOAD_CONNECT, payload: config });
5242
5243
  const loadConnectSuccess$1 = (dependencies = {}) => ({
@@ -5328,6 +5329,7 @@ const TAX_MODE = "tax";
5328
5329
  const STEPS = {
5329
5330
  ACTIONABLE_ERROR: "actionableError",
5330
5331
  ADD_MANUAL_ACCOUNT: "addManualAccount",
5332
+ ADDITIONAL_PRODUCT: "additionalProduct",
5331
5333
  CONNECTED: "connected",
5332
5334
  CONNECTING: "connecting",
5333
5335
  CONSENT: "consent",
@@ -8973,6 +8975,185 @@ const hasNoSingleAccountSelectOptions = (member) => {
8973
8975
  return false;
8974
8976
  };
8975
8977
 
8978
+ const COMBO_JOB_DATA_TYPES = {
8979
+ ACCOUNT_NUMBER: "account_verification",
8980
+ // verification mode
8981
+ ACCOUNT_OWNER: "identity_verification",
8982
+ // include_identity
8983
+ TRANSACTIONS: "transactions",
8984
+ REWARDS: "rewards"};
8985
+
8986
+ const initialState$5 = {
8987
+ _initialValues: "",
8988
+ is_mobile_webview: false,
8989
+ target_origin_referrer: null,
8990
+ ui_message_protocol: "post_message",
8991
+ ui_message_version: 1,
8992
+ ui_message_webview_url_scheme: "mx",
8993
+ color_scheme: "light",
8994
+ mode: AGG_MODE,
8995
+ current_institution_code: null,
8996
+ current_institution_guid: null,
8997
+ current_member_guid: null,
8998
+ current_microdeposit_guid: null,
8999
+ enable_app2app: true,
9000
+ disable_background_agg: null,
9001
+ disable_institution_search: false,
9002
+ include_identity: null,
9003
+ include_transactions: null,
9004
+ iso_country_code: null,
9005
+ oauth_referral_source: REFERRAL_SOURCES.BROWSER,
9006
+ update_credentials: false,
9007
+ wait_for_full_aggregation: false,
9008
+ data_request: null,
9009
+ use_cases: null,
9010
+ additional_product_option: null
9011
+ };
9012
+ const configSlice = createSlice({
9013
+ name: "config",
9014
+ initialState: initialState$5,
9015
+ reducers: {
9016
+ addVerificationData: (state) => {
9017
+ if (state.mode === AGG_MODE) {
9018
+ state.include_transactions = true;
9019
+ }
9020
+ state.mode = VERIFY_MODE;
9021
+ if (Array.isArray(state.use_cases)) {
9022
+ state.use_cases.push("MONEY_MOVEMENT");
9023
+ } else {
9024
+ state.use_cases = ["MONEY_MOVEMENT"];
9025
+ }
9026
+ },
9027
+ addAggregationData: (state) => {
9028
+ state.include_transactions = true;
9029
+ if (Array.isArray(state.use_cases)) {
9030
+ state.use_cases.push("PFM");
9031
+ } else {
9032
+ state.use_cases = ["PFM"];
9033
+ }
9034
+ },
9035
+ additionalProductReset: _additionalProductReset
9036
+ },
9037
+ extraReducers(builder) {
9038
+ builder.addCase(
9039
+ ActionTypes$2.LOAD_CONNECT,
9040
+ (state, action) => {
9041
+ const productDetermineMode = getProductDeterminedMode(action.payload);
9042
+ const ui_message_version = typeof action.payload.ui_message_version === "string" ? parseInt(action.payload.ui_message_version, 10) : action.payload.ui_message_version || state.ui_message_version;
9043
+ const loadedState = {
9044
+ ...state,
9045
+ ...action.payload,
9046
+ ui_message_version,
9047
+ mode: productDetermineMode !== null ? productDetermineMode : action.payload.mode || state.mode
9048
+ };
9049
+ const { _initialValues, ...stateWithoutInitialValues } = loadedState;
9050
+ return {
9051
+ ...stateWithoutInitialValues,
9052
+ // _initialValues is a reference to the values that were used to load the widget initially.
9053
+ // It is meant to be set, and then READ ONLY after that.
9054
+ // Example:
9055
+ // When a user dynamically changes the mode, use_cases, or data for a connection we need to
9056
+ // reset the mode, use_cases, and data to the initial state for the next connection attempt.
9057
+ // JSON is used here to deeply copy the object, use a selector to get the values.
9058
+ _initialValues: JSON.stringify(stateWithoutInitialValues)
9059
+ };
9060
+ }
9061
+ );
9062
+ builder.addCase(
9063
+ ActionTypes$2.CONNECT_GO_BACK,
9064
+ (state, action) => {
9065
+ const resetSteps = [STEPS.SEARCH, STEPS.VERIFY_EXISTING_MEMBER, STEPS.ADDITIONAL_PRODUCT];
9066
+ if (resetSteps.includes(action.payload?.previousStep)) {
9067
+ return _additionalProductReset(state);
9068
+ }
9069
+ return state;
9070
+ }
9071
+ );
9072
+ builder.addCase(ActionTypes$2.RESET_WIDGET_CONNECTED, (state) => {
9073
+ return _additionalProductReset(state);
9074
+ });
9075
+ builder.addCase(ActionTypes$2.ACTIONABLE_ERROR_CONNECT_DIFFERENT_INSTITUTION, (state) => {
9076
+ return _additionalProductReset(state);
9077
+ });
9078
+ builder.addCase(ActionTypes$2.LOGIN_ERROR_START_OVER, (state) => {
9079
+ return _additionalProductReset(state);
9080
+ });
9081
+ builder.addCase(ActionTypes$2.DELETE_MEMBER_SUCCESS_RESET, (state) => {
9082
+ return _additionalProductReset(state);
9083
+ });
9084
+ builder.addCase(ActionTypes$2.RESET_WIDGET_MFA_STEP, (state) => {
9085
+ return _additionalProductReset(state);
9086
+ });
9087
+ }
9088
+ });
9089
+ const selectInitialConfig = createSelector(
9090
+ (state) => state.config._initialValues,
9091
+ (initialValues) => convertInitialValuesToObject(initialValues)
9092
+ );
9093
+ const selectConfig = (state) => state.config;
9094
+ const selectIsMobileWebView = (state) => state.config.is_mobile_webview;
9095
+ const selectUIMessageVersion = (state) => state.config.ui_message_version;
9096
+ const selectConnectConfig = createSelector(selectConfig, (config) => ({
9097
+ mode: config.mode,
9098
+ current_institution_code: config.current_institution_code,
9099
+ current_institution_guid: config.current_institution_guid,
9100
+ current_member_guid: config.current_member_guid,
9101
+ current_microdeposit_guid: config.current_microdeposit_guid,
9102
+ enable_app2app: config.enable_app2app,
9103
+ disable_background_agg: config.disable_background_agg,
9104
+ disable_institution_search: config.disable_institution_search,
9105
+ include_identity: config.include_identity,
9106
+ include_transactions: config.include_transactions,
9107
+ iso_country_code: config.iso_country_code,
9108
+ oauth_referral_source: config.oauth_referral_source,
9109
+ update_credentials: config.update_credentials,
9110
+ wait_for_full_aggregation: config.wait_for_full_aggregation,
9111
+ data_request: config.data_request,
9112
+ use_cases: config.use_cases,
9113
+ additional_product_option: config.additional_product_option
9114
+ }));
9115
+ const selectColorScheme = (state) => state.config.color_scheme;
9116
+ const getProductDeterminedMode = (config) => {
9117
+ const products = config?.data_request?.products;
9118
+ if (Array.isArray(products)) {
9119
+ if (products.includes(COMBO_JOB_DATA_TYPES.ACCOUNT_NUMBER)) {
9120
+ return VERIFY_MODE;
9121
+ } else if (products.includes(COMBO_JOB_DATA_TYPES.REWARDS)) {
9122
+ return REWARD_MODE;
9123
+ } else {
9124
+ return AGG_MODE;
9125
+ }
9126
+ } else {
9127
+ return null;
9128
+ }
9129
+ };
9130
+ const convertInitialValuesToObject = (initialValues) => {
9131
+ try {
9132
+ return JSON.parse(initialValues);
9133
+ } catch (error) {
9134
+ return {};
9135
+ }
9136
+ };
9137
+ function _additionalProductReset(state) {
9138
+ const initialValuesObject = convertInitialValuesToObject(state._initialValues);
9139
+ return {
9140
+ ...state,
9141
+ include_transactions: initialValuesObject?.include_transactions ?? initialState$5.include_transactions,
9142
+ mode: initialValuesObject?.mode ?? initialState$5.mode,
9143
+ use_cases: initialValuesObject?.use_cases ?? initialState$5.use_cases
9144
+ };
9145
+ }
9146
+ const { addVerificationData, addAggregationData, additionalProductReset } = configSlice.actions;
9147
+ const configSlice$1 = configSlice.reducer;
9148
+
9149
+ const ACTIONABLE_ERROR_CODES = {
9150
+ NO_ELIGIBLE_ACCOUNTS: 1e3
9151
+ };
9152
+ const ACTIVE_ACTIONABLE_ERROR_CODES = Object.values(ACTIONABLE_ERROR_CODES);
9153
+ const canHandleActionableError = (errorCode) => {
9154
+ return ACTIVE_ACTIONABLE_ERROR_CODES.includes(errorCode);
9155
+ };
9156
+
8976
9157
  const defaultState$1 = {
8977
9158
  error: null,
8978
9159
  // The most recent job request error, if any
@@ -9165,13 +9346,33 @@ const acceptDisclosure = (state, { payload }) => {
9165
9346
  return { ...state, location: pushLocation(state.location, nextStep) };
9166
9347
  };
9167
9348
  const selectInstitutionSuccess = (state, action) => {
9349
+ let nextStep = STEPS.ENTER_CREDENTIALS;
9350
+ const canOfferVerification = action.payload.institution?.account_verification_is_enabled && action.payload.additionalProductOption === COMBO_JOB_DATA_TYPES.ACCOUNT_NUMBER;
9351
+ const canOfferAggregation = action.payload.additionalProductOption === COMBO_JOB_DATA_TYPES.TRANSACTIONS;
9352
+ if (canOfferVerification || canOfferAggregation) {
9353
+ nextStep = STEPS.ADDITIONAL_PRODUCT;
9354
+ } else if (action.payload.consentIsEnabled) {
9355
+ nextStep = STEPS.CONSENT;
9356
+ }
9357
+ if (state.location.length > 0 && state.location[state.location.length - 1].step === nextStep) {
9358
+ return {
9359
+ ...state,
9360
+ selectedInstitution: action.payload.institution
9361
+ };
9362
+ }
9363
+ return {
9364
+ ...state,
9365
+ location: pushLocation(state.location, nextStep),
9366
+ selectedInstitution: action.payload.institution
9367
+ };
9368
+ };
9369
+ const continueAfterAdditionalProduct = (state, action) => {
9168
9370
  return {
9169
9371
  ...state,
9170
9372
  location: pushLocation(
9171
9373
  state.location,
9172
- action.payload.consentFlag ? STEPS.CONSENT : STEPS.ENTER_CREDENTIALS
9173
- ),
9174
- selectedInstitution: action.payload.institution
9374
+ action.payload.consentIsEnabled ? STEPS.CONSENT : STEPS.ENTER_CREDENTIALS
9375
+ )
9175
9376
  };
9176
9377
  };
9177
9378
  const startOauth = (state, action) => ({
@@ -9281,9 +9482,24 @@ const addManualAccount = (state, { payload }) => {
9281
9482
  return state;
9282
9483
  };
9283
9484
  const connectGoBack = (state) => {
9485
+ const stepsWhichResetValues = [STEPS.SEARCH, STEPS.VERIFY_EXISTING_MEMBER];
9486
+ const newLocationValues = popLocation(state);
9487
+ if (stepsWhichResetValues.includes(newLocationValues[newLocationValues.length - 1]?.step)) {
9488
+ return {
9489
+ ...state,
9490
+ location: newLocationValues,
9491
+ currentMemberGuid: defaultState$1.currentMemberGuid,
9492
+ error: defaultState$1.error,
9493
+ updateCredentials: defaultState$1.updateCredentials,
9494
+ oauthURL: defaultState$1.oauthURL,
9495
+ oauthErrorReason: defaultState$1.oauthErrorReason,
9496
+ jobSchedule: UNINITIALIZED$2,
9497
+ selectedInstitution: defaultState$1.selectedInstitution
9498
+ };
9499
+ }
9284
9500
  return {
9285
9501
  ...state,
9286
- location: popLocation(state)
9502
+ location: newLocationValues
9287
9503
  };
9288
9504
  };
9289
9505
  const actionableErrorConnectDifferentInstitution = (state, action) => {
@@ -9344,7 +9560,7 @@ function getStartingStep(members, member, microdeposit, config, institution, wid
9344
9560
  }
9345
9561
  function getStepFromMember(member) {
9346
9562
  const connection_status = member.connection_status;
9347
- if (member?.most_recent_job_detail_code || hasNoSingleAccountSelectOptions(member))
9563
+ if (member?.most_recent_job_detail_code && canHandleActionableError(member?.most_recent_job_detail_code) || hasNoSingleAccountSelectOptions(member))
9348
9564
  return STEPS.ACTIONABLE_ERROR;
9349
9565
  else if (connection_status === ReadableStatuses$1.CHALLENGED)
9350
9566
  return STEPS.MFA;
@@ -9429,147 +9645,14 @@ const connect = createReducer(defaultState$1, {
9429
9645
  [ActionTypes$2.MFA_CONNECT_SUBMIT_ERROR]: mfaConnectSubmitError,
9430
9646
  [ActionTypes$2.ADD_MANUAL_ACCOUNT_SUCCESS]: addManualAccount,
9431
9647
  [ActionTypes$2.LOGIN_ERROR_START_OVER]: loginErrorStartOver,
9432
- [ActionTypes$2.CONNECT_GO_BACK]: connectGoBack
9433
- });
9434
-
9435
- const COMBO_JOB_DATA_TYPES = {
9436
- ACCOUNT_NUMBER: "account_verification",
9437
- // verification mode
9438
- ACCOUNT_OWNER: "identity_verification",
9439
- // include_identity
9440
- TRANSACTIONS: "transactions",
9441
- REWARDS: "rewards"};
9442
-
9443
- const initialState$5 = {
9444
- _initialValues: "",
9445
- is_mobile_webview: false,
9446
- target_origin_referrer: null,
9447
- ui_message_protocol: "post_message",
9448
- ui_message_version: 1,
9449
- ui_message_webview_url_scheme: "mx",
9450
- color_scheme: "light",
9451
- mode: AGG_MODE,
9452
- current_institution_code: null,
9453
- current_institution_guid: null,
9454
- current_member_guid: null,
9455
- current_microdeposit_guid: null,
9456
- enable_app2app: true,
9457
- disable_background_agg: null,
9458
- disable_institution_search: false,
9459
- include_identity: null,
9460
- include_transactions: null,
9461
- iso_country_code: null,
9462
- oauth_referral_source: REFERRAL_SOURCES.BROWSER,
9463
- update_credentials: false,
9464
- wait_for_full_aggregation: false,
9465
- data_request: null,
9466
- use_cases: null
9467
- };
9468
- const configSlice = createSlice({
9469
- name: "config",
9470
- initialState: initialState$5,
9471
- reducers: {
9472
- stepUpToVerification: (state) => {
9473
- if (state.mode === AGG_MODE) {
9474
- state.include_transactions = true;
9475
- }
9476
- state.mode = VERIFY_MODE;
9477
- if (Array.isArray(state.use_cases)) {
9478
- state.use_cases.push("MONEY_MOVEMENT");
9479
- } else {
9480
- state.use_cases = ["MONEY_MOVEMENT"];
9481
- }
9482
- },
9483
- stepUpToAggregation: (state) => {
9484
- state.include_transactions = true;
9485
- if (Array.isArray(state.use_cases)) {
9486
- state.use_cases.push("PFM");
9487
- } else {
9488
- state.use_cases = ["PFM"];
9489
- }
9490
- },
9491
- stepUpReset: (state) => {
9492
- const initialValuesObject = convertInitialValuesToObject(state._initialValues);
9493
- return {
9494
- ...state,
9495
- include_transactions: initialValuesObject?.include_transactions ?? initialState$5.include_transactions,
9496
- mode: initialValuesObject?.mode ?? initialState$5.mode,
9497
- use_cases: initialValuesObject?.use_cases ?? initialState$5.use_cases
9498
- };
9499
- }
9500
- },
9501
- extraReducers(builder) {
9502
- builder.addCase(
9503
- ActionTypes$2.LOAD_CONNECT,
9504
- (state, action) => {
9505
- const productDetermineMode = getProductDeterminedMode(action.payload);
9506
- const ui_message_version = typeof action.payload.ui_message_version === "string" ? parseInt(action.payload.ui_message_version, 10) : action.payload.ui_message_version || state.ui_message_version;
9507
- const loadedState = {
9508
- ...state,
9509
- ...action.payload,
9510
- ui_message_version,
9511
- mode: productDetermineMode !== null ? productDetermineMode : action.payload.mode || state.mode
9512
- };
9513
- const { _initialValues, ...stateWithoutInitialValues } = loadedState;
9514
- return {
9515
- ...stateWithoutInitialValues,
9516
- // _initialValues is a reference to the values that were used to load the widget initially.
9517
- // It is meant to be set, and then READ ONLY after that.
9518
- // Example:
9519
- // When a user dynamically changes the mode, use_cases, or data for a connection we need to
9520
- // reset the mode, use_cases, and data to the initial state for the next connection attempt.
9521
- // JSON is used here to deeply copy the object, use a selector to get the values.
9522
- _initialValues: JSON.stringify(stateWithoutInitialValues)
9523
- };
9524
- }
9525
- );
9526
- }
9648
+ [ActionTypes$2.CONNECT_GO_BACK]: connectGoBack,
9649
+ // Addtional product offer / step up reducers
9650
+ // These are here to manage changing the location/step of the widget
9651
+ [ActionTypes$2.REJECT_ADDITIONAL_PRODUCT]: continueAfterAdditionalProduct,
9652
+ // Listening to the step up actions from the configSlice
9653
+ [addVerificationData().type]: continueAfterAdditionalProduct,
9654
+ [addAggregationData().type]: continueAfterAdditionalProduct
9527
9655
  });
9528
- const selectConfig = (state) => state.config;
9529
- const selectIsMobileWebView = (state) => state.config.is_mobile_webview;
9530
- const selectUIMessageVersion = (state) => state.config.ui_message_version;
9531
- const selectConnectConfig = createSelector(selectConfig, (config) => ({
9532
- mode: config.mode,
9533
- current_institution_code: config.current_institution_code,
9534
- current_institution_guid: config.current_institution_guid,
9535
- current_member_guid: config.current_member_guid,
9536
- current_microdeposit_guid: config.current_microdeposit_guid,
9537
- enable_app2app: config.enable_app2app,
9538
- disable_background_agg: config.disable_background_agg,
9539
- disable_institution_search: config.disable_institution_search,
9540
- include_identity: config.include_identity,
9541
- include_transactions: config.include_transactions,
9542
- iso_country_code: config.iso_country_code,
9543
- oauth_referral_source: config.oauth_referral_source,
9544
- update_credentials: config.update_credentials,
9545
- wait_for_full_aggregation: config.wait_for_full_aggregation,
9546
- data_request: config.data_request,
9547
- use_cases: config.use_cases
9548
- }));
9549
- const selectColorScheme = (state) => state.config.color_scheme;
9550
- const getProductDeterminedMode = (config) => {
9551
- const products = config?.data_request?.products;
9552
- if (Array.isArray(products)) {
9553
- if (products.includes(COMBO_JOB_DATA_TYPES.ACCOUNT_NUMBER)) {
9554
- return VERIFY_MODE;
9555
- } else if (products.includes(COMBO_JOB_DATA_TYPES.REWARDS)) {
9556
- return REWARD_MODE;
9557
- } else {
9558
- return AGG_MODE;
9559
- }
9560
- } else {
9561
- return null;
9562
- }
9563
- };
9564
- const convertInitialValuesToObject = (initialValues) => {
9565
- try {
9566
- return JSON.parse(initialValues);
9567
- } catch (error) {
9568
- return {};
9569
- }
9570
- };
9571
- const { stepUpToVerification, stepUpToAggregation, stepUpReset } = configSlice.actions;
9572
- const configSlice$1 = configSlice.reducer;
9573
9656
 
9574
9657
  const initialState$4 = {
9575
9658
  loading: true,
@@ -71757,6 +71840,7 @@ const LoginError = React__default.forwardRef(
71757
71840
  const postMessageFunctions = useContext(PostMessageContext);
71758
71841
  const dispatch = useDispatch();
71759
71842
  const connectConfig = useSelector(selectConnectConfig);
71843
+ const initialConfig = useSelector(selectInitialConfig);
71760
71844
  const pageViewInfo = PageviewInfo.CONNECT_LOGIN_ERROR;
71761
71845
  useAnalyticsPath(...pageViewInfo);
71762
71846
  const [isLeaving, setIsLeaving] = useState(false);
@@ -71785,7 +71869,10 @@ const LoginError = React__default.forwardRef(
71785
71869
  }
71786
71870
  });
71787
71871
  }, [member]);
71788
- const loginErrorStartOver = () => dispatch({ type: ActionTypes$2.LOGIN_ERROR_START_OVER, payload: { mode: connectConfig.mode } });
71872
+ const loginErrorStartOver = () => dispatch({
71873
+ type: ActionTypes$2.LOGIN_ERROR_START_OVER,
71874
+ payload: { mode: initialConfig.mode }
71875
+ });
71789
71876
  const handleOkPrimaryActionClick = () => {
71790
71877
  postMessageFunctions.onPostMessage("connect/memberError/primaryAction", {
71791
71878
  member: {
@@ -71992,14 +72079,11 @@ LoginError.propTypes = {
71992
72079
  };
71993
72080
  LoginError.displayName = "LoginError";
71994
72081
 
71995
- const ACTIONABLE_ERROR_CODES = {
71996
- NO_ELIGIBLE_ACCOUNTS: 1e3
71997
- };
71998
-
71999
72082
  const ActionableError = () => {
72000
72083
  const postMessageFunctions = useContext(PostMessageContext);
72001
72084
  const institution = useSelector((state) => state.connect.selectedInstitution);
72002
72085
  const currentMember = useSelector(getCurrentMember);
72086
+ const initialConfig = useSelector(selectInitialConfig);
72003
72087
  const jobDetailCode = currentMember.most_recent_job_detail_code;
72004
72088
  const tokens = useTokens();
72005
72089
  const styles = getStyles$A(tokens);
@@ -72021,7 +72105,10 @@ const ActionableError = () => {
72021
72105
  label: __("Connect a different institution"),
72022
72106
  action: () => {
72023
72107
  postMessageFunctions.onPostMessage("connect/backToSearch");
72024
- dispatch({ type: ActionTypes$2.ACTIONABLE_ERROR_CONNECT_DIFFERENT_INSTITUTION });
72108
+ dispatch({
72109
+ type: ActionTypes$2.ACTIONABLE_ERROR_CONNECT_DIFFERENT_INSTITUTION,
72110
+ payload: initialConfig.mode
72111
+ });
72025
72112
  }
72026
72113
  }
72027
72114
  }
@@ -76674,11 +76761,96 @@ const Actions = {
76674
76761
  HANDLE_SUCCESS: "manualAccount/handleSuccess"
76675
76762
  };
76676
76763
 
76764
+ const ADDITIONAL_PRODUCT_OPTIONS = [
76765
+ COMBO_JOB_DATA_TYPES.TRANSACTIONS,
76766
+ COMBO_JOB_DATA_TYPES.ACCOUNT_NUMBER
76767
+ ];
76768
+ const AdditionalProductStep = React__default.forwardRef(
76769
+ ({
76770
+ additionalProductName,
76771
+ onNoClick = () => {
76772
+ throw new Error("onNoClick not implemented");
76773
+ },
76774
+ onYesClick = () => {
76775
+ throw new Error("onYesClick not implemented");
76776
+ }
76777
+ }, navigationRef) => {
76778
+ const selectedInstitution = useSelector(getSelectedInstitution);
76779
+ useImperativeHandle(navigationRef, () => {
76780
+ return {
76781
+ showBackButton() {
76782
+ return true;
76783
+ }
76784
+ };
76785
+ }, []);
76786
+ const getNextDelay = getDelay();
76787
+ const addAggregationText = {
76788
+ title: __("Add financial management?"),
76789
+ body: __(
76790
+ "You are connecting this account for payments and transfers. Would you also like to connect it for financial management to track income and spending?"
76791
+ ),
76792
+ acceptButtonText: __("Yes, add financial management"),
76793
+ rejectButtonText: __("No, just transfers and payments")
76794
+ };
76795
+ const addVerificationText = {
76796
+ title: __("Add transfers and payments?"),
76797
+ body: __(
76798
+ "You are connecting this account for financial management. Would you also like to connect it for transfers and payments to quickly move money to and from this institution?"
76799
+ ),
76800
+ acceptButtonText: __("Yes, add transfers and payments"),
76801
+ rejectButtonText: __("No, just financial management")
76802
+ };
76803
+ const componentText = additionalProductName === COMBO_JOB_DATA_TYPES.TRANSACTIONS ? addAggregationText : addVerificationText;
76804
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(SlideDown, { delay: getNextDelay(), children: [
76805
+ /* @__PURE__ */ jsxRuntimeExports.jsx(InstitutionBlock, { institution: selectedInstitution, style: { marginBottom: 24 } }),
76806
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
76807
+ x,
76808
+ {
76809
+ component: "h2",
76810
+ "data-test": "additional-product__title-text",
76811
+ style: { marginBottom: 12 },
76812
+ truncate: false,
76813
+ variant: "H2",
76814
+ children: componentText.title
76815
+ }
76816
+ ),
76817
+ /* @__PURE__ */ jsxRuntimeExports.jsx(x, { component: "p", style: { marginBottom: 32 }, truncate: false, variant: "Paragraph", children: componentText.body }),
76818
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
76819
+ Button$2,
76820
+ {
76821
+ "data-test": "additional-product__accept-button",
76822
+ fullWidth: true,
76823
+ onClick: () => {
76824
+ onYesClick();
76825
+ },
76826
+ style: { marginBottom: 8 },
76827
+ variant: "contained",
76828
+ children: componentText.acceptButtonText
76829
+ }
76830
+ ),
76831
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
76832
+ Button$2,
76833
+ {
76834
+ "data-test": "additional-product__reject-button",
76835
+ fullWidth: true,
76836
+ onClick: () => {
76837
+ onNoClick();
76838
+ },
76839
+ variant: "text",
76840
+ children: componentText.rejectButtonText
76841
+ }
76842
+ )
76843
+ ] });
76844
+ }
76845
+ );
76846
+ AdditionalProductStep.displayName = "AdditionalProductStep";
76847
+
76677
76848
  const useSelectInstitution = () => {
76678
76849
  const { api } = useApi();
76679
76850
  const [institutionGuid, setInstitutionGuid] = useState("");
76680
76851
  const dispatch = useDispatch();
76681
76852
  const consentIsEnabled = useSelector((state) => isConsentEnabled(state));
76853
+ const connectConfig = useSelector(selectConnectConfig);
76682
76854
  const handleSelectInstitution = useCallback(
76683
76855
  (institutionGuid2) => {
76684
76856
  setInstitutionGuid(institutionGuid2);
@@ -76692,7 +76864,11 @@ const useSelectInstitution = () => {
76692
76864
  map((institution) => {
76693
76865
  return dispatch({
76694
76866
  type: ActionTypes$2.SELECT_INSTITUTION_SUCCESS,
76695
- payload: { institution, consentFlag: consentIsEnabled || false }
76867
+ payload: {
76868
+ institution,
76869
+ consentIsEnabled: consentIsEnabled || false,
76870
+ additionalProductOption: connectConfig?.additional_product_option || null
76871
+ }
76696
76872
  });
76697
76873
  }),
76698
76874
  catchError((err) => {
@@ -77102,6 +77278,7 @@ DynamicDisclosure.displayName = "DynamicDisclosure";
77102
77278
  const RenderConnectStep = (props) => {
77103
77279
  const postMessageFunctions = useContext(PostMessageContext);
77104
77280
  const connectConfig = useSelector(selectConnectConfig);
77281
+ const initialConfig = useSelector(selectInitialConfig);
77105
77282
  const uiMessageVersion = useSelector(selectUIMessageVersion);
77106
77283
  const isMobileWebview = useSelector(selectIsMobileWebView);
77107
77284
  const client = useSelector((state) => state.profiles.client);
@@ -77119,6 +77296,7 @@ const RenderConnectStep = (props) => {
77119
77296
  const selectedInstitution = useSelector(getSelectedInstitution);
77120
77297
  const updateCredentials = useSelector((state) => state.connect.updateCredentials);
77121
77298
  const verifyMemberError = useSelector((state) => state.connect.error);
77299
+ const consentIsEnabled = useSelector((state) => isConsentEnabled(state));
77122
77300
  const { handleSelectInstitution } = useSelectInstitution();
77123
77301
  const dispatch = useDispatch();
77124
77302
  const tokens = useTokens();
@@ -77181,6 +77359,37 @@ const RenderConnectStep = (props) => {
77181
77359
  ref: props.navigationRef
77182
77360
  }
77183
77361
  ) });
77362
+ } else if (step === STEPS.ADDITIONAL_PRODUCT) {
77363
+ if (!ADDITIONAL_PRODUCT_OPTIONS.includes(connectConfig?.additional_product_option)) {
77364
+ throw new Error("invalid product offer");
77365
+ }
77366
+ const onNoClick = () => {
77367
+ dispatch({
77368
+ type: ActionTypes$2.REJECT_ADDITIONAL_PRODUCT,
77369
+ payload: {
77370
+ consentIsEnabled
77371
+ }
77372
+ });
77373
+ };
77374
+ let onYesClick = null;
77375
+ if (connectConfig?.additional_product_option === COMBO_JOB_DATA_TYPES.ACCOUNT_NUMBER) {
77376
+ onYesClick = () => {
77377
+ dispatch(addVerificationData({ consentIsEnabled }));
77378
+ };
77379
+ } else if (connectConfig?.additional_product_option === COMBO_JOB_DATA_TYPES.TRANSACTIONS) {
77380
+ onYesClick = () => {
77381
+ dispatch(addAggregationData({ consentIsEnabled }));
77382
+ };
77383
+ }
77384
+ connectStepView = /* @__PURE__ */ jsxRuntimeExports.jsx(
77385
+ AdditionalProductStep,
77386
+ {
77387
+ additionalProductName: connectConfig.additional_product_option,
77388
+ onNoClick,
77389
+ onYesClick,
77390
+ ref: props.navigationRef
77391
+ }
77392
+ );
77184
77393
  } else if (step === STEPS.ADD_MANUAL_ACCOUNT) {
77185
77394
  connectStepView = /* @__PURE__ */ jsxRuntimeExports.jsx(
77186
77395
  ManualAccountConnect,
@@ -77188,7 +77397,7 @@ const RenderConnectStep = (props) => {
77188
77397
  availableAccountTypes: props.availableAccountTypes,
77189
77398
  onClose: () => dispatch({
77190
77399
  type: ActionTypes$2.GO_BACK_MANUAL_ACCOUNT,
77191
- payload: connectConfig
77400
+ payload: initialConfig
77192
77401
  }),
77193
77402
  onManualAccountAdded: props.onManualAccountAdded,
77194
77403
  ref: props.navigationRef
@@ -77277,9 +77486,8 @@ const RenderConnectStep = (props) => {
77277
77486
  }
77278
77487
  );
77279
77488
  } else if (step === STEPS.ACTIONABLE_ERROR) {
77280
- connectStepView = [ACTIONABLE_ERROR_CODES.NO_ELIGIBLE_ACCOUNTS].includes(
77281
- currentMember?.most_recent_job_detail_code ?? -1
77282
- ) ? /* @__PURE__ */ jsxRuntimeExports.jsx(ActionableError, {}) : /* @__PURE__ */ jsxRuntimeExports.jsx(
77489
+ const jobDetailCode = currentMember?.most_recent_job_detail_code ?? null;
77490
+ connectStepView = canHandleActionableError(jobDetailCode) ? /* @__PURE__ */ jsxRuntimeExports.jsx(ActionableError, {}) : /* @__PURE__ */ jsxRuntimeExports.jsx(
77283
77491
  LoginError,
77284
77492
  {
77285
77493
  institution: selectedInstitution,
@@ -77332,7 +77540,7 @@ const RenderConnectStep = (props) => {
77332
77540
  postMessageFunctions.onPostMessage(POST_MESSAGES.BACK_TO_SEARCH);
77333
77541
  dispatch({
77334
77542
  type: ActionTypes$2.DELETE_MEMBER_SUCCESS_RESET,
77335
- payload: connectConfig
77543
+ payload: initialConfig
77336
77544
  });
77337
77545
  }
77338
77546
  }
@@ -79373,6 +79581,7 @@ const Connect$2 = ({
79373
79581
  ...props
79374
79582
  }) => {
79375
79583
  const connectConfig = useSelector(selectConnectConfig);
79584
+ const initialConfig = useSelector(selectInitialConfig);
79376
79585
  const loadError = useSelector((state2) => state2.connect.loadError);
79377
79586
  const hasAtriumAPI = useSelector((state2) => state2.profiles.client.has_atrium_api);
79378
79587
  const isLoading = useSelector((state2) => state2.connect.isComponentLoading);
@@ -79380,6 +79589,10 @@ const Connect$2 = ({
79380
79589
  const step = useSelector(
79381
79590
  (state2) => state2.connect.location[state2.connect.location.length - 1]?.step ?? STEPS.SEARCH
79382
79591
  );
79592
+ const previousStep = useSelector((state2) => {
79593
+ if (state2.connect.location.length < 2) return null;
79594
+ return state2.connect.location[state2.connect.location.length - 2]?.step ?? null;
79595
+ });
79383
79596
  const uiMessageVersion = useSelector(selectUIMessageVersion);
79384
79597
  const prevProps = usePrevious({ isLoading, step, clientConfig: props.clientConfig });
79385
79598
  const { loadConnect } = useLoadConnect();
@@ -79393,6 +79606,16 @@ const Connect$2 = ({
79393
79606
  // This holds a reference to the current step component.
79394
79607
  });
79395
79608
  const consentIsEnabled = useSelector((state2) => isConsentEnabled(state2));
79609
+ const handleGoBackWithSideEffects = () => {
79610
+ const BACK_ACTION_WITH_PREV_STEP = {
79611
+ type: ActionTypes$2.CONNECT_GO_BACK,
79612
+ payload: { previousStep }
79613
+ };
79614
+ if (step === STEPS.SEARCH || step === STEPS.VERIFY_EXISTING_MEMBER) {
79615
+ postMessageFunctions.onPostMessage(POST_MESSAGES.BACK_TO_SEARCH, {});
79616
+ }
79617
+ return BACK_ACTION_WITH_PREV_STEP;
79618
+ };
79396
79619
  const dispatch = useDispatch();
79397
79620
  useEffect(() => {
79398
79621
  const [name, path] = PageviewInfo.CONNECT;
@@ -79469,7 +79692,7 @@ const Connect$2 = ({
79469
79692
  } else {
79470
79693
  dispatch({
79471
79694
  type: ActionTypes$2.GO_BACK_POST_MESSAGE,
79472
- payload: connectConfig
79695
+ payload: initialConfig
79473
79696
  });
79474
79697
  postMessageFunctions.onPostMessage("navigation", { did_go_back: true });
79475
79698
  }
@@ -79483,31 +79706,33 @@ const Connect$2 = ({
79483
79706
  if (state.returnToMicrodeposits) {
79484
79707
  dispatch(stepToMicrodeposits$1());
79485
79708
  setState({ ...state, returnToMicrodeposits: false });
79709
+ } else if (connectConfig.additional_product_option) {
79710
+ dispatch(handleGoBackWithSideEffects());
79486
79711
  } else {
79487
79712
  postMessageFunctions.onPostMessage(POST_MESSAGES.BACK_TO_SEARCH, {});
79488
- dispatch({ type: ActionTypes$2.GO_BACK_CONSENT, payload: connectConfig });
79713
+ dispatch({ type: ActionTypes$2.GO_BACK_CONSENT, payload: initialConfig });
79489
79714
  }
79490
79715
  };
79491
79716
  const _handleCredentialsGoBack = () => {
79492
79717
  if (state.returnToMicrodeposits) {
79493
79718
  dispatch(stepToMicrodeposits$1());
79494
79719
  setState({ ...state, returnToMicrodeposits: false });
79495
- } else if (consentIsEnabled) {
79496
- dispatch({ type: ActionTypes$2.CONNECT_GO_BACK });
79720
+ } else if (consentIsEnabled || connectConfig.additional_product_option) {
79721
+ dispatch(handleGoBackWithSideEffects());
79497
79722
  } else {
79498
79723
  postMessageFunctions.onPostMessage(POST_MESSAGES.BACK_TO_SEARCH, {});
79499
- dispatch({ type: ActionTypes$2.GO_BACK_CREDENTIALS, payload: connectConfig });
79724
+ dispatch({ type: ActionTypes$2.GO_BACK_CREDENTIALS, payload: initialConfig });
79500
79725
  }
79501
79726
  };
79502
79727
  const _handleOAuthGoBack = () => {
79503
79728
  if (state.returnToMicrodeposits) {
79504
79729
  dispatch(stepToMicrodeposits$1());
79505
79730
  setState({ ...state, returnToMicrodeposits: false });
79506
- } else if (consentIsEnabled) {
79507
- dispatch({ type: ActionTypes$2.CONNECT_GO_BACK });
79731
+ } else if (consentIsEnabled || connectConfig.additional_product_option) {
79732
+ dispatch(handleGoBackWithSideEffects());
79508
79733
  } else {
79509
79734
  postMessageFunctions.onPostMessage(POST_MESSAGES.BACK_TO_SEARCH, {});
79510
- dispatch({ type: ActionTypes$2.GO_BACK_OAUTH, payload: connectConfig });
79735
+ dispatch({ type: ActionTypes$2.GO_BACK_OAUTH, payload: initialConfig });
79511
79736
  }
79512
79737
  };
79513
79738
  const _handleStepDOMChange = useCallback((ref) => {
@@ -79563,7 +79788,7 @@ const Connect$2 = ({
79563
79788
  /* @__PURE__ */ jsxRuntimeExports.jsx(
79564
79789
  ConnectNavigationHeader,
79565
79790
  {
79566
- connectGoBack: () => dispatch({ type: ActionTypes$2.CONNECT_GO_BACK }),
79791
+ connectGoBack: () => dispatch(handleGoBackWithSideEffects()),
79567
79792
  stepComponentRef: state.stepComponentRef
79568
79793
  }
79569
79794
  ),
@@ -80072,6 +80297,15 @@ const frCa = {
80072
80297
  "No eligible accounts": "Aucun compte admissible",
80073
80298
  "Only checking or savings accounts can be used for transfers. If you have one at %1, make sure to select it when connecting. Otherwise, try connecting a different institution.": "Seuls les comptes chèques ou d’épargne peuvent être utilisés pour les transferts. Si vous en avez un à %1, assurez-vous de le sélectionner lors de la connexion. Sinon, essayez de connecter une autre institution.",
80074
80299
  Required: Required$1,
80300
+ "Add financial management?": "Ajouter la gestion financière ?",
80301
+ "You are connecting this account for payments and transfers. Would you also like to connect it for financial management to track income and spending?": "Vous connectez ce compte pour les paiements et les virements. Souhaitez-vous également le connecter pour la gestion financière afin de suivre vos revenus et vos dépenses ?",
80302
+ "Yes, add financial management": "Oui, ajoutez la gestion financière",
80303
+ "No, just transfers and payment": "Non, juste des virements et des paiements",
80304
+ "Add transfers and payments?": "Ajouter des transferts et des paiements ?",
80305
+ "You are connecting this account for financial management. Would you also like to connect it for transfers and payments to quickly move money to and from this institution?": "Vous connectez ce compte pour la gestion financière. Souhaitez-vous également le connecter pour effectuer des virements et des paiements afin de transférer rapidement des fonds vers et depuis cette institution ?",
80306
+ "Yes, add transfers and payments": "Oui, ajouter des transferts et des paiements",
80307
+ "No, just financial management": "Non, juste la gestion financière",
80308
+ "Select an account to connect": "Sélectionnez un compte pour vous connecter",
80075
80309
  "connect/disclosure/policy/text\u0004By clicking Continue, you agree to the ": "En cliquant sur Continuer, vous acceptez la ",
80076
80310
  "connect/disclosure/policy/link\u0004MX Privacy Policy.": "Politique de confidentialité de MX.",
80077
80311
  "connect/disclosure/policy/link\u0004MX Privacy Policy": "Politique de confidentialité de MX.",
@@ -80559,6 +80793,15 @@ const es = {
80559
80793
  "No eligible accounts": "No hay cuentas elegibles",
80560
80794
  "Only checking or savings accounts can be used for transfers. If you have one at %1, make sure to select it when connecting. Otherwise, try connecting a different institution.": "Solo se pueden usar cuentas de control o ahorro para transferencias. Si tiene uno en %1, asegúrese de seleccionarlo al conectarlo. De lo contrario, intente conectar una institución diferente.",
80561
80795
  Required: Required,
80796
+ "Add financial management?": "¿Añadir gestión financiera?",
80797
+ "You are connecting this account for payments and transfers. Would you also like to connect it for financial management to track income and spending?": "Estás conectando esta cuenta para pagos y transferencias. ¿Te gustaría conectarla también para la gestión financiera y el seguimiento de ingresos y gastos?",
80798
+ "Yes, add financial management": "Sí, añadir gestión financiera",
80799
+ "No, just transfers and payments": "No, solo transferencias y pagos",
80800
+ "Add transfers and payments?": "¿Añadir transferencias y pagos?",
80801
+ "You are connecting this account for financial management. Would you also like to connect it for transfers and payments to quickly move money to and from this institution?": "Estás conectando esta cuenta para la gestión financiera. ¿Te gustaría conectarla también para transferencias y pagos para transferir dinero rápidamente desde y hacia esta institución?",
80802
+ "Yes, add transfers and payments": "Sí, añadir transferencias y pagos",
80803
+ "No, just financial management": "No, sólo gestión financiera",
80804
+ "Select an account to connect": "Seleccione una cuenta para conectarse",
80562
80805
  "connect/disclosure/button\u0004Continue": "Continuar",
80563
80806
  "connect/disclosure/policy/text\u0004By clicking Continue, you agree to the ": "Al hacer clic en Continuar, tu aceptas la ",
80564
80807
  "connect/disclosure/policy/link\u0004MX Privacy Policy.": "Política de privacidad de Money Experience.",