{"version":3,"file":"SMSOTPEnrollScreen.mjs","sources":["../../../../../../../../../web/src/ui/b2b/screens/SMSOTPEnrollScreen.tsx"],"sourcesContent":["import { useLingui } from '@lingui/react/macro';\nimport { COUNTRIES_LIST, CountryCode } from '@stytch/core';\nimport { B2BSMSSendResponse, StytchAPIError, StytchSDKError } from '@stytch/core/public';\nimport React, { FormEvent } from 'react';\n\nimport { getTranslatedError } from '../../../utils/getTranslatedError';\nimport { formatNumberToIncludeCountryCode } from '../../../utils/handleParsePhoneNumber';\nimport { readB2BInternals } from '../../../utils/internal';\nimport Button from '../../components/atoms/Button';\nimport Column from '../../components/atoms/Column';\nimport Typography from '../../components/atoms/Typography';\nimport ButtonColumn from '../../components/molecules/ButtonColumn';\nimport PhoneInput, { getPhoneNumberProps } from '../../components/molecules/PhoneInput';\nimport { useConfig, useGlobalReducer, useStytch } from '../GlobalContextProvider';\nimport { canGoBack } from '../reducer/navigation';\nimport { StytchMutationKey, useMutate } from '../utils';\n\n// eslint-disable-next-line lingui/no-unlocalized-strings\nconst DEFAULT_COUNTRY_CODE = 'US' satisfies CountryCode;\n\n/**\n * Thrown when the user provides a phone number that cannot be parsed.\n */\nclass InvalidPhoneNumberError extends StytchSDKError {\n  constructor() {\n    // eslint-disable-next-line lingui/no-unlocalized-strings\n    super('InvalidPhoneNumberError', 'Invalid phone number');\n  }\n}\n\nexport const SMSOTPEnrollScreen = () => {\n  const stytchClient = useStytch();\n  const [state, dispatch] = useGlobalReducer();\n  const { t } = useLingui();\n  const { smsOtpOptions } = useConfig();\n  const {\n    mfa: {\n      smsOtp: { isSending, sendError, enrolledNumber },\n    },\n  } = state;\n\n  // This screen should only be shown if primary info is available\n  const { memberId, organizationId } = state.mfa.primaryInfo!;\n\n  const [countryCode, setCountryCode] = React.useState<CountryCode>(\n    enrolledNumber?.countryCode ?? DEFAULT_COUNTRY_CODE,\n  );\n  const [phoneNumber, setPhoneNumber] = React.useState(enrolledNumber?.phoneNumber ?? '');\n\n  const errorMessage = React.useMemo(() => {\n    if (!sendError) return undefined;\n\n    if (sendError instanceof InvalidPhoneNumberError) {\n      return t({\n        id: 'error.invalidPhoneNumber',\n        message: 'Phone number format is invalid. Ensure the phone number is in the E.164 format.',\n      });\n    }\n\n    return getTranslatedError(sendError as StytchAPIError, t);\n  }, [sendError, t]);\n\n  const { parsePhoneNumber, getExampleNumber } = getPhoneNumberProps(readB2BInternals(stytchClient).clientsideServices);\n\n  const { trigger: sendSms } = useMutate<\n    B2BSMSSendResponse,\n    unknown,\n    StytchMutationKey,\n    { parsedNumber: string; locale?: string }\n  >(\n    'stytch.otps.sms.send',\n    async (_: string, { arg: { parsedNumber, locale } }: { arg: { parsedNumber: string; locale?: string } }) => {\n      return stytchClient.otps.sms.send({\n        mfa_phone_number: parsedNumber,\n        member_id: memberId,\n        organization_id: organizationId,\n        locale: locale,\n      });\n    },\n    {\n      onSuccess: (response) => {\n        dispatch({\n          type: 'sms_otp/send_success',\n          response,\n          countryCode,\n          phoneNumber,\n          formattedPhoneNumber: `+${COUNTRIES_LIST[countryCode]} ${phoneNumber}`,\n        });\n      },\n      onError: (error) => {\n        dispatch({\n          type: 'sms_otp/send_error',\n          error,\n        });\n      },\n    },\n  );\n\n  const handleSubmit = async (e: FormEvent) => {\n    e.preventDefault();\n\n    dispatch({ type: 'sms_otp/send' });\n    try {\n      // We parse the phone number here (rather than inside `sendSms`) because we\n      // don't want validation errors to be surfaced through the global error\n      // callback\n\n      const parsedNumber = await formatNumberToIncludeCountryCode({\n        parsePhoneNumber,\n        phoneNumber,\n        country: countryCode,\n      });\n\n      if (!parsedNumber.isValid) {\n        throw new InvalidPhoneNumberError();\n      }\n\n      await sendSms({ parsedNumber: parsedNumber.number, locale: smsOtpOptions?.locale });\n    } catch (error) {\n      dispatch({\n        type: 'sms_otp/send_error',\n        error,\n      });\n    }\n  };\n\n  return (\n    <Column as=\"form\" gap={6} onSubmit={handleSubmit}>\n      <Typography variant=\"header\">\n        {t({\n          id: 'mfa.smsEnrollment.title',\n          message: 'Enter your phone number to set up Multi-Factor Authentication',\n        })}\n      </Typography>\n\n      <Typography variant=\"body\">\n        {t({\n          id: 'mfa.smsEnrollment.content',\n          message: 'Your organization requires an additional form of verification to make your account more secure.',\n        })}\n      </Typography>\n\n      <PhoneInput\n        country={countryCode}\n        setCountry={setCountryCode}\n        phone={phoneNumber}\n        setPhone={setPhoneNumber}\n        parsePhoneNumber={parsePhoneNumber}\n        getExampleNumber={getExampleNumber}\n        error={errorMessage}\n      />\n\n      <ButtonColumn>\n        <Button variant=\"primary\" loading={isSending} type=\"submit\" disabled={!phoneNumber || isSending}>\n          {t({ id: 'button.continue', message: 'Continue' })}\n        </Button>\n        {canGoBack(state) && (\n          <Button variant=\"ghost\" onClick={() => dispatch({ type: 'navigate_back' })}>\n            {t({ id: 'button.goBack', message: 'Go back' })}\n          </Button>\n        )}\n      </ButtonColumn>\n    </Column>\n  );\n};\n"],"names":["DEFAULT_COUNTRY_CODE","InvalidPhoneNumberError","StytchSDKError","SMSOTPEnrollScreen","stytchClient","useStytch","state","dispatch","useGlobalReducer","useLingui","smsOtpOptions","useConfig","mfa","smsOtp","isSending","sendError","enrolledNumber","memberId","organizationId","primaryInfo","countryCode","setCountryCode","React","useState","phoneNumber","setPhoneNumber","errorMessage","useMemo","undefined","getTranslatedError","parsePhoneNumber","getExampleNumber","getPhoneNumberProps","readB2BInternals","clientsideServices","trigger","sendSms","useMutate","_","arg","parsedNumber","locale","otps","sms","send","mfa_phone_number","member_id","organization_id","onSuccess","response","type","formattedPhoneNumber","COUNTRIES_LIST","onError","error","handleSubmit","e","preventDefault","formatNumberToIncludeCountryCode","country","isValid","number","Column","as","gap","onSubmit","Typography","variant","PhoneInput","setCountry","phone","setPhone","ButtonColumn","Button","loading","disabled","canGoBack","onClick"],"mappings":"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"}