@truworth/twc-auth 1.2.4 → 1.2.5

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.
Files changed (80) hide show
  1. package/README.md +1 -4
  2. package/build/src/api/axiosClient/index.js +1 -1
  3. package/build/src/api/axiosClient/index.native.js +1 -1
  4. package/build/src/components/VerifyMobileOTP/index.js +8 -6
  5. package/build/src/components/VerifyMobileOTP/index.native.js +6 -11
  6. package/build/src/constants/base-url/index.js +5 -0
  7. package/build/src/constants/base-url/index.native.js +1 -0
  8. package/build/src/constants/cdn-url/index.js +2 -1
  9. package/build/src/contexts/AuthContext.js +3 -1
  10. package/build/src/enums/loginMethod.enum.js +1 -1
  11. package/build/src/navigator/index.native.js +5 -1
  12. package/build/src/screens/EnterEmail/hooks/internal/useEnterEmail.js +50 -40
  13. package/build/src/screens/EnterEmail/index.js +8 -10
  14. package/build/src/screens/EnterEmail/index.native.js +6 -9
  15. package/build/src/screens/EnterMobile/components/ExistingAccountsSheet/hooks/internal/useExistingAccountsSheet.js +36 -0
  16. package/build/src/screens/EnterMobile/components/ExistingAccountsSheet/index.js +33 -0
  17. package/build/src/screens/EnterMobile/components/ExistingAccountsSheet/index.native.js +73 -0
  18. package/build/src/screens/EnterMobile/components/ExistingAccountsSheet/types.js +1 -0
  19. package/build/src/screens/EnterMobile/hooks/internal/useEnterMobile.js +67 -0
  20. package/build/src/screens/EnterMobile/index.js +82 -0
  21. package/build/src/screens/EnterMobile/index.native.js +56 -0
  22. package/build/src/screens/EnterMobile/types.js +1 -0
  23. package/build/src/screens/EnterPassword/hooks/internal/useEnterPassword.js +42 -31
  24. package/build/src/screens/EnterPassword/index.js +6 -6
  25. package/build/src/screens/EnterPassword/index.native.js +5 -10
  26. package/build/src/screens/Login/components/LoginWebComponent/index.js +4 -1
  27. package/build/src/screens/LoginWithEmailOTP/hooks/internal/useLoginWithEmailOTP.js +8 -5
  28. package/build/src/screens/LoginWithMobileOTP/hooks/internal/useLoginWithMobileOTP.js +71 -0
  29. package/build/src/screens/LoginWithMobileOTP/index.js +8 -0
  30. package/build/src/screens/LoginWithMobileOTP/index.native.js +10 -0
  31. package/build/src/screens/SSOLogin/AuthenticationMethods/index.js +9 -8
  32. package/build/src/screens/SSOLogin/AuthenticationMethods/index.native.js +2 -6
  33. package/build/src/screens/SignUp/components/SignUpForm/index.js +20 -5
  34. package/build/src/screens/SignUp/components/SignUpWebComponent/index.js +1 -1
  35. package/build/src/screens/SignUp/index.native.js +14 -13
  36. package/build/src/screens/UserConsent/index.js +1 -1
  37. package/build/src/screens/VerifyLinkPrimaryAccountEmailOTP/hooks/internal/useVerifyLinkPrimaryAccountEmailOTP.js +73 -0
  38. package/build/src/screens/VerifyLinkPrimaryAccountEmailOTP/index.js +8 -0
  39. package/build/src/screens/VerifyLinkPrimaryAccountEmailOTP/index.native.js +14 -0
  40. package/build/src/screens/VerifyLinkPrimaryAccountEmailOTP/types.js +1 -0
  41. package/build/src/screens/VerifyLinkPrimaryAccountMobileOTP/hooks/internal/useVerifyLinkPrimaryAccountMobileOTP.js +82 -0
  42. package/build/src/screens/VerifyLinkPrimaryAccountMobileOTP/index.js +8 -0
  43. package/build/src/screens/VerifyLinkPrimaryAccountMobileOTP/index.native.js +10 -0
  44. package/build/src/screens/VerifyLinkPrimaryAccountMobileOTP/types.js +1 -0
  45. package/build/src/screens/Welcome/index.js +3 -2
  46. package/build/types/components/VerifyMobileOTP/index.d.ts +1 -1
  47. package/build/types/components/VerifyMobileOTP/types.d.ts +0 -1
  48. package/build/types/constants/base-url/index.d.ts +1 -0
  49. package/build/types/constants/base-url/index.native.d.ts +1 -0
  50. package/build/types/constants/cdn-url/index.d.ts +2 -1
  51. package/build/types/contexts/AuthContext.d.ts +2 -1
  52. package/build/types/contexts/type.d.ts +3 -0
  53. package/build/types/enums/loginMethod.enum.d.ts +1 -1
  54. package/build/types/navigator/index.native.d.ts +14 -0
  55. package/build/types/screens/EnterEmail/hooks/internal/useEnterEmail.d.ts +11 -14
  56. package/build/types/screens/EnterEmail/types.d.ts +6 -1
  57. package/build/types/screens/EnterMobile/components/ExistingAccountsSheet/hooks/internal/useExistingAccountsSheet.d.ts +13 -0
  58. package/build/types/screens/EnterMobile/components/ExistingAccountsSheet/index.d.ts +3 -0
  59. package/build/types/screens/EnterMobile/components/ExistingAccountsSheet/index.native.d.ts +3 -0
  60. package/build/types/screens/EnterMobile/components/ExistingAccountsSheet/types.d.ts +28 -0
  61. package/build/types/screens/EnterMobile/hooks/internal/useEnterMobile.d.ts +15 -0
  62. package/build/types/screens/EnterMobile/index.d.ts +4 -0
  63. package/build/types/screens/EnterMobile/index.native.d.ts +4 -0
  64. package/build/types/screens/EnterMobile/types.d.ts +44 -0
  65. package/build/types/screens/EnterPassword/hooks/internal/useEnterPassword.d.ts +8 -8
  66. package/build/types/screens/LoginWithEmailOTP/hooks/internal/useLoginWithEmailOTP.d.ts +1 -1
  67. package/build/types/screens/LoginWithMobileOTP/hooks/internal/useLoginWithMobileOTP.d.ts +11 -0
  68. package/build/types/screens/LoginWithMobileOTP/index.d.ts +5 -0
  69. package/build/types/screens/LoginWithMobileOTP/index.native.d.ts +4 -0
  70. package/build/types/screens/SSOLogin/AuthenticationMethods/index.d.ts +1 -1
  71. package/build/types/screens/SSOLogin/AuthenticationMethods/types.d.ts +1 -0
  72. package/build/types/screens/VerifyLinkPrimaryAccountEmailOTP/hooks/internal/useVerifyLinkPrimaryAccountEmailOTP.d.ts +15 -0
  73. package/build/types/screens/VerifyLinkPrimaryAccountEmailOTP/index.d.ts +3 -0
  74. package/build/types/screens/VerifyLinkPrimaryAccountEmailOTP/index.native.d.ts +4 -0
  75. package/build/types/screens/VerifyLinkPrimaryAccountEmailOTP/types.d.ts +14 -0
  76. package/build/types/screens/VerifyLinkPrimaryAccountMobileOTP/hooks/internal/useVerifyLinkPrimaryAccountMobileOTP.d.ts +17 -0
  77. package/build/types/screens/VerifyLinkPrimaryAccountMobileOTP/index.d.ts +3 -0
  78. package/build/types/screens/VerifyLinkPrimaryAccountMobileOTP/index.native.d.ts +4 -0
  79. package/build/types/screens/VerifyLinkPrimaryAccountMobileOTP/types.d.ts +5 -0
  80. package/package.json +1 -5
