@truworth/twc-auth 1.1.0 → 1.2.2
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/README.md +239 -306
- package/build/assets/animation/redirect-home.json +1101 -0
- package/build/assets/cross_icon copy.svg +5 -0
- package/build/assets/cross_icon.svg +5 -0
- package/build/assets/gender-diversity.svg +22 -0
- package/build/assets/logo.svg +55 -0
- package/build/assets/okay_icon copy.svg +3 -0
- package/build/assets/okay_icon.svg +3 -0
- package/build/src/api/axiosClient/index.js +5 -0
- package/build/src/api/axiosClient/index.native.js +5 -0
- package/build/src/components/AdvancedTransitionWrapper/index.js +380 -0
- package/build/src/components/AdvancedTransitionWrapper/index.native.js +10 -0
- package/build/src/components/AdvancedTransitionWrapper/types.js +1 -0
- package/build/src/components/ConfirmationModal/index.js +11 -0
- package/build/src/components/ConfirmationModal/index.native.js +15 -0
- package/build/src/components/ConfirmationModal/types.js +1 -0
- package/build/src/components/EmailOTPVerify/index.js +20 -0
- package/build/src/components/EmailOTPVerify/index.native.js +26 -0
- package/build/src/components/EmailOTPVerify/type.js +1 -0
- package/build/src/components/IonIcon/index.js +11 -0
- package/build/src/components/IonIcon/index.native.js +9 -0
- package/build/src/components/IonIcon/types.js +1 -0
- package/build/src/components/OTPStatusLabel/index.js +10 -0
- package/build/src/components/OTPStatusLabel/index.native.js +21 -0
- package/build/src/components/OTPStatusLabel/types.js +1 -0
- package/build/src/components/PasswordCriteria/hooks/usePasswordCriteria.js +78 -0
- package/build/src/components/PasswordCriteria/index.js +47 -0
- package/build/src/components/PasswordCriteria/index.native.js +22 -0
- package/build/src/components/PasswordCriteria/types.js +1 -0
- package/build/src/components/ScreenLayout/index.js +12 -0
- package/build/src/components/ScreenLayout/index.native.js +18 -0
- package/build/src/components/ScreenLayout/types.js +1 -0
- package/build/src/components/SupportDetails/index.js +9 -0
- package/build/src/components/SupportDetails/index.native.js +6 -0
- package/build/src/components/VerifyOTP/index.js +23 -0
- package/build/src/components/VerifyOTP/index.native.js +38 -0
- package/build/src/components/VerifyOTP/types.js +1 -0
- package/build/src/constants/cdn-url/index.js +1 -0
- package/build/src/constants/cdn-url/index.native.js +5 -0
- package/build/src/contexts/AuthContext.js +185 -0
- package/build/src/contexts/type.js +1 -0
- package/build/src/helpers/Network.js +93 -0
- package/build/src/helpers/Validation.js +12 -0
- package/build/src/helpers/show-message/index.js +19 -0
- package/build/src/helpers/show-message/index.native.js +14 -0
- package/build/src/helpers/show-message/types.js +1 -0
- package/build/src/helpers/types.js +1 -0
- package/build/src/hooks/internal/useAuthPackageContext.js +9 -0
- package/build/src/hooks/internal/useTimer.js +40 -0
- package/build/src/hooks/useAuthContext.js +10 -0
- package/build/src/hooks/useRequest.js +41 -0
- package/build/src/index.js +14 -0
- package/build/src/navigator/index.js +10 -0
- package/build/src/navigator/index.native.js +16 -0
- package/build/src/screens/CountryCode/components/CountryCodeDropdown/index.js +38 -0
- package/build/src/screens/CountryCode/components/CountryCodeDropdown/index.native.js +6 -0
- package/build/src/screens/CountryCode/components/CountryCodeDropdown/types.js +1 -0
- package/build/src/screens/CountryCode/hooks/internal/useCountryCode.js +38 -0
- package/build/src/screens/CountryCode/index.js +10 -0
- package/build/src/screens/CountryCode/index.native.js +37 -0
- package/build/src/screens/CountryCode/type.js +1 -0
- package/build/src/screens/CreatePassword/hooks/internal/useCreatePassword.js +52 -0
- package/build/src/screens/CreatePassword/index.js +43 -0
- package/build/src/screens/CreatePassword/index.native.js +32 -0
- package/build/src/screens/CreatePassword/type.js +1 -0
- package/build/src/screens/EnterEmail/hooks/internal/useEnterEmail.js +86 -0
- package/build/src/screens/EnterEmail/index.js +30 -0
- package/build/src/screens/EnterEmail/index.native.js +34 -0
- package/build/src/screens/EnterPassword/hooks/internal/useEnterPassword.js +47 -0
- package/build/src/screens/EnterPassword/index.js +22 -0
- package/build/src/screens/EnterPassword/index.native.js +23 -0
- package/build/src/screens/EnterPassword/types.js +1 -0
- package/build/src/screens/Login/components/LoginWebComponent/index.js +44 -0
- package/build/src/screens/Login/components/LoginWebComponent/index.native.js +6 -0
- package/build/src/screens/Login/index.js +10 -0
- package/build/src/screens/Login/index.native.js +6 -0
- package/build/src/screens/SignUp/components/SignUpForm/index.js +174 -0
- package/build/src/screens/SignUp/components/SignUpForm/index.native.js +6 -0
- package/build/src/screens/SignUp/components/SignUpForm/type.js +1 -0
- package/build/src/screens/SignUp/components/SignUpWebComponent/index.js +82 -0
- package/build/src/screens/SignUp/components/SignUpWebComponent/index.native.js +6 -0
- package/build/src/screens/SignUp/components/SignUpWebComponent/types.js +1 -0
- package/build/src/screens/SignUp/hooks/internal/useSignUp.js +138 -0
- package/build/src/screens/SignUp/index.js +6 -0
- package/build/src/screens/SignUp/index.native.js +185 -0
- package/build/src/screens/SignUp/types.js +1 -0
- package/build/src/screens/UserConsent/hooks/internal/useConsent.js +48 -0
- package/build/src/screens/UserConsent/index.js +69 -0
- package/build/src/screens/UserConsent/index.native.js +46 -0
- package/build/src/screens/UserConsent/types.js +1 -0
- package/build/src/screens/VerifyEmail/hooks/internal/useVerifyEmail.js +69 -0
- package/build/src/screens/VerifyEmail/index.js +8 -0
- package/build/src/screens/VerifyEmail/index.native.js +14 -0
- package/build/src/screens/VerifyEmail/types.js +1 -0
- package/build/src/screens/VerifyMobile/hooks/internal/useVerifyMobile.js +73 -0
- package/build/src/screens/VerifyMobile/index.js +8 -0
- package/build/src/screens/VerifyMobile/index.native.js +9 -0
- package/build/src/screens/VerifyMobile/types.js +1 -0
- package/build/src/screens/Welcome/hooks/internal/useWelcome.js +21 -0
- package/build/src/screens/Welcome/index.js +28 -0
- package/build/src/screens/Welcome/index.native.js +41 -0
- package/build/src/types/types.js +1 -0
- package/build/types/api/axiosClient/index.d.ts +1 -0
- package/build/types/api/axiosClient/index.native.d.ts +1 -0
- package/build/types/components/AdvancedTransitionWrapper/index.d.ts +3 -0
- package/build/types/components/AdvancedTransitionWrapper/index.native.d.ts +5 -0
- package/build/types/components/AdvancedTransitionWrapper/types.d.ts +25 -0
- package/build/types/components/ConfirmationModal/index.d.ts +3 -0
- package/build/types/components/ConfirmationModal/index.native.d.ts +3 -0
- package/build/types/components/ConfirmationModal/types.d.ts +13 -0
- package/build/types/components/EmailOTPVerify/index.d.ts +3 -0
- package/build/types/components/EmailOTPVerify/index.native.d.ts +3 -0
- package/build/types/components/EmailOTPVerify/type.d.ts +9 -0
- package/build/types/components/IonIcon/index.d.ts +3 -0
- package/build/types/components/IonIcon/index.native.d.ts +4 -0
- package/build/types/components/IonIcon/types.d.ts +6 -0
- package/build/types/components/OTPStatusLabel/index.d.ts +2 -0
- package/build/types/components/OTPStatusLabel/index.native.d.ts +3 -0
- package/build/types/components/OTPStatusLabel/types.d.ts +6 -0
- package/build/types/components/PasswordCriteria/hooks/usePasswordCriteria.d.ts +13 -0
- package/build/types/components/PasswordCriteria/index.d.ts +3 -0
- package/build/types/components/PasswordCriteria/index.native.d.ts +3 -0
- package/build/types/components/PasswordCriteria/types.d.ts +15 -0
- package/build/types/components/ScreenLayout/index.d.ts +3 -0
- package/build/types/components/ScreenLayout/index.native.d.ts +3 -0
- package/build/types/components/ScreenLayout/types.d.ts +12 -0
- package/build/types/components/SupportDetails/index.d.ts +2 -0
- package/build/types/components/SupportDetails/index.native.d.ts +2 -0
- package/build/types/components/VerifyOTP/index.d.ts +3 -0
- package/build/types/components/VerifyOTP/index.native.d.ts +3 -0
- package/build/types/components/VerifyOTP/types.d.ts +10 -0
- package/build/types/constants/cdn-url/index.d.ts +1 -0
- package/build/types/constants/cdn-url/index.native.d.ts +3 -0
- package/build/types/contexts/AuthContext.d.ts +36 -0
- package/build/types/contexts/type.d.ts +59 -0
- package/build/types/helpers/Network.d.ts +5 -0
- package/build/types/helpers/Validation.d.ts +2 -0
- package/build/types/helpers/show-message/index.d.ts +3 -0
- package/build/types/helpers/show-message/index.native.d.ts +3 -0
- package/build/types/helpers/show-message/types.d.ts +2 -0
- package/build/types/helpers/types.d.ts +13 -0
- package/build/types/hooks/internal/useAuthPackageContext.d.ts +1 -0
- package/build/types/hooks/internal/useTimer.d.ts +3 -0
- package/build/types/hooks/useAuthContext.d.ts +2 -0
- package/build/types/hooks/useRequest.d.ts +5 -0
- package/build/types/index.d.ts +9 -0
- package/build/types/navigator/index.d.ts +2 -0
- package/build/types/navigator/index.native.d.ts +36 -0
- package/build/types/screens/CountryCode/components/CountryCodeDropdown/index.d.ts +3 -0
- package/build/types/screens/CountryCode/components/CountryCodeDropdown/index.native.d.ts +2 -0
- package/build/types/screens/CountryCode/components/CountryCodeDropdown/types.d.ts +17 -0
- package/build/types/screens/CountryCode/hooks/internal/useCountryCode.d.ts +12 -0
- package/build/types/screens/CountryCode/index.d.ts +2 -0
- package/build/types/screens/CountryCode/index.native.d.ts +2 -0
- package/build/types/screens/CountryCode/type.d.ts +11 -0
- package/build/types/screens/CreatePassword/hooks/internal/useCreatePassword.d.ts +26 -0
- package/build/types/screens/CreatePassword/index.d.ts +3 -0
- package/build/types/screens/CreatePassword/index.native.d.ts +4 -0
- package/build/types/screens/CreatePassword/type.d.ts +43 -0
- package/build/types/screens/EnterEmail/hooks/internal/useEnterEmail.d.ts +24 -0
- package/build/types/screens/EnterEmail/index.d.ts +7 -0
- package/build/types/screens/EnterEmail/index.native.d.ts +4 -0
- package/build/types/screens/EnterPassword/hooks/internal/useEnterPassword.d.ts +20 -0
- package/build/types/screens/EnterPassword/index.d.ts +3 -0
- package/build/types/screens/EnterPassword/index.native.d.ts +4 -0
- package/build/types/screens/EnterPassword/types.d.ts +5 -0
- package/build/types/screens/Login/components/LoginWebComponent/index.d.ts +2 -0
- package/build/types/screens/Login/components/LoginWebComponent/index.native.d.ts +2 -0
- package/build/types/screens/Login/index.d.ts +2 -0
- package/build/types/screens/Login/index.native.d.ts +2 -0
- package/build/types/screens/SignUp/components/SignUpForm/index.d.ts +3 -0
- package/build/types/screens/SignUp/components/SignUpForm/index.native.d.ts +2 -0
- package/build/types/screens/SignUp/components/SignUpForm/type.d.ts +9 -0
- package/build/types/screens/SignUp/components/SignUpWebComponent/index.d.ts +2 -0
- package/build/types/screens/SignUp/components/SignUpWebComponent/index.native.d.ts +2 -0
- package/build/types/screens/SignUp/components/SignUpWebComponent/types.d.ts +24 -0
- package/build/types/screens/SignUp/hooks/internal/useSignUp.d.ts +50 -0
- package/build/types/screens/SignUp/index.d.ts +2 -0
- package/build/types/screens/SignUp/index.native.d.ts +4 -0
- package/build/types/screens/SignUp/types.d.ts +18 -0
- package/build/types/screens/UserConsent/hooks/internal/useConsent.d.ts +10 -0
- package/build/types/screens/UserConsent/index.d.ts +3 -0
- package/build/types/screens/UserConsent/index.native.d.ts +4 -0
- package/build/types/screens/UserConsent/types.d.ts +27 -0
- package/build/types/screens/VerifyEmail/hooks/internal/useVerifyEmail.d.ts +19 -0
- package/build/types/screens/VerifyEmail/index.d.ts +3 -0
- package/build/types/screens/VerifyEmail/index.native.d.ts +4 -0
- package/build/types/screens/VerifyEmail/types.d.ts +8 -0
- package/build/types/screens/VerifyMobile/hooks/internal/useVerifyMobile.d.ts +14 -0
- package/build/types/screens/VerifyMobile/index.d.ts +3 -0
- package/build/types/screens/VerifyMobile/index.native.d.ts +4 -0
- package/build/types/screens/VerifyMobile/types.d.ts +5 -0
- package/build/types/screens/Welcome/hooks/internal/useWelcome.d.ts +14 -0
- package/build/types/screens/Welcome/index.d.ts +4 -0
- package/build/types/screens/Welcome/index.native.d.ts +4 -0
- package/build/types/types/types.d.ts +90 -0
- package/get-metro-config.js +40 -0
- package/get-next-config.js +26 -0
- package/package.json +86 -38
- package/dist/index.esm.js +0 -2028
- package/dist/index.umd.js +0 -70
- package/dist/vite.svg +0 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { useMemo, useState } from "react";
|
|
2
|
+
import { validateEmojiRegex } from "../../../../helpers/Validation";
|
|
3
|
+
import { axiosClient } from "../../../../api/axiosClient";
|
|
4
|
+
import { showMessage } from "../../../../helpers/show-message";
|
|
5
|
+
import { useAuthPackageContext } from "../../../../hooks/internal/useAuthPackageContext";
|
|
6
|
+
/**
|
|
7
|
+
* @internal
|
|
8
|
+
* Hook for managing SignUp screen state and auth context integration.
|
|
9
|
+
* This hook is not exposed to package consumers.
|
|
10
|
+
*/
|
|
11
|
+
const useSignUp = () => {
|
|
12
|
+
const [loading, setLoading] = useState(false);
|
|
13
|
+
const [datePicker, showDatePicker] = useState(false);
|
|
14
|
+
const [isPhoneValid, setIsPhoneValid] = useState(false);
|
|
15
|
+
const [existingAccountModal, setExistingAccountModal] = useState(false);
|
|
16
|
+
const [firstName, setFirstName] = useState('');
|
|
17
|
+
const [lastName, setLastName] = useState('');
|
|
18
|
+
const [phone, setPhone] = useState('');
|
|
19
|
+
const [gender, setGender] = useState('');
|
|
20
|
+
const [referralCode, setReferralCode] = useState('');
|
|
21
|
+
const [selectedDOB, setSelectedDOB] = useState('');
|
|
22
|
+
const [countryCode, setCountryCode] = useState('91');
|
|
23
|
+
const [error, setError] = useState({});
|
|
24
|
+
const [phoneError, setPhoneError] = useState(false);
|
|
25
|
+
const [email, setEmail] = useState('');
|
|
26
|
+
const [emailLinkedError, setEmailLinkedError] = useState('');
|
|
27
|
+
const [existingAccounts, setExistingAccounts] = useState([]);
|
|
28
|
+
const { appConfig, registrationMethod } = useAuthPackageContext();
|
|
29
|
+
const onFirstName = (text) => {
|
|
30
|
+
text = validateEmojiRegex(text).replace(/[^A-Za-z]/g, '');
|
|
31
|
+
setFirstName(text);
|
|
32
|
+
};
|
|
33
|
+
const onLastName = (text) => {
|
|
34
|
+
text = validateEmojiRegex(text).replace(/[^A-Za-z]/g, '');
|
|
35
|
+
;
|
|
36
|
+
setLastName(text);
|
|
37
|
+
};
|
|
38
|
+
const handleEmail = (text) => {
|
|
39
|
+
let reg = /^(([^<>()\[\]\\.,;:\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,}))$/;
|
|
40
|
+
if (text.length === 0) {
|
|
41
|
+
setEmailLinkedError('');
|
|
42
|
+
}
|
|
43
|
+
else if (reg.test(text) === false) {
|
|
44
|
+
setEmailLinkedError('Invalid email');
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
setEmailLinkedError('');
|
|
48
|
+
}
|
|
49
|
+
setEmail(text);
|
|
50
|
+
};
|
|
51
|
+
const handleSubmit = ({ onResult }) => {
|
|
52
|
+
if (registrationMethod === 'email' && countryCode === '91') {
|
|
53
|
+
setLoading(true);
|
|
54
|
+
axiosClient({
|
|
55
|
+
url: '/auth/mobile-exists',
|
|
56
|
+
method: 'POST',
|
|
57
|
+
data: { phone }
|
|
58
|
+
}).then(res => {
|
|
59
|
+
setLoading(false);
|
|
60
|
+
if (res?.data?.exists) {
|
|
61
|
+
setExistingAccounts(res?.data?.memberDetails || []);
|
|
62
|
+
setExistingAccountModal(true);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
onResult();
|
|
66
|
+
}).catch(err => onHandleError(err, onResult));
|
|
67
|
+
}
|
|
68
|
+
else if (registrationMethod === 'mobile' && email) {
|
|
69
|
+
setLoading(true);
|
|
70
|
+
axiosClient({
|
|
71
|
+
url: '/auth/email-exists',
|
|
72
|
+
method: 'POST',
|
|
73
|
+
data: { email }
|
|
74
|
+
}).then(() => {
|
|
75
|
+
setLoading(false);
|
|
76
|
+
setEmailLinkedError('This email is already linked with another user.');
|
|
77
|
+
}).catch(err => onHandleError(err, onResult));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
onResult();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const onHandleError = (err, onResult) => {
|
|
84
|
+
setLoading(false);
|
|
85
|
+
const status = err?.response?.status;
|
|
86
|
+
if (!status) {
|
|
87
|
+
return showMessage('Network error. Please try again.', err?.response?.data?.message);
|
|
88
|
+
}
|
|
89
|
+
if (status === 404) {
|
|
90
|
+
return onResult();
|
|
91
|
+
}
|
|
92
|
+
if (status === 400) {
|
|
93
|
+
return showMessage(err?.response?.data?.errors?.[0]?.message ?? 'Something went wrong');
|
|
94
|
+
}
|
|
95
|
+
if (typeof status === 'number' && status >= 500) {
|
|
96
|
+
return showMessage('Something went wrong');
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const getLoginTypeText = (loginType) => {
|
|
100
|
+
switch (loginType) {
|
|
101
|
+
case 1: return 'Email';
|
|
102
|
+
case 2: return 'Google';
|
|
103
|
+
case 3: return 'Facebook';
|
|
104
|
+
case 4: return 'Apple';
|
|
105
|
+
case 5: return 'Microsoft';
|
|
106
|
+
default: return 'Email';
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const disabled = useMemo(() => {
|
|
110
|
+
return !firstName || firstName.length < 3 || !lastName || lastName.length < 3 || !selectedDOB || !gender
|
|
111
|
+
|| (registrationMethod == "email" && (!phone || !isPhoneValid)) || emailLinkedError.length > 0;
|
|
112
|
+
}, [firstName, lastName, selectedDOB, gender, phone, isPhoneValid, emailLinkedError, registrationMethod]);
|
|
113
|
+
return {
|
|
114
|
+
loading,
|
|
115
|
+
firstName, lastName,
|
|
116
|
+
gender, setGender,
|
|
117
|
+
datePicker, showDatePicker,
|
|
118
|
+
selectedDOB, setSelectedDOB,
|
|
119
|
+
phone, setPhone,
|
|
120
|
+
referralCode, setReferralCode,
|
|
121
|
+
countryCode, setCountryCode,
|
|
122
|
+
error, setError,
|
|
123
|
+
email, setEmail,
|
|
124
|
+
phoneError, setPhoneError,
|
|
125
|
+
isPhoneValid, setIsPhoneValid,
|
|
126
|
+
emailLinkedError,
|
|
127
|
+
existingAccounts,
|
|
128
|
+
existingAccountModal, setExistingAccountModal,
|
|
129
|
+
onFirstName, onLastName,
|
|
130
|
+
handleEmail, handleSubmit,
|
|
131
|
+
getLoginTypeText,
|
|
132
|
+
disabled,
|
|
133
|
+
registrationMethod,
|
|
134
|
+
appName: appConfig.appName,
|
|
135
|
+
termsAndConditionsUrl: appConfig.termsAndConditionsUrl
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
export { useSignUp };
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { View, Text, Platform, Keyboard, TouchableOpacity, ScrollView, TextInput } from 'react-native';
|
|
4
|
+
import { useNavigation, useRoute } from '@react-navigation/native';
|
|
5
|
+
import { useModalize } from 'react-native-modalize';
|
|
6
|
+
import { Freshchat } from 'react-native-freshchat-sdk';
|
|
7
|
+
import { Layout } from '@ui-kitten/components';
|
|
8
|
+
import DateTimePicker from '@react-native-community/datetimepicker';
|
|
9
|
+
import IonIcon from 'react-native-vector-icons/Ionicons';
|
|
10
|
+
import moment from 'moment';
|
|
11
|
+
import { BottomSheet, Chips, Colors, TextInputField, DateInputField, widthPercentageToDP as wp, isIphoneX, RoundedButton, CustomKeyboardAvoidingView } from '@truworth/twc-rn-common';
|
|
12
|
+
import { ScreenLayout } from '../../components/ScreenLayout';
|
|
13
|
+
import { useSignUp } from './hooks/internal/useSignUp';
|
|
14
|
+
import { useAuthPackageContext } from '../../hooks/internal/useAuthPackageContext';
|
|
15
|
+
import GenderDiversity from '../../../assets/gender-diversity.svg';
|
|
16
|
+
const { gray, primary, utility } = Colors;
|
|
17
|
+
const SignUp = ({ navigation, route }) => {
|
|
18
|
+
const [knowMoreModal, setKnowMoreModal] = useState(false);
|
|
19
|
+
const { loading, firstName, lastName, gender, setGender, datePicker, showDatePicker, selectedDOB, setSelectedDOB, phone, setPhone, referralCode, setReferralCode, countryCode, setCountryCode, error, setError, phoneError, setPhoneError, isPhoneValid, setIsPhoneValid, email, emailLinkedError, existingAccounts, existingAccountModal, setExistingAccountModal, onFirstName, onLastName, handleEmail, handleSubmit, getLoginTypeText, disabled, registrationMethod, } = useSignUp();
|
|
20
|
+
const onChange = (event, selectedDate) => {
|
|
21
|
+
showDatePicker(Platform.OS === 'ios');
|
|
22
|
+
if (selectedDate) {
|
|
23
|
+
setSelectedDOB(moment(selectedDate).format('YYYY-MM-DD'));
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
return (_jsxs(Layout, { style: { flex: 1, backgroundColor: primary.white }, children: [_jsx(CustomKeyboardAvoidingView, { keyboardVerticalOffset: Platform.OS == 'ios' ? 20 : 0, behavior: Platform.OS == 'ios' ? 'padding' : undefined, children: _jsx(ScrollView, { showsVerticalScrollIndicator: false, keyboardShouldPersistTaps: 'always', children: _jsxs(ScreenLayout, { title: "Looks like you're new here!", subTitle: "Tell us more about you so we can setup your account.", buttonProps: {
|
|
27
|
+
label: 'Register',
|
|
28
|
+
loading,
|
|
29
|
+
onPress: () => {
|
|
30
|
+
handleSubmit({
|
|
31
|
+
onResult: () => {
|
|
32
|
+
navigation.navigate('CreatePassword', {
|
|
33
|
+
email: email.length > 0 ? email : route.params?.email || '',
|
|
34
|
+
phone: phone.length > 0 ? phone : route.params?.phone || '',
|
|
35
|
+
firstName,
|
|
36
|
+
lastName,
|
|
37
|
+
gender,
|
|
38
|
+
selectedDOB,
|
|
39
|
+
countryCode,
|
|
40
|
+
referralCode,
|
|
41
|
+
registrationMethod
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
disabled: disabled
|
|
47
|
+
}, children: [_jsxs(View, { style: { flexDirection: 'row', justifyContent: 'space-between' }, children: [_jsx(View, { style: { width: '47%' }, children: _jsx(TextInputField, { label: "First Name", value: firstName, onChangeValue: text => {
|
|
48
|
+
onFirstName(text);
|
|
49
|
+
setError(prev => ({ ...prev, firstName: text.length < 3 }));
|
|
50
|
+
}, error: {
|
|
51
|
+
show: error.firstName ? 'At least 3 letters' : '',
|
|
52
|
+
message: 'Enter at least 3 letters'
|
|
53
|
+
}, autoFocus: true, autoCapitalize: "words", clearButtonMode: "always" }) }), _jsx(View, { style: { width: '47%' }, children: _jsx(TextInputField, { label: "Last Name", value: lastName, onChangeValue: text => {
|
|
54
|
+
onLastName(text);
|
|
55
|
+
setError(prev => ({ ...prev, lastName: text.length < 3 }));
|
|
56
|
+
}, error: {
|
|
57
|
+
show: error.lastName ? 'At least 3 letters' : '',
|
|
58
|
+
message: 'Enter at least 3 letters'
|
|
59
|
+
}, autoCapitalize: "words", clearButtonMode: "always" }) })] }), _jsxs(View, { style: { flexDirection: 'row', marginTop: 32, marginBottom: 16 }, children: [_jsx(Text, { style: {
|
|
60
|
+
fontSize: 14, fontWeight: '600',
|
|
61
|
+
color: gray.gray_900, lineHeight: 16, flex: 1,
|
|
62
|
+
}, children: "Your biological sex at the time of birth" }), _jsx(TouchableOpacity, { activeOpacity: 0.8, onPress: () => setKnowMoreModal(true), children: _jsx(Text, { style: {
|
|
63
|
+
fontSize: 14, fontWeight: '600',
|
|
64
|
+
color: primary.primary_main, lineHeight: 16,
|
|
65
|
+
}, children: "Know More" }) })] }), _jsxs(View, { style: { flexDirection: 'row', justifyContent: 'space-between' }, children: [_jsx(TouchableOpacity, { activeOpacity: 1, style: { width: '48%' }, onPress: () => setGender('F'), children: _jsx(Chips, { label: " Female", leftIcon: "female", size: "large", selected: gender === 'F', containerStyle: { width: wp(42) } }) }), _jsx(TouchableOpacity, { activeOpacity: 1, style: { width: '48%' }, onPress: () => setGender('M'), children: _jsx(Chips, { label: " Male", leftIcon: "male", size: "large", selected: gender === 'M', containerStyle: { width: wp(42) } }) })] }), _jsx(DateInputField, { containerStyle: { marginTop: 32 }, label: 'Date of Birth', value: selectedDOB ? moment(selectedDOB).format('DD/MM/YYYY') : '', onPress: () => {
|
|
66
|
+
Keyboard.dismiss();
|
|
67
|
+
showDatePicker(true);
|
|
68
|
+
} }), registrationMethod == 'email' &&
|
|
69
|
+
_jsx(MobileInput, { phone: phone, setPhone: setPhone, countryCode: countryCode, setCountryCode: setCountryCode, phoneError: phoneError, setPhoneError: setPhoneError, isValid: isPhoneValid, setIsValid: setIsPhoneValid }), registrationMethod == 'mobile' &&
|
|
70
|
+
_jsx(View, { style: { marginTop: 24, marginBottom: 20 }, children: _jsx(TextInputField, { label: "Enter Your Email (Optional)", onChangeValue: handleEmail, value: email, autoFocus: false, autoCapitalize: 'none', keyboardType: "email-address", error: {
|
|
71
|
+
show: Boolean(emailLinkedError),
|
|
72
|
+
message: emailLinkedError
|
|
73
|
+
} }) }), _jsx(TextInputField, { label: "Enter Referral Code (Optional)", onChangeValue: text => setReferralCode(text.toUpperCase()), value: referralCode, autoCapitalize: 'characters', containerStyle: { marginTop: 12 } })] }) }) }), datePicker &&
|
|
74
|
+
_jsxs(View, { style: { width: '100%', backgroundColor: 'white', position: 'absolute', bottom: 0 }, children: [Platform.OS === 'ios' && (_jsx(View, { style: { backgroundColor: '#333', justifyContent: 'flex-end', marginTop: 30, padding: 10, marginLeft: -20, marginRight: 0, flexDirection: 'row', zIndex: 1 }, children: _jsx(TouchableOpacity, { onPress: () => showDatePicker(false), children: _jsx(Text, { style: { textAlign: 'right', fontSize: 14, color: '#FFFFFF' }, children: "Done" }) }) })), _jsx(View, { children: _jsx(DateTimePicker, { minimumDate: new Date(1900, 0, 1), value: selectedDOB ? moment(selectedDOB).toDate() : new Date('1990-01-01'), mode: 'date', display: Platform.OS === 'android' ? 'default' : 'spinner', onChange: onChange, style: { marginTop: 10, flex: 1 }, maximumDate: new Date() }) })] }), knowMoreModal &&
|
|
75
|
+
_jsx(KnowMoreModal, { visible: knowMoreModal, hide: () => setKnowMoreModal(false) }), existingAccountModal &&
|
|
76
|
+
_jsx(ExistingAccountsModal, { phone: phone, countryCode: countryCode, visible: existingAccountModal, hide: () => setExistingAccountModal(false), existingAccounts: existingAccounts, getLoginTypeText: getLoginTypeText })] }));
|
|
77
|
+
};
|
|
78
|
+
const KnowMoreModal = ({ visible, hide }) => {
|
|
79
|
+
const { ref: knowMoreRef, open: openKnowMoreSheet, close: closeKnowMoreSheet } = useModalize();
|
|
80
|
+
const { appConfig } = useAuthPackageContext();
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
if (visible) {
|
|
83
|
+
openKnowMoreSheet();
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
closeKnowMoreSheet();
|
|
87
|
+
}
|
|
88
|
+
}, [visible]);
|
|
89
|
+
return (_jsxs(BottomSheet, { sheetRef: knowMoreRef, onClose: hide, childrenStyle: { padding: 16 }, children: [_jsx(View, { style: { height: 10 } }), _jsxs(View, { style: { flexDirection: 'row', alignItems: 'center' }, children: [_jsx(GenderDiversity, { height: 60, width: 60 }), _jsxs(Text, { style: { marginLeft: 15, flex: 1, fontSize: 18, fontWeight: 'bold', color: '#228186' }, children: ["The ", appConfig.appName, " respects Gender Diversity & Inclusion!"] })] }), _jsxs(Text, { style: { fontSize: 14, color: gray.gray_600, lineHeight: 20, marginTop: 20, }, children: ["The ", appConfig.appName, " aims to provide you with a personalized wellness experience. This requires us to incorporate certain algorithms based on protocols provided by established health & medical institutions around the world. These protocols are based on your biological sex at birth."] }), _jsx(View, { style: { height: 20 } })] }));
|
|
90
|
+
};
|
|
91
|
+
const ExistingAccountsModal = ({ visible, hide, existingAccounts, countryCode, phone, getLoginTypeText }) => {
|
|
92
|
+
const { ref: existingAccountsRef, open: openExistingAccountsSheet, close: closeExistingAccountsSheet } = useModalize();
|
|
93
|
+
const navigation = useNavigation();
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (visible) {
|
|
96
|
+
openExistingAccountsSheet();
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
closeExistingAccountsSheet();
|
|
100
|
+
}
|
|
101
|
+
}, [visible]);
|
|
102
|
+
return (_jsx(BottomSheet, { sheetRef: existingAccountsRef, title: 'Existing Accounts', onClose: hide, childrenStyle: { padding: 16 }, adjustToContentHeight: true, 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: "Mobile Number Already Linked" }), _jsxs(Text, { style: { fontSize: 12, fontWeight: '500', color: gray.gray_500, lineHeight: 18, textAlign: 'center', marginHorizontal: 16, marginTop: 4 }, children: ["The mobile number +", countryCode, " ", String(phone).replace(/\d(?=\d{2})/g, 'X'), " is linked to the following ", existingAccounts.length === 1 ? 'account' : `${existingAccounts.length} accounts`, "."] })] }), _jsx(View, { style: { backgroundColor: gray.gray_200, height: 2, marginVertical: 8 } })] }), flatListProps: {
|
|
103
|
+
showsVerticalScrollIndicator: false,
|
|
104
|
+
contentContainerStyle: { flexGrow: 1 },
|
|
105
|
+
data: existingAccounts,
|
|
106
|
+
keyExtractor: (item, index) => item.memberId || index.toString(),
|
|
107
|
+
ListHeaderComponent: _jsx(_Fragment, { children: _jsxs(Text, { style: { fontSize: 12, fontWeight: '600', color: gray.gray_900, marginHorizontal: 16, marginTop: 8, marginBottom: 8 }, children: ["Please login with any of the below ", existingAccounts.length === 1 ? 'account' : 'accounts', " or contact our support team for assistance."] }) }),
|
|
108
|
+
renderItem: ({ item }) => {
|
|
109
|
+
return (_jsxs(View, { style: {
|
|
110
|
+
padding: 16,
|
|
111
|
+
margin: 8,
|
|
112
|
+
borderWidth: 1,
|
|
113
|
+
borderRadius: 8,
|
|
114
|
+
borderColor: gray.gray_200
|
|
115
|
+
}, children: [_jsxs(View, { 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(View, { style: { height: 1, backgroundColor: gray.gray_200, marginVertical: 8 } }), _jsxs(View, { style: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }, children: [_jsx(Text, { style: { fontSize: 12, fontWeight: '500', color: gray.gray_500 }, children: "Login Type" }), _jsx(Text, { style: { fontSize: 12, fontWeight: '600', color: gray.gray_800 }, children: getLoginTypeText(item.loginType) })] }), _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));
|
|
116
|
+
}
|
|
117
|
+
}, FooterComponent: _jsxs(View, { style: {
|
|
118
|
+
width: '100%',
|
|
119
|
+
backgroundColor: primary.white,
|
|
120
|
+
marginTop: 8,
|
|
121
|
+
padding: 16,
|
|
122
|
+
paddingBottom: isIphoneX() ? 42 : 16,
|
|
123
|
+
borderTopWidth: Platform.OS == 'android' ? 1 : 0,
|
|
124
|
+
borderTopColor: gray.gray_300,
|
|
125
|
+
shadowColor: '#DDDDDD',
|
|
126
|
+
shadowOffset: { width: 0, height: -2 },
|
|
127
|
+
shadowOpacity: 0.5,
|
|
128
|
+
shadowRadius: 3,
|
|
129
|
+
elevation: 3
|
|
130
|
+
}, children: [_jsx(RoundedButton, { label: "Go to Login", size: "large", onPress: () => navigation.navigate('EnterEmail'), containerStyle: { marginBottom: 8 } }), _jsxs(TouchableOpacity, { activeOpacity: 0.8, onPress: () => Freshchat.showConversations(), style: {
|
|
131
|
+
flexDirection: 'row',
|
|
132
|
+
alignItems: 'center',
|
|
133
|
+
justifyContent: 'center',
|
|
134
|
+
padding: 8,
|
|
135
|
+
marginTop: 8
|
|
136
|
+
}, children: [_jsx(IonIcon, { name: 'headset', size: 12, color: primary.primary_main }), _jsx(Text, { style: {
|
|
137
|
+
fontSize: 14,
|
|
138
|
+
fontWeight: '600',
|
|
139
|
+
color: primary.primary_main,
|
|
140
|
+
marginStart: 8
|
|
141
|
+
}, children: "Contact Support" })] })] }) }));
|
|
142
|
+
};
|
|
143
|
+
const MobileInput = ({ phone, setPhone, countryCode, setCountryCode, phoneError, setPhoneError, setIsValid }) => {
|
|
144
|
+
const navigation = useNavigation();
|
|
145
|
+
const route = useRoute();
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
if (route.params?.countryCode) {
|
|
148
|
+
const { countryCode } = route.params;
|
|
149
|
+
setCountryCode(countryCode);
|
|
150
|
+
}
|
|
151
|
+
}, [route.params?.countryCode]);
|
|
152
|
+
const changeCountryCode = () => {
|
|
153
|
+
setIsValid(false);
|
|
154
|
+
setPhone('');
|
|
155
|
+
navigation.navigate('CountryCode', { prevRoute: 'SignUp', ...route.params });
|
|
156
|
+
};
|
|
157
|
+
const onChangeMobile = (text) => {
|
|
158
|
+
setPhoneError(false);
|
|
159
|
+
setPhone(text);
|
|
160
|
+
if (countryCode === '91' && text.length > 9 && /^[0-9\b]+$/.test(text)) {
|
|
161
|
+
setIsValid(true);
|
|
162
|
+
}
|
|
163
|
+
else if (countryCode != '91' && text.length > 5) {
|
|
164
|
+
setIsValid(true);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
setIsValid(false);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
return (_jsxs(View, { style: { marginTop: 16 }, children: [_jsx(Text, { style: { fontSize: 14, fontWeight: '600', color: gray.gray_900 }, children: "Enter Mobile Number" }), _jsxs(View, { style: {
|
|
171
|
+
flexDirection: 'row', borderWidth: 1, borderRadius: 8,
|
|
172
|
+
alignItems: 'center', paddingHorizontal: 12, height: 56,
|
|
173
|
+
backgroundColor: primary.white, marginTop: 12,
|
|
174
|
+
borderColor: phone.length > 0 ? gray.gray_500 : gray.gray_300,
|
|
175
|
+
}, children: [_jsxs(TouchableOpacity, { activeOpacity: 0.8, onPress: changeCountryCode, style: { flexDirection: 'row', alignItems: 'center' }, children: [_jsx(Text, { style: { fontSize: 14, color: primary.black, fontWeight: '500' }, children: `+${countryCode}` }), _jsx(IonIcon, { size: 14, name: 'caret-down', color: gray.gray_900 })] }), _jsx(TextInput, { style: {
|
|
176
|
+
flex: 1, fontSize: 14, fontWeight: '500',
|
|
177
|
+
color: primary.black, marginLeft: 2,
|
|
178
|
+
}, onChangeText: text => onChangeMobile(text), value: phone, keyboardType: "numeric", maxLength: countryCode === '91' ? 10 : 14 }), phone.length > 0 &&
|
|
179
|
+
_jsx(TouchableOpacity, { activeOpacity: 0.8, onPress: () => {
|
|
180
|
+
setPhone('');
|
|
181
|
+
setIsValid(false);
|
|
182
|
+
setPhoneError(false);
|
|
183
|
+
}, style: { position: 'absolute', right: 10 }, children: _jsx(IonIcon, { size: 24, name: 'close', color: gray.gray_900 }) })] }), _jsx(Text, { style: { fontSize: 12, fontWeight: '500', color: utility.danger_main, marginStart: 4, marginTop: 4 }, children: phoneError ? 'This mobile number is already linked with other user' : '' })] }));
|
|
184
|
+
};
|
|
185
|
+
export default SignUp;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { axiosClient } from "../../../../api/axiosClient";
|
|
3
|
+
import { showMessage } from "../../../../helpers/show-message";
|
|
4
|
+
/**
|
|
5
|
+
* @internal
|
|
6
|
+
* Internal hook for managing UserConsent screen state and auth context integration. Not exposed to package consumers.
|
|
7
|
+
*/
|
|
8
|
+
const useConsent = () => {
|
|
9
|
+
const [loading, setLoading] = useState(false);
|
|
10
|
+
const onAgree = ({ registrationParams, source, onResult }) => {
|
|
11
|
+
const { firstName, lastName, selectedDOB, gender, referralCode, email, phone, countryCode, registrationMethod, password } = registrationParams || {};
|
|
12
|
+
const payload = {
|
|
13
|
+
firstName,
|
|
14
|
+
lastName,
|
|
15
|
+
dateOfBirth: selectedDOB,
|
|
16
|
+
gender,
|
|
17
|
+
countryCode,
|
|
18
|
+
source,
|
|
19
|
+
registrationMethod
|
|
20
|
+
};
|
|
21
|
+
if (referralCode) {
|
|
22
|
+
payload.referralCode = referralCode;
|
|
23
|
+
}
|
|
24
|
+
if (password) {
|
|
25
|
+
payload.password = password;
|
|
26
|
+
}
|
|
27
|
+
if (email) {
|
|
28
|
+
payload.email = email;
|
|
29
|
+
}
|
|
30
|
+
if (phone) {
|
|
31
|
+
payload.phone = phone;
|
|
32
|
+
}
|
|
33
|
+
setLoading(true);
|
|
34
|
+
axiosClient({
|
|
35
|
+
url: '/auth/registration/initiate',
|
|
36
|
+
method: 'POST',
|
|
37
|
+
data: payload,
|
|
38
|
+
})
|
|
39
|
+
.then((res) => onResult(res.data))
|
|
40
|
+
.catch((err) => {
|
|
41
|
+
console.log(err);
|
|
42
|
+
showMessage(err?.response?.data?.errors?.[0]);
|
|
43
|
+
})
|
|
44
|
+
.finally(() => setLoading(false));
|
|
45
|
+
};
|
|
46
|
+
return { loading, onAgree };
|
|
47
|
+
};
|
|
48
|
+
export { useConsent };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import dynamic from 'next/dynamic';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import Image from 'next/image';
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
import { Info } from 'lucide-react';
|
|
7
|
+
import { useRouter } from "next/router";
|
|
8
|
+
import { Flex, Typography, ResponsiveModal as Modal, Button } from '@truworth/twc-web-design';
|
|
9
|
+
import { useAuthPackageContext } from '../../hooks/internal/useAuthPackageContext';
|
|
10
|
+
import { CDN_IMAGES_URL } from '@truworth/twc-web-common';
|
|
11
|
+
import { useConsent } from './hooks/internal/useConsent';
|
|
12
|
+
import { ScreenLayout } from "../../components/ScreenLayout";
|
|
13
|
+
import redirectHome from '../../../assets/animation/redirect-home.json';
|
|
14
|
+
const Lottie = dynamic(() => import('react-lottie'), { ssr: false });
|
|
15
|
+
const UserConsent = ({ routeParams, onVerifyEmail, onVerifyMobile, onBackHandler }) => {
|
|
16
|
+
const { email, phone } = routeParams || {};
|
|
17
|
+
const [redirectModal, setRedirectModal] = useState(false);
|
|
18
|
+
const { loading, onAgree } = useConsent();
|
|
19
|
+
const { onLogin, appConfig: { appName, privacyPolicyUrl }, LogoComponent } = useAuthPackageContext();
|
|
20
|
+
const onAgreeHandler = (res) => {
|
|
21
|
+
const { token, member, emailVerificationRequired, mobileVerificationRequired, sessionToken } = res;
|
|
22
|
+
if (token && member) {
|
|
23
|
+
return onLogin({ token, member });
|
|
24
|
+
}
|
|
25
|
+
if (emailVerificationRequired) {
|
|
26
|
+
if (!sessionToken || !email) {
|
|
27
|
+
console.warn('UserConsent: missing sessionToken/email for VerifyEmail');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
return onVerifyEmail({ email, phone, sessionToken });
|
|
31
|
+
}
|
|
32
|
+
if (mobileVerificationRequired) {
|
|
33
|
+
if (!sessionToken || !phone) {
|
|
34
|
+
console.warn('UserConsent: missing sessionToken/phone for VerifyMobile');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
return onVerifyMobile({ phone, sessionToken });
|
|
38
|
+
}
|
|
39
|
+
// Fallback to avoid silent no-op
|
|
40
|
+
console.warn('onAgree returned no actionable flags. Please retry or contact support.');
|
|
41
|
+
};
|
|
42
|
+
return (_jsx(ScreenLayout, { title: _jsxs(Flex, { direction: 'column', className: 'h-full lg:justify-center', children: [React.isValidElement(LogoComponent)
|
|
43
|
+
? LogoComponent
|
|
44
|
+
: typeof LogoComponent === 'function'
|
|
45
|
+
? React.createElement(LogoComponent)
|
|
46
|
+
:
|
|
47
|
+
_jsx(Image, { src: `${CDN_IMAGES_URL ?? ''}/new-twc_logo.svg`, alt: "logo", priority: true, width: 176, height: 40, className: "mb-9 h-auto" }), _jsx(Flex, { className: 'p-0 lg:gap-8 flex-col-reverse lg:flex-row', children: _jsxs(Flex, { direction: 'column', className: 'p-0', children: [_jsx(Typography, { type: 'heading', size: 'h5', className: 'mb-3 text-gray-900', children: "Thank you for your trust & sharing your personal information with us." }), _jsx(Typography, { type: 'heading', size: 'h6', className: "mb-6 text-gray-600", children: "User Consent" }), _jsxs(Typography, { type: 'body', size: 'medium', className: 'lg:text-sm text-gray-800', children: ["I provide ", appName, " with the consent to collect, use, store, share, and/or otherwise process my personal information including but not limited to Name, Gender (biological sex at the time of birth), Date of Birth and Email Address, Mobile Number, and other health vital & lifestyle information). The information is collected for the specified, explicit and legitimate purposes only - which is to assess me or my family's Health Risk, schedule Investigations, Health Check-ups, Doctor Consultations, Procedure, Treatment, provide Health & Wellness Coaching and Payments and ensure that the same is not excessive in relation to the purposes for which it is being collected, and also ensure that such personal information is retained only as long as the user is registered on the platform. I, also agree to receive Email / SMS/WhatsApp alerts and calls in connection with me or my family's health & wellness services."] }), _jsxs(Typography, { type: 'body', size: 'medium', className: "lg:text-sm mt-5 text-gray-800", children: ["Please refer to the 'Terms & Conditions', Privacy & Data Protection Policy listed on ", _jsxs("a", { href: privacyPolicyUrl, target: '_blank', rel: "noopener noreferrer", className: "text-primary block font-semibold", children: [appName, "'s Privacy & Data Protection Policy"] })] }), _jsxs(Flex, { className: '!px-0 flex-col lg:flex-row mt-8', children: [_jsx(Button, { label: "Yes, I Agree", variant: "primary", loading: loading, onClick: () => onAgree({
|
|
48
|
+
registrationParams: routeParams,
|
|
49
|
+
source: 'web',
|
|
50
|
+
onResult: onAgreeHandler
|
|
51
|
+
}), className: "w-full lg:!w-auto lg:!mt-0" }), _jsx(Button, { label: "Not Now, I Will Register Later", variant: "link", onClick: () => setRedirectModal(true), className: "w-full lg:!w-auto lg:!mt-0" })] })] }) })] }), subTitle: "", onPressBack: onBackHandler, children: redirectModal &&
|
|
52
|
+
_jsx(RedirectToHomeModal, { redirectModal: redirectModal }) }));
|
|
53
|
+
};
|
|
54
|
+
const RedirectToHomeModal = ({ redirectModal }) => {
|
|
55
|
+
const router = useRouter();
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
router.push('/login');
|
|
58
|
+
}, []);
|
|
59
|
+
return (_jsxs(Modal, { title: "", open: redirectModal, showCloseButton: false, footer: null, children: [_jsx(Lottie
|
|
60
|
+
/* @ts-ignore */
|
|
61
|
+
, {
|
|
62
|
+
/* @ts-ignore */
|
|
63
|
+
options: {
|
|
64
|
+
animationData: redirectHome,
|
|
65
|
+
loop: true,
|
|
66
|
+
autoplay: true
|
|
67
|
+
}, height: 150, width: 250 }), _jsxs(Flex, { direction: 'column', style: { marginTop: "-30px" }, children: [_jsx(Typography, { type: 'heading', size: 'h5', className: 'text-center mb-6', color: "text-gray-800", children: "Redirecting to the website homepage" }), _jsxs(Flex, { children: [_jsx(Info, { color: 'blue' }), _jsx(Typography, { type: 'body', size: 'small', className: 'text-center mb-6', color: "text-gray-800", children: "We have not stored any information you shared during registration." })] })] })] }));
|
|
68
|
+
};
|
|
69
|
+
export default UserConsent;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ScrollView, Text, TouchableOpacity, Linking, View, Platform } from 'react-native';
|
|
3
|
+
import { Layout } from '@ui-kitten/components';
|
|
4
|
+
import { Colors, Header } from '@truworth/twc-rn-common';
|
|
5
|
+
import { ScreenLayout } from '../../components/ScreenLayout';
|
|
6
|
+
import { useAuthPackageContext } from '../../hooks/internal/useAuthPackageContext';
|
|
7
|
+
import { useConsent } from './hooks/internal/useConsent';
|
|
8
|
+
const { primary, gray } = Colors;
|
|
9
|
+
const UserConsent = ({ navigation, route }) => {
|
|
10
|
+
const { email, phone } = route.params || {};
|
|
11
|
+
const { onLogin, appConfig: { appName, privacyPolicyUrl } } = useAuthPackageContext();
|
|
12
|
+
const { loading, onAgree } = useConsent();
|
|
13
|
+
const onAgreeHandler = (res) => {
|
|
14
|
+
const { token, member, emailVerificationRequired, mobileVerificationRequired, sessionToken } = res;
|
|
15
|
+
if (token && member) {
|
|
16
|
+
return onLogin({ token, member });
|
|
17
|
+
}
|
|
18
|
+
if (emailVerificationRequired) {
|
|
19
|
+
if (!sessionToken || !email) {
|
|
20
|
+
console.warn('UserConsent: missing sessionToken/email for VerifyEmail');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
return navigation.navigate('VerifyEmail', { email, phone, sessionToken });
|
|
24
|
+
}
|
|
25
|
+
if (mobileVerificationRequired) {
|
|
26
|
+
if (!sessionToken || !phone) {
|
|
27
|
+
console.warn('UserConsent: missing sessionToken/phone for VerifyMobile');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
return navigation.navigate('VerifyMobile', { phone, sessionToken });
|
|
31
|
+
}
|
|
32
|
+
console.warn('onAgree returned no actionable flags. Please retry or contact support.');
|
|
33
|
+
};
|
|
34
|
+
return (_jsxs(Layout, { style: { flex: 1, backgroundColor: primary.white }, children: [_jsx(Header, {}), _jsx(ScrollView, { children: _jsx(ScreenLayout, { hideHeader: true, title: "", subTitle: "", buttonProps: {
|
|
35
|
+
loading,
|
|
36
|
+
type: 'secondary',
|
|
37
|
+
label: 'I agree, Register me.',
|
|
38
|
+
onPress: () => onAgree({
|
|
39
|
+
registrationParams: route.params,
|
|
40
|
+
source: Platform.OS,
|
|
41
|
+
onResult: onAgreeHandler
|
|
42
|
+
}),
|
|
43
|
+
disabled: loading,
|
|
44
|
+
}, children: _jsxs(View, { style: { paddingHorizontal: 8 }, children: [_jsxs(Text, { style: { color: gray.gray_600, fontWeight: '400', lineHeight: 24 }, children: ["I provide ", appName, ", with the consent to collect, use, store, share, and / or otherwise process my personal information including but not limited to Name, Gender (biological sex at the time of birth), Date of Birth and Email Address, Mobile Number, and other health vital & lifestyle information).", ' ', "The information is collected for the specified, explicit and legitimate purposes only \u2013 which is to assess me or my family\u2019s Health Risk, schedule Investigations, Health Check-ups, Doctor Consultations, Procedure, Treatment, provide Health & Wellness Coaching and Payments and ensure that the same is not excessive in relation to the purposes for which it is being collected, and also ensure that such personal information is retained only as long as the user is registered on the platform.", ' ', "I, also agree to receive Email / SMS / WhatsApp alerts and calls in connection with me or my family\u2019s health & wellness services.", ' ', "Please refer to the Terms & Conditions, Privacy & Data Protection Policy listed on", ' '] }), _jsx(TouchableOpacity, { style: { marginTop: 16, marginBottom: -12 }, activeOpacity: 0.8, onPress: () => privacyPolicyUrl && Linking.openURL(privacyPolicyUrl), children: _jsxs(Text, { style: { fontSize: 16, fontWeight: '600', color: primary.primary_main, lineHeight: 24 }, children: [appName, "'s Privacy & Data Protection Policy"] }) })] }) }) })] }));
|
|
45
|
+
};
|
|
46
|
+
export default UserConsent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from "react";
|
|
2
|
+
import { showMessage } from "../../../../helpers/show-message";
|
|
3
|
+
import { axiosClient } from "../../../../api/axiosClient";
|
|
4
|
+
/**
|
|
5
|
+
* @internal
|
|
6
|
+
* Hook for managing VerifyEmail screen state and auth context integration.
|
|
7
|
+
* This hook is not exposed to package consumers.
|
|
8
|
+
*/
|
|
9
|
+
const useVerifyEmail = ({ sessionToken }) => {
|
|
10
|
+
const [sessionTokenState, setSessionToken] = useState(sessionToken || '');
|
|
11
|
+
const [resendOTPCounter, setResendOTPCounter] = useState(0);
|
|
12
|
+
const [status, setStatus] = useState('');
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
resendOTP();
|
|
15
|
+
}, []);
|
|
16
|
+
const resendOTP = useCallback(() => {
|
|
17
|
+
if (!sessionTokenState) {
|
|
18
|
+
console.error('useVerifyEmail: sessionToken is required to resend OTP');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
setResendOTPCounter(prevCounter => prevCounter + 1);
|
|
22
|
+
setStatus('loading');
|
|
23
|
+
axiosClient({
|
|
24
|
+
url: '/auth/registration/email/send-otp',
|
|
25
|
+
method: 'POST',
|
|
26
|
+
data: { sessionToken: sessionTokenState },
|
|
27
|
+
}).then((res) => {
|
|
28
|
+
setSessionToken(res.data.sessionToken);
|
|
29
|
+
}).catch((err) => {
|
|
30
|
+
console.log(err);
|
|
31
|
+
showMessage(err?.response?.data?.errors?.[0]?.message);
|
|
32
|
+
}).finally(() => setStatus(''));
|
|
33
|
+
}, [sessionTokenState]);
|
|
34
|
+
const validateOTP = useCallback(({ otp, onVerifiedOTP }) => {
|
|
35
|
+
if (!sessionTokenState) {
|
|
36
|
+
console.error('useVerifyEmail: sessionToken is required to resend OTP');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
setStatus('loading');
|
|
40
|
+
axiosClient({
|
|
41
|
+
url: '/auth/registration/email/verify-otp',
|
|
42
|
+
method: 'POST',
|
|
43
|
+
data: { otp, sessionToken: sessionTokenState },
|
|
44
|
+
}).then((res) => {
|
|
45
|
+
setStatus('valid');
|
|
46
|
+
onVerifiedOTP({ sessionToken: res?.data?.sessionToken });
|
|
47
|
+
setStatus('');
|
|
48
|
+
}).catch((err) => {
|
|
49
|
+
console.log(err);
|
|
50
|
+
if (err?.response?.status === 400) {
|
|
51
|
+
setStatus('invalid');
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
setStatus('');
|
|
54
|
+
}, 5000);
|
|
55
|
+
showMessage(err?.response?.data?.errors?.[0]?.message);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
setStatus('');
|
|
59
|
+
showMessage(err?.response?.data?.errors?.[0]?.message);
|
|
60
|
+
});
|
|
61
|
+
}, [sessionTokenState]);
|
|
62
|
+
return {
|
|
63
|
+
resendOTP,
|
|
64
|
+
validateOTP,
|
|
65
|
+
status,
|
|
66
|
+
resendOTPCounter,
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
export { useVerifyEmail };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useVerifyEmail } from "./hooks/internal/useVerifyEmail";
|
|
3
|
+
import { EmailOTPVerify } from "../../components/EmailOTPVerify";
|
|
4
|
+
const VerifyEmail = ({ email, sessionToken, onVerifiedOTP }) => {
|
|
5
|
+
const { status, resendOTPCounter, validateOTP, resendOTP, } = useVerifyEmail({ sessionToken });
|
|
6
|
+
return (_jsx(EmailOTPVerify, { email: email, status: status, resendOTPCounter: resendOTPCounter, validateOTP: (otp) => validateOTP?.({ otp, onVerifiedOTP }), resendOTP: resendOTP }));
|
|
7
|
+
};
|
|
8
|
+
export default VerifyEmail;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { EmailOTPVerify } from "../../components/EmailOTPVerify";
|
|
3
|
+
import { useVerifyEmail } from "./hooks/internal/useVerifyEmail";
|
|
4
|
+
const VerifyEmail = ({ navigation, route }) => {
|
|
5
|
+
const { phone, sessionToken, email } = route.params || {};
|
|
6
|
+
const { status, resendOTPCounter, validateOTP, resendOTP, } = useVerifyEmail({ sessionToken });
|
|
7
|
+
return (_jsx(EmailOTPVerify, { email: email, status: status, resendOTPCounter: resendOTPCounter, validateOTP: (otp) => validateOTP?.({
|
|
8
|
+
otp,
|
|
9
|
+
onVerifiedOTP: ({ sessionToken }) => {
|
|
10
|
+
navigation.navigate('VerifyMobile', { phone, sessionToken });
|
|
11
|
+
}
|
|
12
|
+
}), resendOTP: resendOTP }));
|
|
13
|
+
};
|
|
14
|
+
export default VerifyEmail;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|