{"version":3,"file":"SMSOTPEntryScreen.mjs","sources":["../../../../../../../../../web/src/ui/b2b/screens/SMSOTPEntryScreen.tsx"],"sourcesContent":["import { useLingui } from '@lingui/react/macro';\nimport {\n  B2BMFAProducts,\n  B2BSMSAuthenticateResponse,\n  B2BSMSSendResponse,\n  StytchAPIError,\n  StytchProjectConfigurationInput,\n} from '@stytch/core/public';\nimport React, { useEffect, useMemo } from 'react';\n\nimport { getTranslatedError } from '../../../utils/getTranslatedError';\nimport { formatNumber } from '../../../utils/handleParsePhoneNumber';\nimport { readB2BInternals } from '../../../utils/internal';\nimport Button from '../../components/atoms/Button';\nimport Column from '../../components/atoms/Column';\nimport { useCountdown } from '../../components/atoms/Countdown';\nimport { errorToast } from '../../components/atoms/Toast';\nimport ButtonColumn from '../../components/molecules/ButtonColumn';\nimport { LoadingScreen } from '../../components/molecules/Loading';\nimport { ResendOTPButton } from '../../components/organisms/ResendOTPButton';\nimport { SentOTPEntry } from '../../components/organisms/SentOTPEntry';\nimport { useConfig, useGlobalReducer, useStytch } from '../GlobalContextProvider';\nimport { AppScreens } from '../types/AppScreens';\nimport { StytchMutationKey, useMutate } from '../utils';\n\nexport const SMSOTPEntryScreen = () => {\n  const stytchClient = useStytch();\n  const {\n    sessionOptions: { sessionDurationMinutes },\n    smsOtpOptions,\n  } = useConfig();\n  const { t } = useLingui();\n\n  const [state, dispatch] = useGlobalReducer();\n  const {\n    mfa: { isEnrolling, smsOtp, primaryInfo },\n  } = state;\n\n  const { codeExpiration, formattedDestination } = smsOtp;\n\n  // This screen should only be shown if primary info is available\n  const { enrolledMfaMethods, memberId, memberPhoneNumber, organizationId, organizationMfaOptionsSupported } =\n    primaryInfo!;\n\n  const resendCountdown = useCountdown();\n\n  const {\n    trigger: sendSms,\n    isMutating: isSending,\n    error: sendError,\n  } = useMutate<\n    B2BSMSSendResponse,\n    unknown,\n    StytchMutationKey,\n    { memberId: string; organizationId: string; locale?: string }\n  >(\n    'stytch.otps.sms.send',\n    (\n      _: string,\n      {\n        arg: { memberId, organizationId, locale },\n      }: { arg: { memberId: string; organizationId: string; locale?: string } },\n    ) => {\n      dispatch({ type: 'sms_otp/send' });\n      return stytchClient.otps.sms.send({ member_id: memberId, organization_id: organizationId, locale });\n    },\n    {\n      onSuccess: (response) => {\n        dispatch({ type: 'sms_otp/send_success', response });\n      },\n      onError: (error) => {\n        const message = getTranslatedError(error as StytchAPIError, t);\n        if (message) {\n          errorToast({ message });\n        }\n        dispatch({ type: 'sms_otp/send_error', error: message });\n      },\n      // Throw on error to ensure promise is rejected\n      throwOnError: true,\n    },\n  );\n\n  const {\n    trigger: authenticate,\n    isMutating: isAuthenticating,\n    error: authenticateError,\n  } = useMutate<\n    B2BSMSAuthenticateResponse<StytchProjectConfigurationInput>,\n    unknown,\n    StytchMutationKey,\n    { otp: string; memberId: string; organizationId: string; sessionDurationMinutes: number }\n  >(\n    'stytch.otps.sms.authenticate',\n    (\n      _: string,\n      {\n        arg: { otp, memberId, organizationId, sessionDurationMinutes },\n      }: { arg: { otp: string; memberId: string; organizationId: string; sessionDurationMinutes: number } },\n    ) =>\n      stytchClient.otps.sms.authenticate({\n        code: otp,\n        member_id: memberId,\n        organization_id: organizationId,\n        session_duration_minutes: sessionDurationMinutes,\n      }),\n    {\n      onSuccess: () => {\n        dispatch({ type: 'sms_otp/authenticate_success' });\n      },\n      onError: () => {\n        resendCountdown.clear();\n      },\n    },\n  );\n\n  const shouldCreate = codeExpiration === null && !isSending && !sendError;\n  useEffect(() => {\n    if (shouldCreate) {\n      sendSms({ memberId, organizationId, locale: smsOtpOptions?.locale }).catch(() => {\n        // error in the UI is handled through the error object so we just swallow it here when auto-sending\n      });\n    }\n  }, [memberId, organizationId, sendSms, shouldCreate, smsOtpOptions?.locale]);\n\n  useEffect(() => {\n    if (!formattedDestination && memberPhoneNumber) {\n      const handleFormatNumber = async () => {\n        const parsePhoneNumber = (phoneNumber: string) =>\n          readB2BInternals(stytchClient).clientsideServices.parsedPhoneNumber({\n            phoneNumber,\n          });\n\n        const national = await formatNumber({\n          parsePhoneNumber,\n          phoneNumber: memberPhoneNumber,\n        });\n\n        dispatch({\n          type: 'sms_otp/format_destination',\n          formattedPhoneNumber: national,\n        });\n      };\n\n      handleFormatNumber();\n    }\n  }, [dispatch, formattedDestination, stytchClient, memberPhoneNumber]);\n\n  const isTotpAvailable = useMemo(\n    () =>\n      !isEnrolling &&\n      enrolledMfaMethods.includes(B2BMFAProducts.totp) &&\n      (organizationMfaOptionsSupported.length === 0 || organizationMfaOptionsSupported.includes(B2BMFAProducts.totp)),\n    [enrolledMfaMethods, isEnrolling, organizationMfaOptionsSupported],\n  );\n  const errorMessage = authenticateError\n    ? t({ id: 'error.passcodeInvalid', message: 'Invalid passcode, please try again.' })\n    : undefined;\n\n  // The user can go back to change their phone number if either:\n  // - we are in an enrollment flow\n  // - they are not enrolled in any MFA methods at all\n  // - they are not enrolled in any of the limited MFA methods supported by the organization\n  const canGoBack = useMemo(\n    () =>\n      isEnrolling ||\n      enrolledMfaMethods.length === 0 ||\n      (organizationMfaOptionsSupported.length > 0 &&\n        !enrolledMfaMethods.some((enrolledMethod) => organizationMfaOptionsSupported.includes(enrolledMethod))),\n    [enrolledMfaMethods, isEnrolling, organizationMfaOptionsSupported],\n  );\n\n  const handleSubmit = (otp: string) => {\n    authenticate({ otp, memberId, organizationId, sessionDurationMinutes });\n  };\n\n  const handleSwitchToTotp = () => {\n    dispatch({ type: 'transition', history: 'push', screen: AppScreens.TOTPEntry });\n  };\n\n  const handleResendOTP = async () => {\n    await sendSms({ memberId, organizationId, locale: smsOtpOptions?.locale });\n  };\n\n  const handleBack = () => {\n    dispatch({ type: 'navigate_back' });\n  };\n\n  const resendButton = (\n    <ResendOTPButton countdown={resendCountdown} isSubmitting={isAuthenticating} resendOTP={handleResendOTP} />\n  );\n  const switchToTotpButton = isTotpAvailable && (\n    <Button variant=\"ghost\" onClick={handleSwitchToTotp}>\n      {t({ id: 'mfa.methods.authenticatorApp', message: 'Use an authenticator app' })}\n    </Button>\n  );\n  const backButton = canGoBack && (\n    <Button variant=\"ghost\" onClick={handleBack}>\n      {t({ id: 'button.goBack', message: 'Go back' })}\n    </Button>\n  );\n\n  return (\n    <Column gap={6}>\n      {codeExpiration !== null ? (\n        <SentOTPEntry\n          isSubmitting={isAuthenticating}\n          onSubmit={handleSubmit}\n          errorMessage={errorMessage}\n          expiration={codeExpiration.getTime()}\n          formattedDestination={formattedDestination ?? memberPhoneNumber ?? ''}\n        />\n      ) : (\n        <LoadingScreen />\n      )}\n\n      {switchToTotpButton && backButton ? (\n        <ButtonColumn\n          top={resendButton}\n          bottom={\n            <>\n              {switchToTotpButton}\n              {backButton}\n            </>\n          }\n        />\n      ) : (\n        <ButtonColumn>\n          {resendButton}\n          {switchToTotpButton}\n          {backButton}\n        </ButtonColumn>\n      )}\n    </Column>\n  );\n};\n"],"names":["SMSOTPEntryScreen","stytchClient","useStytch","sessionOptions","sessionDurationMinutes","smsOtpOptions","useConfig","useLingui","state","dispatch","useGlobalReducer","mfa","isEnrolling","smsOtp","primaryInfo","codeExpiration","formattedDestination","enrolledMfaMethods","memberId","memberPhoneNumber","organizationId","organizationMfaOptionsSupported","resendCountdown","useCountdown","trigger","sendSms","isMutating","isSending","error","sendError","useMutate","_","arg","locale","type","otps","sms","send","member_id","organization_id","onSuccess","response","onError","message","getTranslatedError","errorToast","throwOnError","authenticate","isAuthenticating","authenticateError","otp","code","session_duration_minutes","clear","shouldCreate","useEffect","catch","handleFormatNumber","parsePhoneNumber","phoneNumber","readB2BInternals","clientsideServices","parsedPhoneNumber","national","formatNumber","formattedPhoneNumber","isTotpAvailable","useMemo","includes","B2BMFAProducts","totp","length","errorMessage","undefined","canGoBack","some","enrolledMethod","handleSubmit","handleSwitchToTotp","history","screen","AppScreens","TOTPEntry","handleResendOTP","handleBack","resendButton","React","ResendOTPButton","countdown","isSubmitting","resendOTP","switchToTotpButton","Button","variant","onClick","backButton","Column","gap","SentOTPEntry","onSubmit","expiration","getTime","LoadingScreen","ButtonColumn","top","bottom"],"mappings":"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"}