package/README.md CHANGED
@@ -70,7 +70,6 @@ Truworth Auth Module - A comprehensive authentication solution for React Native
70
70
  | react | >=18.2.0 |
71
71
  | react-native | >=0.74.5 |
72
72
  | react-native-fast-image | >=8.6.3 |
73
- | react-native-freshchat-sdk | >=4.6.6 |
74
73
  | react-native-gesture-handler | >=2.16.0 |
75
74
  | react-native-linear-gradient | >=2.8.3 |
76
75
  | react-native-modalize | >=2.1.1 |
@@ -80,13 +79,12 @@ Truworth Auth Module - A comprehensive authentication solution for React Native
80
79
  | react-native-svg | >=15.8.0 |
81
80
  | react-native-vector-icons | >=9.2.0 |
82
81
 
83
- > Note: lottie-react-native, react-native-fast-image, and react-native-freshchat-sdk are optional and only needed if your app uses features that depend on them.
82
+ > Note: lottie-react-native, react-native-fast-image are optional and only needed if your app uses features that depend on them.
84
83
 
85
84
  #### Web Dependencies
86
85
 
87
86
  | Package | Version |
88
87
  | ------------------------ | -------- |
89
- | @truworth/twc-web-common | ^1.0.11 |
90
88
  | @truworth/twc-web-design | ^1.9.0 |
91
89
  | antd | ^5.6.3 |
92
90
  | framer-motion | ^12.6.2 |
@@ -108,7 +106,6 @@ Truworth Auth Module - A comprehensive authentication solution for React Native
108
106
  ```bash
109
107
  npm install \
110
108
  next@^15.0.4 \
111
- @truworth/twc-web-common@^1.0.11 \
112
109
  @truworth/twc-web-design@^1.9.0 \
113
110
  antd@^5.6.3 \
114
111
  framer-motion@^12.6.2 \
@@ -1,4 +1,4 @@
1
- import { BASE_URL } from "@truworth/twc-web-common";
1
+ import { BASE_URL } from '../../constants/base-url';
2
2
  import axios from "axios";
3
3
  export const axiosClient = axios.create({
4
4
  baseURL: BASE_URL,
@@ -1,4 +1,4 @@
1
- import { BASE_URL } from '@truworth/twc-rn-common';
1
+ import { BASE_URL } from "../../constants/base-url";
2
2
  import axios from 'axios';
3
3
  export const axiosClient = axios.create({
4
4
  baseURL: BASE_URL,
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState, useEffect } from "react";
3
3
  import { Button, Flex, OTPInput, Typography } from "@truworth/twc-web-design";
4
- const VerifyMobileOTP = ({ validateOTP, timer, resendOTP, phone, status, resendTextClassName }) => {
4
+ const VerifyMobileOTP = ({ validateOTP, timer, resendOTP, phone, status }) => {
5
5
  const [otp, setOtp] = useState('');
6
6
  const [otpError, setOtpError] = useState(false);
7
7
  useEffect(() => {
@@ -10,14 +10,16 @@ const VerifyMobileOTP = ({ validateOTP, timer, resendOTP, phone, status, resendT
10
10
  setOtp('');
11
11
  }
12
12
  }, [status]);
13
- const defaultPhoneDisplayText = (_jsxs(Typography, { type: 'body', size: 'large', className: 'mb-6 text-gray-400 text-center', children: ["OTP sent to", _jsx("span", { className: 'pl-2 text-secondary-dark', children: phone ? `XXXXXXX${phone.slice(-3)}` : 'your registered mobile number' })] }));
14
- return (_jsxs(_Fragment, { children: [defaultPhoneDisplayText, _jsx(OTPInput, { value: otp, onChange: (code) => {
13
+ return (_jsxs(_Fragment, { children: [_jsxs(Typography, { type: 'body', size: 'large', className: 'mb-6 text-gray-400 text-center', children: ["OTP sent to", _jsx("span", { className: 'pl-2 text-secondary-dark', children: phone ? `XXXXXXX${phone.slice(-3)}` : 'your registered mobile number' })] }), _jsx(OTPInput, { value: otp, onChange: (code) => {
15
14
  setOtp(code);
16
15
  setOtpError(false);
17
16
  }, error: otpError, maxLength: 6, className: `!w-auto ${otpError ? '!border-destructive' : ''}` }), otpError &&
18
- _jsx(Typography, { type: "utility", size: "medium", className: "mt-4", color: "text-utility-danger-main", children: "Please enter the correct OTP." }), (timer <= 0) ?
19
- _jsxs(Flex, { justify: 'between', align: 'center', className: 'mt-4', children: [_jsx(Typography, { type: 'utility', size: 'medium', className: resendTextClassName, children: "Didn't receive OTP?" }), _jsx(Button, { label: 'Resend Code', size: 'small', variant: 'link', onClick: () => resendOTP() })] })
17
+ _jsx(Typography, { type: "utility", size: "medium", className: "mt-4", color: "text-utility-danger-main", children: "Please enter the correct OTP." }), timer <= 0 ?
18
+ _jsxs(Flex, { justify: 'between', align: 'center', className: 'mt-4', children: [_jsx(Typography, { type: 'utility', size: 'medium', children: "Didn't receive OTP?" }), _jsx(Button, { label: 'Re-send OTP', size: 'small', variant: 'link', onClick: () => {
19
+ setOtp('');
20
+ resendOTP();
21
+ } })] })
20
22
  :
21
- _jsxs(Typography, { type: 'utility', size: 'medium', className: `mt-3 ${resendTextClassName}`, children: ["Resend Code in ", timer > 0 ? `${timer} seconds` : 'OTP expired'] }), _jsx(Button, { label: "Continue", isFullWidth: true, onClick: () => validateOTP?.(otp), disabled: otp ? otp?.length < 6 : true, className: "mt-6" })] }));
23
+ _jsxs(Typography, { type: 'utility', size: 'medium', className: 'mt-3', children: ["Resend Code in ", timer, " seconds"] }), _jsx(Button, { label: "Continue", isFullWidth: true, onClick: () => validateOTP?.(otp), disabled: otp ? otp?.length < 6 : true, className: "mt-6" })] }));
22
24
  };
23
25
  export { VerifyMobileOTP };
@@ -8,30 +8,25 @@ import { OTPStatusLabel } from '../OTPStatusLabel/index.native';
8
8
  import OTPInputView from '@twotalltotems/react-native-otp-input';
9
9
  const { gray } = Colors;
10
10
  const VerifyMobileOTP = ({ validateOTP, timer, status, resendOTP, phone }) => {
11
- const [otp, setOTP] = useState('');
11
+ const [otp, setOtp] = useState('');
12
12
  const { otpValue } = useAuthPackageContext();
13
- useEffect(() => {
14
- if (otp?.length === 6) {
15
- validateOTP(otp);
16
- }
17
- }, [otp]);
18
13
  useEffect(() => {
19
14
  if (otpValue && otpValue.length == 6) {
20
- setOTP(otpValue);
15
+ setOtp(otpValue);
21
16
  }
22
17
  }, [otpValue]);
23
18
  return (_jsxs(Layout, { style: { flex: 1, backgroundColor: '#FFFFFF' }, children: [_jsx(Header, {}), _jsxs(CustomKeyboardAvoidingView, { behavior: Platform.OS === 'ios' ? 'padding' : undefined, keyboardVerticalOffset: 0, children: [_jsxs(ScrollView, { style: { paddingHorizontal: 20, paddingTop: 32, flex: 1 }, children: [_jsxs(Text, { textBreakStrategy: 'simple', style: {
24
19
  fontSize: 20, fontWeight: '600', color: gray.gray_900,
25
20
  lineHeight: 32, marginBottom: 32,
26
- }, children: ["OTP sent to ", '\n', phone ? phone.replace(/\d(?=\d{4})/g, 'x') : ''] }), _jsx(View, { style: { justifyContent: 'center', flexDirection: 'row', marginBottom: 30, position: 'relative' }, children: _jsx(OTPInputView, { pinCount: 6, autoFocusOnLoad: false, onCodeChanged: text => setOTP(text), codeInputFieldStyle: {
21
+ }, children: ["OTP sent to ", '\n', phone ? phone.replace(/\d(?=\d{4})/g, 'x') : ''] }), _jsx(View, { style: { justifyContent: 'center', flexDirection: 'row', marginBottom: 30, position: 'relative' }, children: _jsx(OTPInputView, { pinCount: 6, autoFocusOnLoad: false, onCodeChanged: text => setOtp(text), codeInputFieldStyle: {
27
22
  fontSize: 20, color: 'black', width: 30,
28
23
  height: 45, borderWidth: 0, borderBottomWidth: 1,
29
24
  }, codeInputHighlightStyle: { borderColor: '#03DAC6' }, style: {
30
25
  height: 50,
31
26
  width: Dimensions.get('window').width - 100,
32
- }, code: otp ?? '', onCodeFilled: code => setOTP(code) }) }), timer <= 0 &&
33
- _jsxs(View, { style: { flexDirection: 'row', alignItems: 'center' }, children: [_jsxs(Text, { style: { fontSize: 12, color: '#000', fontWeight: '400', opacity: 0.5 }, children: ["Did not receive OTP?", ' '] }), _jsx(TouchableOpacity, { disabled: timer > 0, onPress: () => {
34
- setOTP('');
27
+ }, code: otp ?? '', onCodeFilled: code => validateOTP(code) }) }), timer <= 0 &&
28
+ _jsxs(View, { style: { flexDirection: 'row', alignItems: 'center' }, children: [_jsx(Text, { style: { fontSize: 12, color: '#000', fontWeight: '400', opacity: 0.5 }, children: "Did not receive OTP?" }), _jsx(TouchableOpacity, { disabled: timer > 0, onPress: () => {
29
+ setOtp('');
35
30
  resendOTP();
36
31
  }, children: _jsx(Text, { style: { fontSize: 14, color: '#2cbaa4', fontWeight: '400', opacity: 1 }, children: "Re-send OTP" }) })] })] }), _jsx(View, { style: { width: '100%' }, children: _jsx(OTPStatusLabel, { status: status, timer: timer }) })] })] }));
37
32
  };
@@ -0,0 +1,5 @@
1
+ const baseUrl = process.env.NEXT_PUBLIC_TWC_API_BASE_URL;
2
+ if (!baseUrl) {
3
+ throw new Error('NEXT_PUBLIC_TWC_API_BASE_URL environment variable is required');
4
+ }
5
+ export const BASE_URL = baseUrl;
@@ -0,0 +1 @@
1
+ export const BASE_URL = process.env.BASE_URL;
@@ -1 +1,2 @@
1
- export { MEMBER_IMAGES_URL } from "@truworth/twc-web-common";
1
+ export const MEMBER_IMAGES_URL = process.env.NEXT_PUBLIC_MEMBER_IMAGES_URL;
2
+ export const CDN_IMAGES_URL = process.env.NEXT_PUBLIC_CDN_IMAGES_URL;
@@ -31,8 +31,9 @@ const AuthPackageContext = React.createContext(null);
31
31
  * @param onLogout - Optional callback after successful logout
32
32
  * @param onLaunchAuthSession - Optional callback after successfully launching the auth session. For example, it can be used to set the Firebase notification token or request Android permissions.
33
33
  * @param onRefreshSession - Optional handler for refreshing user session
34
+ * @param openChatSupport - Optional callback to open chat support
34
35
  */
35
- const AuthProvider = ({ children, LogoComponent, session, appConfig, onLogin, onLogout, onLaunchAuthSession, onRefreshSession }) => {
36
+ const AuthProvider = ({ children, LogoComponent, session, appConfig, onLogin, onLogout, onLaunchAuthSession, onRefreshSession, openChatSupport }) => {
36
37
  const [isLoadingProfile, setIsLoadingProfile] = useState(false);
37
38
  const [profile, setProfile] = useState(null);
38
39
  const [client, setClient] = useState(null);
@@ -177,6 +178,7 @@ const AuthProvider = ({ children, LogoComponent, session, appConfig, onLogin, on
177
178
  onTokenChange: (token) => setToken(token),
178
179
  onRegistrationMethodChange: (method) => setRegistrationMethod(method),
179
180
  otpValue,
181
+ openChatSupport
180
182
  };
181
183
  return (_jsx(AuthContext.Provider, { value: AuthContextValues, children: _jsx(AuthPackageContext.Provider, { value: AuthPackageContextValues, children: children }) }));
182
184
  };
@@ -1,6 +1,6 @@
1
1
  export var LoginMethodCode;
2
2
  (function (LoginMethodCode) {
3
- LoginMethodCode[LoginMethodCode["EmailPassword"] = 1] = "EmailPassword";
3
+ LoginMethodCode[LoginMethodCode["Email"] = 1] = "Email";
4
4
  LoginMethodCode[LoginMethodCode["Facebook"] = 2] = "Facebook";
5
5
  LoginMethodCode[LoginMethodCode["Google"] = 3] = "Google";
6
6
  LoginMethodCode[LoginMethodCode["Apple"] = 4] = "Apple";
@@ -16,8 +16,12 @@ import SSOSearchOrganization from '../screens/SSOLogin/SearchOrganization/index.
16
16
  import SSOAuthenticationMethods from '../screens/SSOLogin/AuthenticationMethods/index.native';
17
17
  import SSOAuthWebView from '../screens/SSOLogin/AuthWebView/index.native';
18
18
  import SSOCallback from '../screens/SSOLogin/SSOCallback/index.native';
19
+ import LoginWithMobileOTP from '../screens/LoginWithMobileOTP/index.native';
20
+ import EnterMobile from '../screens/EnterMobile/index.native';
21
+ import VerifyLinkPrimaryAccountEmailOTP from '../screens/VerifyLinkPrimaryAccountEmailOTP/index.native';
22
+ import VerifyLinkPrimaryAccountMobileOTP from '../screens/VerifyLinkPrimaryAccountMobileOTP/index.native';
19
23
  const { Navigator, Screen } = createNativeStackNavigator();
20
24
  const AuthNavigator = () => {
21
- return (_jsxs(Navigator, { screenOptions: { headerShown: false }, children: [_jsx(Screen, { name: "Welcome", component: Welcome }), _jsx(Screen, { name: "EnterEmail", component: EnterEmail }), _jsx(Screen, { name: "EnterPassword", component: EnterPassword }), _jsx(Screen, { name: "SignUp", component: SignUp }), _jsx(Screen, { name: "CountryCode", component: CountryCode }), _jsx(Screen, { name: "CreatePassword", component: CreatePassword }), _jsx(Screen, { name: "UserConsent", component: UserConsent }), _jsx(Screen, { name: "VerifyMobile", component: VerifyMobile }), _jsx(Screen, { name: "VerifyEmail", component: VerifyEmail }), _jsx(Screen, { name: "LoginWithEmailOTP", component: LoginWithEmailOTP }), _jsx(Screen, { name: "VerifyResetPasswordOTP", component: VerifyResetPasswordOTP }), _jsx(Screen, { name: "ResetPassword", component: ResetPassword }), _jsx(Screen, { name: "SSOSearchOrganization", component: SSOSearchOrganization }), _jsx(Screen, { name: "SSOAuthenticationMethods", component: SSOAuthenticationMethods }), _jsx(Screen, { name: "SSOAuthWebView", component: SSOAuthWebView }), _jsx(Screen, { name: "SSOCallback", component: SSOCallback })] }));
25
+ return (_jsxs(Navigator, { screenOptions: { headerShown: false }, children: [_jsx(Screen, { name: "Welcome", component: Welcome }), _jsx(Screen, { name: "EnterEmail", component: EnterEmail }), _jsx(Screen, { name: "EnterPassword", component: EnterPassword }), _jsx(Screen, { name: "SignUp", component: SignUp }), _jsx(Screen, { name: "CountryCode", component: CountryCode }), _jsx(Screen, { name: "CreatePassword", component: CreatePassword }), _jsx(Screen, { name: "UserConsent", component: UserConsent }), _jsx(Screen, { name: "VerifyMobile", component: VerifyMobile }), _jsx(Screen, { name: "VerifyEmail", component: VerifyEmail }), _jsx(Screen, { name: "LoginWithEmailOTP", component: LoginWithEmailOTP }), _jsx(Screen, { name: "VerifyResetPasswordOTP", component: VerifyResetPasswordOTP }), _jsx(Screen, { name: "ResetPassword", component: ResetPassword }), _jsx(Screen, { name: "LoginWithMobileOTP", component: LoginWithMobileOTP }), _jsx(Screen, { name: "EnterMobile", component: EnterMobile }), _jsx(Screen, { name: "VerifyLinkPrimaryAccountEmailOTP", component: VerifyLinkPrimaryAccountEmailOTP }), _jsx(Screen, { name: "VerifyLinkPrimaryAccountMobileOTP", component: VerifyLinkPrimaryAccountMobileOTP }), _jsx(Screen, { name: "SSOSearchOrganization", component: SSOSearchOrganization }), _jsx(Screen, { name: "SSOAuthenticationMethods", component: SSOAuthenticationMethods }), _jsx(Screen, { name: "SSOAuthWebView", component: SSOAuthWebView }), _jsx(Screen, { name: "SSOCallback", component: SSOCallback })] }));
22
26
  };
23
27
  export { AuthNavigator };
@@ -1,68 +1,78 @@
1
- import { useCallback, useState } from "react";
1
+ import { useState, useCallback } from "react";
2
2
  import { showMessage } from "../../../../helpers/show-message";
3
3
  import { useAuthPackageContext } from "../../../../hooks/internal/useAuthPackageContext";
4
4
  import { checkEmailExists } from "../../../../api/auth";
5
- import { LoginMethodCode } from "../../../../enums";
6
- const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
5
+ import { LoginMethodCode, RegistrationMethod } from "../../../../enums";
6
+ const EMAIL_REGEX = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
7
7
  /**
8
8
  * @internal
9
- * Internal hook for managing EnterEmail screen state and auth context integration. Not exposed to package consumers.
9
+ * Hook for managing Enter Email screen logic and authentication integration.
10
10
  */
11
11
  const useEnterEmail = () => {
12
+ const [email, setEmail] = useState("");
13
+ const [loginType, setLoginType] = useState("");
12
14
  const [loading, setLoading] = useState(false);
13
- const [isInvalidEmail, setInvalidEmail] = useState(true);
14
- const [loginConflictModalVisible, setLoginConflictModalVisible] = useState(false);
15
- const [loginType, setLoginType] = useState('');
16
- const [email, setEmail] = useState('');
15
+ const [isEmailValid, setIsEmailValid] = useState(false);
16
+ const [isLoginConflictModalVisible, setIsLoginConflictModalVisible] = useState(false);
17
17
  const { appConfig, onRegistrationMethodChange } = useAuthPackageContext();
18
- const enterEmail = useCallback((text) => {
19
- const value = text.toLowerCase().trim();
20
- setInvalidEmail(!emailRegex.test(value));
21
- setEmail(value);
22
- }, [emailRegex]);
23
- const handleValidateEmail = async ({ onContinue }) => {
18
+ /**
19
+ * Handles email input change with validation
20
+ */
21
+ const handleEmailChange = useCallback((value) => {
22
+ const normalizedEmail = value.toLowerCase().trim();
23
+ setEmail(normalizedEmail);
24
+ setIsEmailValid(EMAIL_REGEX.test(normalizedEmail));
25
+ }, []);
26
+ /**
27
+ * Validates email existence and handles login conflicts
28
+ */
29
+ const handleEmailExists = useCallback(async ({ onValidate }) => {
24
30
  setLoading(true);
25
31
  try {
26
32
  const { emailExist, loginType } = await checkEmailExists(email);
27
- const code = Number(loginType);
28
- if (emailExist && code !== LoginMethodCode.EmailPassword) {
29
- const loginTypesMap = {
30
- [LoginMethodCode.Facebook]: 'Facebook',
31
- [LoginMethodCode.Google]: 'Google',
32
- [LoginMethodCode.Apple]: 'Apple',
33
- [LoginMethodCode.SSO]: 'SSO',
33
+ const loginCode = Number(loginType);
34
+ if (emailExist && loginCode !== LoginMethodCode.Email) {
35
+ const loginMethodMap = {
36
+ [LoginMethodCode.Facebook]: "Facebook",
37
+ [LoginMethodCode.Google]: "Google",
38
+ [LoginMethodCode.Apple]: "Apple",
39
+ [LoginMethodCode.SSO]: "SSO",
34
40
  };
35
- setLoginType(loginTypesMap[code] || 'your social account');
36
- setLoginConflictModalVisible(true);
41
+ setLoginType(loginMethodMap[loginCode] || "your social account");
42
+ setIsLoginConflictModalVisible(true);
37
43
  return;
38
44
  }
39
- onContinue({ emailExist });
45
+ onRegistrationMethodChange(RegistrationMethod.EMAIL);
46
+ onValidate({ emailExist });
40
47
  }
41
- catch (err) {
42
- const errorMessage = err?.response?.data?.errors?.[0]?.message ?? 'Something went wrong';
43
- showMessage({ message: errorMessage });
48
+ catch (error) {
49
+ const message = error?.response?.data?.errors?.[0]?.message ?? "Something went wrong";
50
+ showMessage({ message });
44
51
  }
45
52
  finally {
46
53
  setLoading(false);
47
54
  }
48
- };
49
- const clearText = useCallback(() => {
50
- setEmail('');
51
- setInvalidEmail(true);
55
+ }, [email]);
56
+ /**
57
+ * Clears email input field
58
+ */
59
+ const handleClearEmail = useCallback(() => {
60
+ setEmail("");
61
+ setIsEmailValid(false);
52
62
  }, []);
53
63
  return {
54
64
  email,
55
- appName: appConfig.appName,
56
- isInvalidEmail,
65
+ isEmailValid,
57
66
  loading,
58
- enterEmail,
59
- handleValidateEmail,
60
- clearText,
61
- loginConflictModalVisible,
62
- setLoginConflictModalVisible,
67
+ handleEmailChange,
68
+ handleEmailExists,
69
+ handleClearEmail,
70
+ isLoginConflictModalVisible,
71
+ setIsLoginConflictModalVisible,
63
72
  onRegistrationMethodChange,
64
- loginConflictErrorTitle: `Sign in with ${loginType}`,
65
- loginConflictErrorDescription: `Looks like you previously registered using ${loginType}. Please go back and sign in with ${loginType}.`,
73
+ appName: appConfig.appName,
74
+ loginConflictTitle: `Sign in with ${loginType}`,
75
+ loginConflictDescription: `Looks like you previously registered using ${loginType}. Please go back and sign in with ${loginType}.`,
66
76
  };
67
77
  };
68
78
  export { useEnterEmail };
@@ -5,24 +5,22 @@ import { ScreenLayout } from "../../components/ScreenLayout";
5
5
  import { useEnterEmail } from "./hooks/internal/useEnterEmail";
6
6
  import { SupportDetails } from '../../components/SupportDetails';
7
7
  const EnterEmail = ({ onContinue, onPressSignInWithSSO }) => {
8
- const { loading, email, isInvalidEmail, loginConflictModalVisible, loginConflictErrorTitle, loginConflictErrorDescription, enterEmail, appName, handleValidateEmail, setLoginConflictModalVisible, } = useEnterEmail();
8
+ const { email, isEmailValid, handleEmailChange, appName, handleEmailExists, loading, loginConflictTitle, loginConflictDescription, isLoginConflictModalVisible, setIsLoginConflictModalVisible } = useEnterEmail();
9
9
  const form = useForm({ defaultValues: { email } });
10
10
  return (_jsxs(_Fragment, { children: [_jsxs(ScreenLayout, { title: `Hi, Welcome To ${appName}!`, subTitle: "Please enter email to get started.", buttonProps: {
11
11
  loading,
12
12
  label: 'Continue',
13
13
  onClick: () => {
14
- if (!loading && !isInvalidEmail) {
15
- handleValidateEmail({
16
- onContinue: (params) => onContinue({ email, emailExist: params.emailExist })
17
- });
18
- }
14
+ handleEmailExists({
15
+ onValidate: ({ emailExist }) => onContinue({ email, emailExist })
16
+ });
19
17
  },
20
- disabled: isInvalidEmail || loading,
18
+ disabled: !isEmailValid,
21
19
  }, children: [_jsx(Form, { className: "w-full", form: form, children: _jsx(Form.Item, { name: "email", label: "Email", children: _jsx(TextInput, { type: "email", value: email, size: "medium", placeholder: "example@domain", ...form.register('email', {
22
20
  onChange: (e) => {
23
- enterEmail(e.target.value);
21
+ handleEmailChange(e.target.value);
24
22
  }
25
- }) }) }) }), loginConflictModalVisible &&
26
- _jsx(LoginConflictModal, { title: loginConflictErrorTitle, primaryLabel: 'Okay', description: loginConflictErrorDescription, visible: loginConflictModalVisible, onProceed: () => setLoginConflictModalVisible(false), onClose: () => setLoginConflictModalVisible(false) })] }), _jsx(Button, { isFullWidth: true, type: "button", label: 'Sign In with SSO', variant: 'secondary', className: 'flex-none mt-6', onClick: onPressSignInWithSSO }), _jsx(SupportDetails, {})] }));
23
+ }) }) }) }), isLoginConflictModalVisible &&
24
+ _jsx(LoginConflictModal, { title: loginConflictTitle, description: loginConflictDescription, visible: isLoginConflictModalVisible, onProceed: () => setIsLoginConflictModalVisible(false), onClose: () => setIsLoginConflictModalVisible(false), primaryLabel: 'Okay' })] }), _jsx(Button, { isFullWidth: true, type: "button", label: 'Sign In with SSO', variant: 'secondary', className: 'flex-none mt-6', onClick: onPressSignInWithSSO }), _jsx(SupportDetails, {})] }));
27
25
  };
28
26
  export default EnterEmail;
@@ -8,13 +8,12 @@ import { ConfirmationModal as LoginConflictModal } from '../../components/Confir
8
8
  import { RegistrationMethod } from '../../enums';
9
9
  const { utility } = Colors;
10
10
  const EnterEmail = ({ navigation }) => {
11
- const { loading, email, isInvalidEmail, loginConflictModalVisible, loginConflictErrorTitle, loginConflictErrorDescription, enterEmail, clearText, handleValidateEmail, onRegistrationMethodChange, setLoginConflictModalVisible, } = useEnterEmail();
12
- const onContinue = (params) => {
11
+ const { email, isEmailValid, handleEmailChange, handleClearEmail, handleEmailExists, loading, loginConflictTitle, loginConflictDescription, isLoginConflictModalVisible, setIsLoginConflictModalVisible } = useEnterEmail();
12
+ const onValidate = (params) => {
13
13
  if (params.emailExist) {
14
14
  navigation.navigate('EnterPassword', { email });
15
15
  }
16
16
  else {
17
- onRegistrationMethodChange(RegistrationMethod.EMAIL);
18
17
  navigation.navigate('SignUp', { email });
19
18
  }
20
19
  };
@@ -23,12 +22,10 @@ const EnterEmail = ({ navigation }) => {
23
22
  label: 'Continue',
24
23
  onPress: () => {
25
24
  Keyboard.dismiss();
26
- if (!loading && !isInvalidEmail) {
27
- handleValidateEmail({ onContinue });
28
- }
25
+ handleEmailExists({ onValidate });
29
26
  },
30
- disabled: isInvalidEmail || loading,
31
- }, children: _jsx(TextInputField, { value: email, placeholder: 'Enter here...', onChangeValue: text => enterEmail(text), rightIcon2: email.length > 0 ? 'close' : '', onPressRightIcon2: clearText, autoFocus: true, autoCapitalize: 'none', keyboardType: 'email-address' }) }), loginConflictModalVisible &&
32
- _jsx(LoginConflictModal, { title: loginConflictErrorTitle, description: loginConflictErrorDescription, visible: loginConflictModalVisible, onProceed: () => setLoginConflictModalVisible(false), onClose: () => setLoginConflictModalVisible(false), iconColor: utility.warning_main, primaryLabel: 'Okay' })] }));
27
+ disabled: !isEmailValid,
28
+ }, children: _jsx(TextInputField, { value: email, placeholder: 'Enter here...', onChangeValue: handleEmailChange, rightIcon2: email.length > 0 ? 'close' : '', onPressRightIcon2: handleClearEmail, autoFocus: true, autoCapitalize: 'none', keyboardType: 'email-address' }) }), isLoginConflictModalVisible &&
29
+ _jsx(LoginConflictModal, { title: loginConflictTitle, description: loginConflictDescription, visible: isLoginConflictModalVisible, onProceed: () => setIsLoginConflictModalVisible(false), onClose: () => setIsLoginConflictModalVisible(false), iconColor: utility.warning_main, primaryLabel: 'Okay' })] }));
33
30
  };
34
31
  export default EnterEmail;
@@ -0,0 +1,36 @@
1
+ import { useCallback, useState } from "react";
2
+ import { axiosClient } from '../../../../../../api/axiosClient';
3
+ import { showMessage } from "../../../../../../helpers/show-message";
4
+ /**
5
+ * @internal
6
+ * Internal hook for managing useExistingAccountsSheet hook state and auth context integration. Not exposed to package consumers.
7
+ */
8
+ const useExistingAccountsSheet = () => {
9
+ const [loading, setLoading] = useState(false);
10
+ const [selectedAccount, setSelectedAccount] = useState(null);
11
+ const linkPrimaryAccount = useCallback(({ phone, onInitiateLinking }) => {
12
+ setLoading(true);
13
+ axiosClient({
14
+ url: '/auth/mobile/link-primary-account/initiate',
15
+ method: 'POST',
16
+ data: {
17
+ phone,
18
+ memberId: selectedAccount?.memberId,
19
+ },
20
+ })
21
+ .then((res) => onInitiateLinking(res.data))
22
+ .catch((error) => {
23
+ console.log(error);
24
+ const message = error?.response?.data?.errors?.[0]?.message ?? 'Unable to initiate linking. Please try again.';
25
+ showMessage({ message });
26
+ })
27
+ .finally(() => setLoading(false));
28
+ }, [selectedAccount]);
29
+ return {
30
+ loading,
31
+ linkPrimaryAccount,
32
+ selectedAccount,
33
+ setSelectedAccount
34
+ };
35
+ };
36
+ export { useExistingAccountsSheet };
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useExistingAccountsSheet } from './hooks/internal/useExistingAccountsSheet';
3
+ import { ResponsiveModal, Typography, Flex, Button, Card, Radio } from '@truworth/twc-web-design';
4
+ import { SupportDetails } from '../../../../components/SupportDetails';
5
+ import { IonIcon } from '../../../../components/IonIcon';
6
+ import { LoginMethodCode } from '../../../../enums';
7
+ import moment from 'moment';
8
+ const ExistingAccountsSheet = ({ visible, hide, phone, existingAccounts, onInitiateAccountLinking }) => {
9
+ const { loading, linkPrimaryAccount, selectedAccount, setSelectedAccount, } = useExistingAccountsSheet();
10
+ const onContinue = () => {
11
+ if (!phone || !selectedAccount?.email) {
12
+ return;
13
+ }
14
+ linkPrimaryAccount({
15
+ phone,
16
+ onInitiateLinking: ({ sessionToken }) => {
17
+ onInitiateAccountLinking?.({
18
+ sessionToken,
19
+ email: selectedAccount?.email
20
+ });
21
+ }
22
+ });
23
+ };
24
+ const displayPhone = phone ? `+91${phone.replace(/^.{8}/, 'XXXXXXXX')}` : '+91**********';
25
+ return (_jsxs(ResponsiveModal, { open: visible, onClose: hide, onOpenChange: hide, maskClosable: false, title: _jsxs(_Fragment, { children: [_jsx(Typography, { type: "heading", size: "h6", children: "Multiple Accounts Found" }), _jsxs(Typography, { type: "utility", size: "medium", color: "gray-600", className: "mt-2 mb-3", children: ["The phone number ", displayPhone, " is linked to the following accounts."] }), _jsx("hr", {})] }), centered: true, showCloseButton: false, className: "px-0", footer: _jsxs(Flex, { direction: "column", className: 'pt-1', children: [_jsx(Flex, { className: "flex-1 border-t border-gray-300 mb-2" }), selectedAccount &&
26
+ _jsxs(Flex, { align: 'center', className: 'bg-utility-warning-bg p-2 rounded-lg gap-1', children: [_jsx(IonIcon, { name: "information-circle-outline", style: { color: "hsl(var(--tw-ui-utility---warning--main))", fontSize: 24 } }), _jsxs(Typography, { type: "utility", size: "small", children: [_jsx("span", { className: "text-gray-500 text-[12px]", children: "Once you proceed, this phone number will be removed" }), " from other accounts."] })] }), _jsx(Button, { isFullWidth: true, loading: loading, variant: "primary", label: "Link and Continue", className: 'mt-4 mb-[-16px]', onClick: onContinue, disabled: !selectedAccount }), _jsx(SupportDetails, {})] }), children: [_jsx(Typography, { type: "utility", size: "medium", className: "mb-4", children: "Select account you want to continue with." }), existingAccounts.map((item) => {
27
+ return (_jsx(OptionCard, { item: item, onClick: () => setSelectedAccount(item), selectedItem: selectedAccount }, item.memberId));
28
+ })] }));
29
+ };
30
+ const OptionCard = ({ item, onClick, selectedItem }) => {
31
+ return (_jsx(Card, { containerStyle: `p-4 mb-2 ${item.memberId === selectedItem?.memberId ? 'border-primary' : 'border-gray-200'}`, children: _jsxs(Flex, { className: 'gap-2', onClick: onClick, children: [_jsx(Radio, { selectedValue: selectedItem?.memberId, options: [{ label: '', value: item.memberId }] }), _jsx(Flex, { direction: 'column', className: 'mt-[-2px]', children: _jsxs(_Fragment, { children: [_jsxs(Flex, { direction: "column", className: "border-b-2 pb-2 w-full", children: [_jsx(Typography, { type: "utility", size: "large", className: "break-words w-full mb-1", children: item.name }), _jsx(Typography, { type: "utility", size: "medium", color: "primary", className: "truncate w-full", children: item.email })] }), _jsxs(_Fragment, { children: [_jsxs(Flex, { justify: "between", className: "mt-3", children: [_jsx(Typography, { type: "utility", size: "medium", color: "gray-700", children: "Registration Source" }), _jsx(Typography, { type: "utility", size: "medium", color: "gray-800", children: item.loginType ? LoginMethodCode[item.loginType] : '—' })] }), _jsxs(Flex, { justify: "between", className: "mt-3", children: [_jsx(Typography, { type: "utility", size: "medium", color: "gray-700", children: "Registration Date" }), _jsx(Typography, { type: "utility", size: "medium", color: "gray-800", children: item.createdOn ? moment(item.createdOn).format('DD/MM/YYYY') : '—' })] })] })] }) })] }) }));
32
+ };
33
+ export { ExistingAccountsSheet };
@@ -0,0 +1,73 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect } from 'react';
3
+ import { Divider } from '@ui-kitten/components';
4
+ import { Platform, Text, TouchableOpacity, View } from 'react-native';
5
+ import { useNavigation } from '@react-navigation/native';
6
+ import { BottomSheet, Colors, isIphoneX, RadioButton, RoundedButton } from '@truworth/twc-rn-common';
7
+ import { useModalize } from 'react-native-modalize';
8
+ import { useExistingAccountsSheet } from './hooks/internal/useExistingAccountsSheet';
9
+ import { useAuthPackageContext } from '../../../../hooks/internal/useAuthPackageContext';
10
+ import { LoginMethodCode } from '../../../../enums';
11
+ import moment from 'moment';
12
+ import IonIcons from 'react-native-vector-icons/Ionicons';
13
+ const { primary, gray, utility } = Colors;
14
+ const ExistingAccountsSheet = ({ visible, hide, phone, existingAccounts }) => {
15
+ const { ref: sheetRef, open: openSheet, close: closeSheet } = useModalize();
16
+ const navigation = useNavigation();
17
+ const { openChatSupport } = useAuthPackageContext();
18
+ const { loading, linkPrimaryAccount, selectedAccount, setSelectedAccount } = useExistingAccountsSheet();
19
+ useEffect(() => {
20
+ if (visible) {
21
+ openSheet();
22
+ }
23
+ else {
24
+ closeSheet();
25
+ }
26
+ }, [visible]);
27
+ const onContinue = () => {
28
+ if (!phone || !selectedAccount?.email) {
29
+ return;
30
+ }
31
+ linkPrimaryAccount({
32
+ phone,
33
+ onInitiateLinking: ({ sessionToken }) => {
34
+ navigation.navigate('VerifyLinkPrimaryAccountEmailOTP', {
35
+ phone,
36
+ sessionToken,
37
+ email: selectedAccount?.email
38
+ });
39
+ hide();
40
+ }
41
+ });
42
+ };
43
+ const displayPhone = phone ? `+91${phone.replace(/^.{8}/, 'XXXXXXXX')}` : '+91**********';
44
+ return (_jsx(BottomSheet, { sheetRef: sheetRef, onClose: hide, panGestureEnabled: false, HeaderComponent: _jsxs(_Fragment, { children: [_jsxs(View, { style: { paddingTop: 22, marginHorizontal: 22 }, children: [_jsx(Text, { style: { fontSize: 16, fontWeight: '600', color: gray.gray_900, textAlign: 'center' }, children: "Multiple Accounts Found" }), _jsxs(Text, { style: { fontSize: 12, fontWeight: '500', color: gray.gray_500, lineHeight: 20, textAlign: 'center', marginHorizontal: 16 }, children: ["The phone number ", displayPhone, " is linked to the following accounts."] })] }), _jsx(View, { style: { backgroundColor: gray.gray_200, height: 2, marginVertical: 8 } })] }), flatListProps: {
45
+ showsVerticalScrollIndicator: false,
46
+ contentContainerStyle: { flexGrow: 1 },
47
+ data: existingAccounts,
48
+ keyExtractor: (item) => item.memberId,
49
+ ListHeaderComponent: _jsx(Text, { style: { fontSize: 14, fontWeight: '600', color: gray.gray_900, marginHorizontal: 16, marginTop: 8 }, children: "Select account you want to continue with." }),
50
+ renderItem: ({ item }) => {
51
+ return (_jsxs(TouchableOpacity, { activeOpacity: 0.8, style: { padding: 16, margin: 8, borderWidth: 1, borderRadius: 8, borderColor: selectedAccount?.memberId === item.memberId ? primary.primary_main : gray.gray_200 }, onPress: () => setSelectedAccount(item), children: [_jsxs(View, { style: { flexDirection: 'row', alignItems: 'center' }, children: [_jsx(RadioButton, { checked: selectedAccount?.memberId === item.memberId, onChecked: () => setSelectedAccount(item) }), _jsxs(View, { style: { flex: 1, marginStart: 8 }, children: [_jsx(Text, { style: { fontSize: 14, fontWeight: '600', color: gray.gray_900 }, children: item.name }), _jsx(Text, { style: { fontSize: 12, fontWeight: '500', color: primary.primary_main, marginTop: 3 }, children: item.email })] })] }), _jsx(Divider, { style: { marginVertical: 8, backgroundColor: gray.gray_200 } }), _jsxs(View, { style: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }, children: [_jsx(Text, { style: { fontSize: 12, fontWeight: '500', color: gray.gray_500 }, children: "Registration Source" }), _jsx(Text, { style: { fontSize: 12, fontWeight: '600', color: gray.gray_800 }, children: LoginMethodCode[item.loginType] || 'Unknown' })] }), _jsxs(View, { style: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginTop: 8 }, children: [_jsx(Text, { style: { fontSize: 12, fontWeight: '500', color: gray.gray_500 }, children: "Registration Date" }), _jsx(Text, { style: { fontSize: 12, fontWeight: '600', color: gray.gray_800, }, children: moment(item.createdOn).format('DD/MM/YYYY') })] })] }, item.memberId));
52
+ }
53
+ }, FooterComponent: _jsxs(View, { style: {
54
+ width: '100%', backgroundColor: 'white', marginTop: 8,
55
+ padding: 16, marginBottom: isIphoneX() ? 30 : 0,
56
+ borderTopWidth: Platform.OS == 'android' ? 1 : 0, borderTopColor: gray.gray_300,
57
+ shadowColor: '#DDDDDD', shadowOffset: { width: 0, height: -2 },
58
+ shadowOpacity: 1, shadowRadius: 3, elevation: 3
59
+ }, children: [selectedAccount &&
60
+ _jsxs(View, { style: {
61
+ backgroundColor: utility.warning_bg,
62
+ padding: 8,
63
+ borderRadius: 8,
64
+ marginBottom: 8,
65
+ flexDirection: 'row',
66
+ alignItems: 'center',
67
+ }, children: [_jsx(IonIcons, { size: 16, name: "information-circle", style: { marginRight: 8 }, color: utility.warning_main }), _jsxs(Text, { style: {
68
+ flex: 1, fontSize: 12, fontWeight: '500',
69
+ lineHeight: 18, color: gray.gray_500,
70
+ }, children: ["Once you proceed, this phone number will be ", _jsx(Text, { style: { fontWeight: '600', color: gray.gray_900 }, children: "removed from other accounts." })] })] }), _jsx(RoundedButton, { label: 'Link and Continue', size: 'large', loading: loading, disabled: !selectedAccount, onPress: onContinue, containerStyle: { marginBottom: 8 } }), openChatSupport &&
71
+ _jsxs(TouchableOpacity, { activeOpacity: 0.8, onPress: openChatSupport, style: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', padding: 8 }, children: [_jsx(IonIcons, { size: 12, name: 'headset', color: primary.primary_main }), _jsx(Text, { style: { fontSize: 14, fontWeight: '600', color: primary.primary_main, marginStart: 8 }, children: "Connect with Support" })] })] }) }));
72
+ };
73
+ export { ExistingAccountsSheet };
@@ -0,0 +1,67 @@
1
+ import { useState } from "react";
2
+ import { checkMobileExists } from "../../../../api/auth";
3
+ import { showMessage } from "../../../../helpers/show-message";
4
+ import { useAuthPackageContext } from "../../../../hooks/internal/useAuthPackageContext";
5
+ import { RegistrationMethod } from "../../../../enums";
6
+ const useEnterMobile = () => {
7
+ const [loading, setLoading] = useState(false);
8
+ const [isValidPhone, setValidPhone] = useState(false);
9
+ const [showExistingAccountsSheet, setShowExistingAccountsSheet] = useState(false);
10
+ const [phone, setPhone] = useState('');
11
+ const [countryCode, setCountryCode] = useState('91');
12
+ const [existingAccounts, setExistingAccounts] = useState([]);
13
+ const { onRegistrationMethodChange } = useAuthPackageContext();
14
+ const handleEnterMobile = (text) => {
15
+ setPhone(text);
16
+ const isNumeric = /^[0-9]+$/.test(text);
17
+ if (countryCode === '91' && text.length === 10 && isNumeric) {
18
+ setValidPhone(true);
19
+ }
20
+ else if (countryCode !== '91' && text.length >= 6 && text.length <= 15 && isNumeric) {
21
+ setValidPhone(true);
22
+ }
23
+ else {
24
+ setValidPhone(false);
25
+ }
26
+ };
27
+ const handleValidatePhone = async ({ onValidate }) => {
28
+ setLoading(true);
29
+ try {
30
+ const { mobileExist, linkedAccounts } = await checkMobileExists(phone);
31
+ if (mobileExist) {
32
+ if (linkedAccounts && linkedAccounts.length > 1) {
33
+ setExistingAccounts(linkedAccounts);
34
+ return setShowExistingAccountsSheet(true);
35
+ }
36
+ }
37
+ if (!mobileExist) {
38
+ onRegistrationMethodChange(RegistrationMethod.MOBILE);
39
+ }
40
+ onValidate({ mobileExist, email: linkedAccounts?.[0]?.email ?? '' });
41
+ }
42
+ catch (err) {
43
+ const errorMessage = err?.response?.data?.errors?.[0]?.message ?? 'Something went wrong';
44
+ showMessage({ message: errorMessage });
45
+ }
46
+ finally {
47
+ setLoading(false);
48
+ }
49
+ };
50
+ const handleClearPhoneInput = () => {
51
+ setPhone('');
52
+ setValidPhone(false);
53
+ };
54
+ return {
55
+ loading,
56
+ phone,
57
+ isValidPhone,
58
+ countryCode, setCountryCode,
59
+ existingAccounts,
60
+ showExistingAccountsSheet,
61
+ setShowExistingAccountsSheet,
62
+ handleValidatePhone,
63
+ handleEnterMobile,
64
+ handleClearPhoneInput,
65
+ };
66
+ };
67
+ export { useEnterMobile };