ordering-ui-react-native 0.22.76 → 0.22.77-release

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 (137) hide show
  1. package/package.json +5 -7
  2. package/src/components/BusinessesListing/index.tsx +1 -1
  3. package/src/components/Checkout/index.tsx +40 -39
  4. package/src/components/VerifyPhone/styles.tsx +1 -2
  5. package/src/context/OfflineActions/index.tsx +236 -0
  6. package/src/providers/AlertProvider.tsx +3 -1
  7. package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +5 -3
  8. package/themes/business/src/components/AcceptOrRejectOrder/styles.tsx +1 -0
  9. package/themes/business/src/components/BusinessController/index.tsx +8 -3
  10. package/themes/business/src/components/BusinessProductList/index.tsx +3 -2
  11. package/themes/business/src/components/Chat/index.tsx +15 -3
  12. package/themes/business/src/components/DriverMap/index.tsx +44 -33
  13. package/themes/business/src/components/FloatingButton/index.tsx +3 -2
  14. package/themes/business/src/components/LanguageSelector/index.tsx +1 -1
  15. package/themes/business/src/components/LoginForm/index.tsx +123 -98
  16. package/themes/business/src/components/LogoutButton/index.tsx +13 -4
  17. package/themes/business/src/components/MapView/RenderMarker.tsx +146 -0
  18. package/themes/business/src/components/MapView/index.tsx +68 -142
  19. package/themes/business/src/components/NewOrderNotification/index.tsx +38 -54
  20. package/themes/business/src/components/OrderDetails/Business.tsx +56 -20
  21. package/themes/business/src/components/OrderDetails/Delivery.tsx +111 -42
  22. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +146 -36
  23. package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +51 -28
  24. package/themes/business/src/components/OrderDetails/styles.tsx +39 -3
  25. package/themes/business/src/components/OrderDetails/usePrinterCommands.tsx +17 -16
  26. package/themes/business/src/components/OrderDetailsLogistic/index.tsx +3 -2
  27. package/themes/business/src/components/OrderSummary/index.tsx +271 -176
  28. package/themes/business/src/components/OrdersListManager/index.tsx +13 -1
  29. package/themes/business/src/components/OrdersOption/index.tsx +207 -144
  30. package/themes/business/src/components/OrdersOption/styles.tsx +14 -0
  31. package/themes/business/src/components/PreviousMessages/index.tsx +26 -3
  32. package/themes/business/src/components/PreviousOrders/OrderItem.tsx +20 -8
  33. package/themes/business/src/components/PreviousOrders/index.tsx +74 -66
  34. package/themes/business/src/components/PreviousOrders/styles.tsx +2 -1
  35. package/themes/business/src/components/PrinterEdition/MessageAlert.tsx +33 -0
  36. package/themes/business/src/components/PrinterEdition/index.tsx +143 -75
  37. package/themes/business/src/components/PrinterEdition/printerList.tsx +23 -0
  38. package/themes/business/src/components/PrinterSettings/index.tsx +1 -1
  39. package/themes/business/src/components/ProductItemAccordion/index.tsx +15 -16
  40. package/themes/business/src/components/ReviewCustomer/index.tsx +2 -0
  41. package/themes/business/src/components/StoresList/index.tsx +2 -2
  42. package/themes/business/src/components/UserProfileForm/index.tsx +48 -10
  43. package/themes/business/src/components/UserProfileForm/styles.tsx +7 -0
  44. package/themes/business/src/components/WebsocketStatus/index.tsx +2 -2
  45. package/themes/business/src/config/currency.tsx +1010 -0
  46. package/themes/business/src/hooks/useLocation.tsx +16 -12
  47. package/themes/business/src/layouts/SafeAreaContainer.tsx +35 -19
  48. package/themes/business/src/types/index.tsx +26 -4
  49. package/themes/business/src/utils/index.tsx +26 -2
  50. package/themes/doordash/src/components/BusinessesListing/index.tsx +1 -1
  51. package/themes/doordash/src/components/LoginForm/index.tsx +1 -2
  52. package/themes/instacart/src/components/BusinessesListing/index.tsx +1 -1
  53. package/themes/kiosk/src/components/Checkout/index.tsx +9 -5
  54. package/themes/kiosk/src/components/CustomerName/index.tsx +1 -1
  55. package/themes/kiosk/src/components/NavBar/index.tsx +14 -14
  56. package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
  57. package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +8 -10
  58. package/themes/kiosk/src/components/PaymentOptions/index.tsx +121 -57
  59. package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
  60. package/themes/original/index.tsx +223 -219
  61. package/themes/original/src/components/AddressForm/index.tsx +76 -17
  62. package/themes/original/src/components/AppleLogin/index.tsx +3 -4
  63. package/themes/original/src/components/BusinessController/index.tsx +4 -2
  64. package/themes/original/src/components/BusinessItemAccordion/index.tsx +1 -1
  65. package/themes/original/src/components/BusinessListingSearch/BusinessSearchFooter.tsx +102 -90
  66. package/themes/original/src/components/BusinessListingSearch/BusinessSearchHeader.tsx +7 -3
  67. package/themes/original/src/components/BusinessListingSearch/index.tsx +8 -13
  68. package/themes/original/src/components/BusinessPreorder/index.tsx +30 -17
  69. package/themes/original/src/components/BusinessProductsList/SubcategoriesComponent/index.tsx +72 -69
  70. package/themes/original/src/components/BusinessProductsList/index.tsx +4 -5
  71. package/themes/original/src/components/BusinessProductsList/styles.tsx +0 -3
  72. package/themes/original/src/components/BusinessProductsListing/index.tsx +5 -4
  73. package/themes/original/src/components/BusinessesListing/Layout/Appointment/styles.tsx +1 -0
  74. package/themes/original/src/components/BusinessesListing/Layout/Original/styles.tsx +2 -1
  75. package/themes/original/src/components/Cart/index.tsx +42 -12
  76. package/themes/original/src/components/Checkout/index.tsx +126 -98
  77. package/themes/original/src/components/FloatingButton/index.tsx +1 -1
  78. package/themes/original/src/components/GPSButton/index.tsx +2 -1
  79. package/themes/original/src/components/GoogleMap/index.tsx +3 -2
  80. package/themes/original/src/components/Help/functions.tsx +76 -0
  81. package/themes/original/src/components/Help/index.tsx +74 -29
  82. package/themes/original/src/components/Help/styles.tsx +4 -1
  83. package/themes/original/src/components/HelpOptions/index.tsx +53 -0
  84. package/themes/original/src/components/HighestRatedBusinesses/index.tsx +1 -1
  85. package/themes/original/src/components/Home/index.tsx +36 -11
  86. package/themes/original/src/components/LastOrder/index.tsx +1 -1
  87. package/themes/original/src/components/LoginForm/Otp/index.tsx +1 -1
  88. package/themes/original/src/components/LoginForm/index.tsx +883 -852
  89. package/themes/original/src/components/MessageListing/index.tsx +1 -1
  90. package/themes/original/src/components/Messages/index.tsx +562 -555
  91. package/themes/original/src/components/MomentOption/TimeListItem.tsx +56 -0
  92. package/themes/original/src/components/MomentOption/index.tsx +141 -61
  93. package/themes/original/src/components/MomentOption/styles.tsx +1 -1
  94. package/themes/original/src/components/MomentSelector/index.tsx +5 -2
  95. package/themes/original/src/components/MultiCheckout/index.tsx +78 -33
  96. package/themes/original/src/components/MultiOrdersDetails/SingleOrderCard.tsx +2 -2
  97. package/themes/original/src/components/MultiOrdersDetails/index.tsx +2 -2
  98. package/themes/original/src/components/NavBar/index.tsx +6 -2
  99. package/themes/original/src/components/NotFoundSource/index.tsx +40 -39
  100. package/themes/original/src/components/NotFoundSource/styles.tsx +18 -9
  101. package/themes/original/src/components/OrderDetails/OrderEta.tsx +4 -3
  102. package/themes/original/src/components/OrderDetails/OrderHistory.tsx +11 -4
  103. package/themes/original/src/components/OrderDetails/index.tsx +44 -20
  104. package/themes/original/src/components/OrderDetails/styles.tsx +0 -1
  105. package/themes/original/src/components/OrderProgress/index.tsx +5 -4
  106. package/themes/original/src/components/OrderSummary/index.tsx +32 -11
  107. package/themes/original/src/components/OrderTypeSelector/index.tsx +120 -120
  108. package/themes/original/src/components/OrdersOption/index.tsx +325 -325
  109. package/themes/original/src/components/PaymentOptionWallet/index.tsx +1 -0
  110. package/themes/original/src/components/PaymentOptions/index.tsx +471 -459
  111. package/themes/original/src/components/PhoneInputNumber/index.tsx +92 -7
  112. package/themes/original/src/components/ProductItemAccordion/index.tsx +28 -37
  113. package/themes/original/src/components/ProductOptionSubOption/index.tsx +15 -14
  114. package/themes/original/src/components/ServiceForm/index.tsx +2 -2
  115. package/themes/original/src/components/SignupForm/index.tsx +1010 -971
  116. package/themes/original/src/components/SingleOrderCard/index.tsx +8 -5
  117. package/themes/original/src/components/SingleProductCard/index.tsx +2 -1
  118. package/themes/original/src/components/SingleProductCard/styles.tsx +0 -3
  119. package/themes/original/src/components/StripeCardsList/index.tsx +7 -1
  120. package/themes/original/src/components/StripeElementsForm/index.tsx +2 -2
  121. package/themes/original/src/components/TaxInformation/index.tsx +3 -2
  122. package/themes/original/src/components/UserDetails/index.tsx +17 -16
  123. package/themes/original/src/components/UserFormDetails/index.tsx +109 -67
  124. package/themes/original/src/components/UserVerification/index.tsx +70 -23
  125. package/themes/original/src/components/VerifyPhone/index.tsx +1 -1
  126. package/themes/original/src/components/shared/OInput.tsx +97 -97
  127. package/themes/original/src/components/shared/OModal.tsx +7 -2
  128. package/themes/original/src/providers/AlertProvider.tsx +1 -1
  129. package/themes/original/src/types/index.tsx +700 -695
  130. package/themes/original/src/utils/index.tsx +50 -34
  131. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
  132. package/themes/original/src/components/HelpAccountAndPayment/index.tsx +0 -62
  133. package/themes/original/src/components/HelpAccountAndPayment/styles.tsx +0 -12
  134. package/themes/original/src/components/HelpGuide/index.tsx +0 -68
  135. package/themes/original/src/components/HelpGuide/styles.tsx +0 -12
  136. package/themes/original/src/components/HelpOrder/index.tsx +0 -71
  137. package/themes/original/src/components/HelpOrder/styles.tsx +0 -13
@@ -1,5 +1,5 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
- import { View, Pressable, StyleSheet, Linking, Platform, TouchableOpacity } from 'react-native';
2
+ import { View, Pressable, StyleSheet, Linking, Platform, TouchableOpacity, Modal } from 'react-native';
3
3
  import { useForm, Controller } from 'react-hook-form';
4
4
  import Spinner from 'react-native-loading-spinner-overlay';
5
5
  import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
@@ -11,998 +11,1037 @@ import ReCaptcha from '@fatnlazycat/react-native-recaptcha-v3'
11
11
  import ReactNativeHapticFeedback from "react-native-haptic-feedback";
12
12
 
13
13
  import {
14
- SignupForm as SignUpController,
15
- useLanguage,
16
- useConfig,
17
- useSession,
18
- ToastType,
19
- useToast,
14
+ SignupForm as SignUpController,
15
+ useLanguage,
16
+ useConfig,
17
+ useSession,
18
+ ToastType,
19
+ useToast,
20
20
  } from 'ordering-components/native';
21
21
  import { useTheme } from 'styled-components/native';
22
22
  import { FormSide, FormInput, SocialButtons } from './styles';
23
23
  import { Otp } from '../LoginForm/Otp'
24
24
 
25
25
  import {
26
- ButtonsWrapper,
27
- LoginWith as SignupWith,
28
- TabBtn,
29
- OTab,
30
- OTabs,
31
- RecaptchaButton
26
+ ButtonsWrapper,
27
+ LoginWith as SignupWith,
28
+ TabBtn,
29
+ OTab,
30
+ OTabs,
31
+ RecaptchaButton
32
32
  } from '../LoginForm/styles';
33
33
 
34
34
  import NavBar from '../NavBar';
35
- import { VerifyPhone } from '../VerifyPhone';
36
35
 
37
36
  import Alert from '../../../../../src/providers/AlertProvider'
38
37
  import { OText, OButton, OInput } from '../shared';
39
- import { OModal } from '../../../../../src/components/shared';
40
38
  import { SignupParams } from '../../types';
41
39
  import { sortInputFields } from '../../utils';
42
40
  import { GoogleLogin } from '../GoogleLogin';
43
41
  import { AppleLogin } from '../AppleLogin';
44
42
 
45
43
  const notValidationFields = [
46
- 'coupon',
47
- 'driver_tip',
48
- 'mobile_phone',
49
- 'address',
50
- 'address_notes',
44
+ 'coupon',
45
+ 'driver_tip',
46
+ 'mobile_phone',
47
+ 'address',
48
+ 'address_notes',
51
49
  ];
52
50
 
53
51
  const SignupFormUI = (props: SignupParams) => {
54
- const {
55
- navigation,
56
- loginButtonText,
57
- signupButtonText,
58
- onNavigationRedirect,
59
- formState,
60
- validationFields,
61
- showField,
62
- isRequiredField,
63
- useChekoutFileds,
64
- useSignupByEmail,
65
- useSignupByCellphone,
66
- handleSuccessSignup,
67
- handleButtonSignupClick,
68
- verifyPhoneState,
69
- checkPhoneCodeState,
70
- setCheckPhoneCodeState,
71
- handleSendVerifyCode,
72
- handleCheckPhoneCode,
73
- notificationState,
74
- handleChangePromotions,
75
- enableReCaptcha,
76
- handleReCaptcha,
77
- generateOtpCode,
78
- numOtpInputs,
79
- setWillVerifyOtpState,
80
- handleChangeInput,
81
- willVerifyOtpState,
82
- setOtpState,
83
- setSignUpTab,
84
- signUpTab,
85
- useSignUpFullDetails,
86
- useSignUpOtpEmail,
87
- useSignUpOtpCellphone,
88
- isGuest
89
- } = props;
90
-
91
- const theme = useTheme();
92
-
93
- const style = StyleSheet.create({
94
- btnOutline: {
95
- backgroundColor: '#FFF',
96
- color: theme.colors.primary,
97
- },
98
- inputStyle: {
99
- marginBottom: 20,
100
- borderWidth: 1,
101
- borderRadius: 7.6,
102
- },
103
- wrappText: {
104
- display: 'flex',
105
- flexDirection: 'row',
106
- justifyContent: 'space-between',
107
- marginBottom: 30,
108
- },
109
- line: {
110
- height: 1,
111
- backgroundColor: theme.colors.border,
112
- flexGrow: 1,
113
- marginBottom: 7,
114
- },
115
- checkBoxStyle: {
116
- width: 25,
117
- height: 25,
118
- }
119
- });
120
-
121
- const [, { showToast }] = useToast();
122
- const [, t] = useLanguage();
123
- const [, { login }] = useSession();
124
- const [{ configs }] = useConfig();
125
- const { control, handleSubmit, clearErrors, errors, register, unregister, setValue } = useForm();
126
-
127
- const [passwordSee, setPasswordSee] = useState(false);
128
- const [formValues, setFormValues] = useState(null);
129
- const [isModalVisible, setIsModalVisible] = useState(false);
130
- const [isLoadingVerifyModal, setIsLoadingVerifyModal] = useState(false);
131
- const [isFBLoading, setIsFBLoading] = useState(false);
132
- const [phoneInputData, setPhoneInputData] = useState({
133
- error: '',
134
- phone: {
135
- country_phone_code: null,
136
- cellphone: null,
137
- country_code: null
138
- },
139
- });
140
- const [alertState, setAlertState] = useState({ open: false, title: '', content: [] })
141
- const [recaptchaConfig, setRecaptchaConfig] = useState<any>({})
142
- const [recaptchaVerified, setRecaptchaVerified] = useState(false)
143
- const [tabLayouts, setTabLayouts] = useState<any>({})
144
-
145
- const tabsRef = useRef<any>(null)
146
- const nameRef = useRef<any>(null);
147
- const lastnameRef = useRef<any>(null);
148
- const middleNameRef = useRef<any>(null);
149
- const secondLastnameRef = useRef<any>(null);
150
- const emailRef = useRef<any>(null);
151
- const phoneRef = useRef<any>(null);
152
- const passwordRef = useRef<any>(null);
153
- const recaptchaRef = useRef<any>({});
154
-
155
- const showInputPhoneNumber = (validationFields?.fields?.checkout?.cellphone?.enabled ?? false) || configs?.verification_phone_required?.value === '1'
156
- const googleLoginEnabled = configs?.google_login_enabled?.value === '1' || !configs?.google_login_enabled?.enabled
157
- const facebookLoginEnabled = configs?.facebook_login_enabled?.value === '1' || !configs?.facebook_login_enabled?.enabled
158
- const appleLoginEnabled = Platform.OS === 'ios' && (configs?.apple_login_enabled?.value === '1' || !configs?.apple_login_enabled?.enabled)
159
-
160
- const closeAlert = () => {
161
- setAlertState({
162
- open: false,
163
- title: '',
164
- content: []
165
- })
166
- }
167
-
168
- const vibrateApp = (impact?: string) => {
169
- const options = {
170
- enableVibrateFallback: true,
171
- ignoreAndroidSystemSettings: false
172
- };
173
- ReactNativeHapticFeedback.trigger(impact || "impactLight", options);
174
- }
175
-
176
- const handleRefs = (ref: any, code: string) => {
177
- switch (code) {
178
- case 'name': {
179
- nameRef.current = ref;
180
- break;
181
- }
182
- case 'middle_name': {
183
- middleNameRef.current = ref;
184
- }
185
- case 'lastname': {
186
- lastnameRef.current = ref;
187
- break;
188
- }
189
- case 'second_lastname': {
190
- secondLastnameRef.current = ref;
191
- break;
192
- }
193
- case 'email': {
194
- emailRef.current = ref;
195
- break;
196
- }
197
- }
198
- };
199
-
200
- const handleOnLayout = (event: any, opc: string) => {
201
- const _tabLayouts = { ...tabLayouts }
202
- const categoryKey = opc
203
- _tabLayouts[categoryKey] = event.nativeEvent.layout
204
- setTabLayouts(_tabLayouts)
205
- }
206
-
207
- const handleFocusRef = (code: string) => {
208
- switch (code) {
209
- case 'name': {
210
- nameRef?.current?.focus();
211
- break;
212
- }
213
- case 'middle_name': {
214
- middleNameRef?.current?.focus();
215
- break;
216
- }
217
- case 'lastname': {
218
- lastnameRef?.current?.focus();
219
- break;
220
- }
221
- case 'second_lastname': {
222
- secondLastnameRef?.current?.focus();
223
- break;
224
- }
225
- case 'email': {
226
- emailRef?.current?.focus();
227
- break;
228
- }
229
- }
230
- };
231
-
232
- const getNextFieldCode = (index: number) => {
233
- const fields = sortInputFields({
234
- values: validationFields?.fields?.checkout,
235
- })?.filter(
236
- (field: any) =>
237
- !notValidationFields.includes(field.code) && showField(field.code),
238
- );
239
- return fields[index + 1]?.code;
240
- };
241
-
242
- const handleSuccessFacebook = (user: any) => {
243
- login({
244
- user,
245
- token: user.session.access_token,
246
- });
247
- navigation.navigate('Home');
248
- };
249
-
250
- const handleSignUpTab = (tab: string) => {
251
- setSignUpTab && setSignUpTab(tab)
252
- clearErrors()
253
- }
254
-
255
- const onSubmit = (values?: any) => {
256
- if (phoneInputData.error && signUpTab !== 'otpEmail') {
257
- showToast(ToastType.Error, phoneInputData.error);
258
- vibrateApp()
259
- return;
260
- }
261
- if (
262
- !phoneInputData.phone.country_phone_code &&
263
- !phoneInputData.phone.cellphone &&
264
- ((validationFields?.fields?.checkout?.cellphone?.enabled &&
265
- validationFields?.fields?.checkout?.cellphone?.required) ||
266
- configs?.verification_phone_required?.value === '1') &&
267
- signUpTab !== 'otpEmail'
268
- ) {
269
- showToast(
270
- ToastType.Error,
271
- t(
272
- 'VALIDATION_ERROR_MOBILE_PHONE_REQUIRED',
273
- 'The field Mobile phone is required.',
274
- ),
275
- );
276
- vibrateApp()
277
- return;
278
- }
279
- if (signUpTab === 'otpEmail' || signUpTab === 'otpCellphone') {
280
- generateOtpCode && generateOtpCode({
281
- ...values,
282
- ...((phoneInputData.phone.cellphone !== null && phoneInputData.phone.country_phone_code !== null) && { ...phoneInputData.phone }),
283
- country_code: phoneInputData.phone.country_code
284
- })
285
- return
286
- }
287
- handleButtonSignupClick &&
288
- handleButtonSignupClick({
289
- ...values,
290
- ...((phoneInputData.phone.cellphone !== null && phoneInputData.phone.country_phone_code !== null) && { ...phoneInputData.phone }),
291
- country_code: phoneInputData.phone.country_code
292
- });
293
- if (!formState.loading && formState.result.result && !formState.result.error) {
294
- handleSuccessSignup && handleSuccessSignup(formState.result.result);
295
- }
296
- };
297
-
298
- const handleSingUpOtp = (value: string) => {
299
- setOtpState && setOtpState(value)
300
- }
301
-
302
- const handleVerifyCodeClick = (values: any) => {
303
- const formData = values || formValues;
304
- handleSendVerifyCode &&
305
- handleSendVerifyCode({
306
- ...formData,
307
- ...phoneInputData.phone,
308
- });
309
- setIsLoadingVerifyModal(true);
310
- };
311
-
312
- // get object with rules for hook form inputs
313
- const getInputRules = (field: any) => {
314
- const rules: any = {
315
- required: isRequiredField(field.code)
316
- ? t(
317
- `VALIDATION_ERROR_${field.code.toUpperCase()}_REQUIRED`,
318
- `${field.name} is required`,
319
- ).replace('_attribute_', t(field.name, field.code))
320
- : null,
321
- };
322
- if (field.code && field.code === 'email') {
323
- rules.pattern = {
324
- value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
325
- message: t('INVALID_ERROR_EMAIL', 'Invalid email address').replace(
326
- '_attribute_',
327
- t('EMAIL', 'Email'),
328
- ),
329
- };
330
- }
331
- return rules;
332
- };
333
-
334
- const handleChangeInputEmail = (value: string, onChange: any) => {
335
- onChange(value.toLowerCase().trim().replace(/[&,()%";:ç?<>{}\\[\]\s]/g, ''));
336
- };
337
-
338
- const handleOpenTermsUrl = async (url: any) => {
339
- const supported = await Linking.canOpenURL(url);
340
-
341
- if (supported) {
342
- await Linking.openURL(url);
343
- } else {
344
- showToast(ToastType.Error, t('VALIDATION_ERROR_ACTIVE_URL', 'The _attribute_ is not a valid URL.').replace('_attribute_', t('URL', 'URL')))
345
- vibrateApp()
346
- }
347
- }
348
-
349
- const handleOpenRecaptcha = () => {
350
- setRecaptchaVerified(false)
351
- if (!recaptchaConfig?.siteKey) {
352
- showToast(ToastType.Error, t('NO_RECAPTCHA_SITE_KEY', 'The config doesn\'t have recaptcha site key'));
353
- vibrateApp()
354
- return
355
- }
356
- if (!recaptchaConfig?.baseUrl) {
357
- showToast(ToastType.Error, t('NO_RECAPTCHA_BASE_URL', 'The config doesn\'t have recaptcha base url'));
358
- vibrateApp()
359
- return
360
- }
361
- recaptchaRef.current.open()
362
- }
363
-
364
- const onRecaptchaVerify = (token: any) => {
365
- setRecaptchaVerified(true)
366
- handleReCaptcha && handleReCaptcha({ code: token, version: recaptchaConfig?.version })
367
- }
368
-
369
- useEffect(() => {
370
- if (configs && Object.keys(configs).length > 0 && enableReCaptcha) {
371
- if (configs?.security_recaptcha_type?.value === 'v3' &&
372
- configs?.security_recaptcha_score_v3?.value > 0 &&
373
- configs?.security_recaptcha_site_key_v3?.value
374
- ) {
375
- setRecaptchaConfig({
376
- version: 'v3',
377
- siteKey: configs?.security_recaptcha_site_key_v3?.value || null,
378
- baseUrl: configs?.security_recaptcha_base_url?.value || null
379
- })
380
- return
381
- }
382
- if (configs?.security_recaptcha_site_key?.value) {
383
- setRecaptchaConfig({
384
- version: 'v2',
385
- siteKey: configs?.security_recaptcha_site_key?.value || null,
386
- baseUrl: configs?.security_recaptcha_base_url?.value || null
387
- })
388
- }
389
- }
390
- }, [configs, enableReCaptcha])
391
-
392
- useEffect(() => {
393
- if (!formState.loading && formState.result?.error) {
394
- if (formState.result?.result?.[0] === 'ERROR_AUTH_VERIFICATION_CODE') {
395
- setRecaptchaVerified(false)
396
- setRecaptchaConfig({
397
- version: 'v2',
398
- siteKey: configs?.security_recaptcha_site_key?.value || null,
399
- baseUrl: configs?.security_recaptcha_base_url?.value || null
400
- })
401
- showToast(ToastType.Info, t('TRY_AGAIN', 'Please try again'))
402
- vibrateApp()
403
- return
404
- }
405
- formState.result?.result && formState.result?.result[0]?.includes("_") ?
406
- showToast(ToastType.Error, t(`${formState.result?.result[0]}`, 'Phone number already used')) :
407
- showToast(ToastType.Error, formState.result?.result[0])
408
- formState.result?.result && vibrateApp()
409
- setIsLoadingVerifyModal(false);
410
- }
411
- }, [formState]);
412
-
413
- useEffect(() => {
414
- if (Object.keys(errors).length > 0) {
415
- setIsLoadingVerifyModal(false);
416
- vibrateApp()
417
- }
418
- }, [errors])
419
-
420
- useEffect(() => {
421
- if (signUpTab === 'default' || signUpTab === 'otpCellphone') {
422
- register('cellphone', {
423
- required: isRequiredField('cellphone')
424
- ? t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Mobile phone is required').replace('_attribute_', t('CELLPHONE', 'Cellphone'))
425
- : null
426
- })
427
- } else {
428
- unregister('cellphone')
429
- }
430
- }, [signUpTab])
431
-
432
- useEffect(() => {
433
- if (phoneInputData?.phone?.cellphone) setValue('cellphone', phoneInputData?.phone?.cellphone, '')
434
- else setValue('cellphone', '')
435
- }, [phoneInputData?.phone?.cellphone])
436
-
437
- useEffect(() => {
438
- if (verifyPhoneState && !verifyPhoneState?.loading) {
439
- if (verifyPhoneState.result?.error) {
440
- const message =
441
- typeof verifyPhoneState?.result?.result === 'string'
442
- ? verifyPhoneState?.result?.result
443
- : verifyPhoneState?.result?.result[0];
444
- verifyPhoneState.result?.result && showToast(ToastType.Error, message);
445
- verifyPhoneState.result?.result && vibrateApp()
446
- setIsLoadingVerifyModal(false);
447
- return;
448
- }
449
-
450
- const okResult = verifyPhoneState.result?.result === 'OK';
451
- if (okResult) {
452
- !isModalVisible && setIsModalVisible(true);
453
- setIsLoadingVerifyModal(false);
454
- }
455
- }
456
- }, [verifyPhoneState]);
457
-
458
- useEffect(() => {
459
- setPhoneInputData({
460
- ...phoneInputData,
461
- phone: {
462
- ...phoneInputData.phone,
463
- country_code: configs?.default_country_code?.value
464
- }
465
- })
466
- }, [configs])
467
-
468
- useEffect(() => {
469
- if (checkPhoneCodeState?.result?.error) {
470
- setAlertState({
471
- open: true,
472
- title: (typeof checkPhoneCodeState?.result?.result === 'string' ? checkPhoneCodeState?.result?.result : checkPhoneCodeState?.result?.result[0].toString()) || t('ERROR', 'Error'),
473
- content: []
474
- })
475
- }
476
- }, [checkPhoneCodeState])
477
-
478
- return (
479
- <View>
480
- {isGuest ? (
481
- <OText style={{ textAlign: 'center', marginBottom: 10 }} size={18}>{t('SIGNUP', 'Signup')}</OText>
482
- ) : (
483
- <NavBar
484
- title={t('SIGNUP', 'Signup')}
485
- titleAlign={'center'}
486
- onActionLeft={() => navigation?.canGoBack() && navigation.goBack()}
487
- showCall={false}
488
- btnStyle={{ paddingLeft: 0 }}
489
- titleWrapStyle={{ paddingHorizontal: 0 }}
490
- titleStyle={{ marginLeft: 0, marginRight: 0 }}
491
- />
492
- )}
493
- <FormSide>
494
- {((Number(useSignUpFullDetails) + Number(useSignUpOtpEmail) + Number(useSignUpOtpCellphone)) > 1) && (
495
- <SignupWith>
496
- <OTabs
497
- horizontal
498
- showsHorizontalScrollIndicator={false}
499
- ref={tabsRef}
500
- >
501
- {useSignUpFullDetails && (
502
- <TabBtn
503
- onPress={() => handleSignUpTab('default')}
504
- onLayout={(event: any) => handleOnLayout(event, 'default')}
505
- >
506
- <OTab
507
- style={{
508
- borderBottomColor:
509
- signUpTab === 'default'
510
- ? theme.colors.textNormal
511
- : theme.colors.border,
512
- }}>
513
- <OText
514
- size={14}
515
- color={
516
- signUpTab === 'default'
517
- ? theme.colors.textNormal
518
- : theme.colors.disabled
519
- }
520
- weight={signUpTab === 'default' ? 'bold' : 'normal'}>
521
- {t('DEFAULT', 'Default')}
522
- </OText>
523
- </OTab>
524
- </TabBtn>
525
- )}
526
- {useSignUpOtpEmail && (
527
- <TabBtn
528
- onPress={() => handleSignUpTab('otpEmail')}
529
- onLayout={(event: any) => handleOnLayout(event, 'otpEmail')}
530
- >
531
- <OTab
532
- style={{
533
- borderBottomColor:
534
- signUpTab === 'otpEmail'
535
- ? theme.colors.textNormal
536
- : theme.colors.border,
537
- }}>
538
- <OText
539
- size={14}
540
- color={
541
- signUpTab === 'otpEmail'
542
- ? theme.colors.textNormal
543
- : theme.colors.disabled
544
- }
545
- weight={signUpTab === 'otpEmail' ? 'bold' : 'normal'}>
546
- {t('BY_OTP_EMAIL', 'by Otp Email')}
547
- </OText>
548
- </OTab>
549
- </TabBtn>
550
-
551
- )}
552
- {useSignUpOtpCellphone && (
553
- <TabBtn
554
- onPress={() => handleSignUpTab('otpCellphone')}
555
- onLayout={(event: any) => handleOnLayout(event, 'otpCellphone')}
556
- >
557
- <OTab
558
- style={{
559
- borderBottomColor:
560
- signUpTab === 'otpCellphone'
561
- ? theme.colors.textNormal
562
- : theme.colors.border,
563
- }}>
564
- <OText
565
- size={14}
566
- color={
567
- signUpTab === 'otpCellphone'
568
- ? theme.colors.textNormal
569
- : theme.colors.disabled
570
- }
571
- weight={signUpTab === 'otpCellphone' ? 'bold' : 'normal'}>
572
- {t('BY_OTP_CELLPHONE', 'by Otp Cellphone')}
573
- </OText>
574
- </OTab>
575
- </TabBtn>
576
- )}
577
- </OTabs>
578
- </SignupWith>
579
- )}
580
- <FormInput>
581
- {!(useChekoutFileds && validationFields?.loading) ? (
582
- <>
583
- {sortInputFields({
584
- values: validationFields?.fields?.checkout,
585
- }).map(
586
- (item: any, i: number) => {
587
- const field = item?.validation_field || item
588
- return (!notValidationFields.includes(field.code) &&
589
- showField &&
590
- showField(field.code) &&
591
- (signUpTab === 'default' ||
592
- (signUpTab === 'otpEmail' && field.code === 'email')) && (
593
- <React.Fragment key={field.id}>
594
- {errors?.[`${field.code}`] && (
595
- <OText
596
- size={14}
597
- color={theme.colors.danger5}
598
- weight={'normal'}>
599
- {errors?.[`${field.code}`]?.message} {errors?.[`${field.code}`]?.type === 'required' && '*'}
600
- </OText>
601
- )}
602
- <Controller
603
- control={control}
604
- render={({ onChange, value }: any) => (
605
- <OInput
606
- placeholder={t(field.name?.replace(/\s/g, '_')?.toUpperCase(), field.name)}
607
- style={style.inputStyle}
608
- icon={
609
- field.code === 'email'
610
- ? theme.images.general.email
611
- : theme.images.general.user
612
- }
613
- value={value}
614
- onChange={(val: any) =>
615
- field.code !== 'email'
616
- ? (onChange(val))
617
- : handleChangeInputEmail(val, onChange)
618
- }
619
- autoCapitalize={
620
- field.code === 'email' ? 'none' : 'sentences'
621
- }
622
- autoCorrect={field.code === 'email' && false}
623
- type={
624
- field.code === 'email' ? 'email-address' : 'default'
625
- }
626
- autoCompleteType={
627
- field.code === 'email' ? 'email' : 'off'
628
- }
629
- returnKeyType="next"
630
- blurOnSubmit={false}
631
- forwardRef={(ref: any) => handleRefs(ref, field.code)}
632
- onSubmitEditing={() =>
633
- field.code === 'email'
634
- ? phoneRef?.current?.focus?.()
635
- : handleFocusRef(getNextFieldCode(i))
636
- }
637
- borderColor={errors?.[`${field.code}`] ? theme.colors.danger5 : theme.colors.border}
638
- />
639
- )}
640
- name={field.code}
641
- rules={getInputRules(field)}
642
- defaultValue=""
643
- />
644
- </React.Fragment>
645
- ))
646
- }
647
- )}
648
-
649
- {(!!showInputPhoneNumber && (signUpTab === 'default' || signUpTab === 'otpCellphone')) && (
650
- <View style={{ marginBottom: 25 }}>
651
- <PhoneInputNumber
652
- data={phoneInputData}
653
- handleData={(val: any) => setPhoneInputData({
654
- ...phoneInputData,
655
- ...val,
656
- phone: {
657
- ...phoneInputData.phone,
658
- ...val.phone,
659
- country_code: phoneInputData.phone.country_code
660
- }
661
- })}
662
- forwardRef={phoneRef}
663
- changeCountry={(val: any) => setPhoneInputData({
664
- ...phoneInputData,
665
- phone: {
666
- ...phoneInputData.phone,
667
- country_code: val.cca2
668
- }
669
- })}
670
- textInputProps={{
671
- returnKeyType: 'next',
672
- onSubmitEditing: () => passwordRef?.current?.focus?.(),
673
- }}
674
- isStartValidation={errors?.cellphone}
675
- />
676
- </View>
677
- )}
678
-
679
- {(enableReCaptcha && recaptchaConfig?.version) && (
680
- <>
681
- {recaptchaConfig?.version === 'v3' ? (
682
- <ReCaptcha
683
- url={recaptchaConfig?.baseUrl}
684
- siteKey={recaptchaConfig?.siteKey}
685
- containerStyle={{ height: 40 }}
686
- onExecute={onRecaptchaVerify}
687
- reCaptchaType={1}
688
- />
689
- ) : (
690
- <>
691
- <TouchableOpacity
692
- onPress={handleOpenRecaptcha}
693
- style={{ marginHorizontal: 4, marginBottom: 10 }}
694
- >
695
- <RecaptchaButton>
696
- {recaptchaVerified ? (
697
- <MaterialCommunityIcons
698
- name="checkbox-marked"
699
- size={23}
700
- color={theme.colors.primary}
701
- />
702
- ) : (
703
- <MaterialCommunityIcons
704
- name="checkbox-blank-outline"
705
- size={23}
706
- color={theme.colors.disabled}
707
- />
708
- )}
709
- <OText size={14} mLeft={8}>{t('VERIFY_ReCAPTCHA', 'Verify reCAPTCHA')}</OText>
710
- </RecaptchaButton>
711
- </TouchableOpacity>
712
- <Recaptcha
713
- ref={recaptchaRef}
714
- siteKey={recaptchaConfig?.siteKey}
715
- baseUrl={recaptchaConfig?.baseUrl}
716
- onVerify={onRecaptchaVerify}
717
- onExpire={() => setRecaptchaVerified(false)}
718
- />
719
- </>
720
- )}
721
-
722
- </>
723
- )}
724
- {(signUpTab === 'default') && (
725
- <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
726
- <Controller
727
- control={control}
728
- render={({ onChange, value }: any) => (
729
- <CheckBox
730
- value={value}
731
- onValueChange={newValue => {
732
- onChange(newValue)
733
- handleChangePromotions()
734
- }}
735
- boxType={'square'}
736
- tintColors={{
737
- true: theme.colors.primary,
738
- false: theme.colors.disabled
739
- }}
740
- tintColor={theme.colors.disabled}
741
- onCheckColor={theme.colors.primary}
742
- onTintColor={theme.colors.primary}
743
- style={Platform.OS === 'ios' && style.checkBoxStyle}
744
- />
745
- )}
746
- name='promotions'
747
- defaultValue={false}
748
- />
749
- <OText style={{ fontSize: 14, paddingHorizontal: 5 }}>{t('RECEIVE_NEWS_EXCLUSIVE_PROMOTIONS', 'Receive newsletters and exclusive promotions')}</OText>
750
- </View>
751
- )}
752
- {configs?.terms_and_conditions?.value === 'true' && (
753
- <>
754
- {errors?.termsAccept && (
755
- <OText
756
- size={14}
757
- color={theme.colors.danger5}
758
- weight={'normal'}>
759
- {errors?.termsAccept?.message}*
760
- </OText>
761
- )}
762
- <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
763
- <Controller
764
- control={control}
765
- render={({ onChange, value }: any) => (
766
- <CheckBox
767
- value={value}
768
- onValueChange={newValue => {
769
- onChange(newValue)
770
- }}
771
- boxType={'square'}
772
- tintColors={{
773
- true: theme.colors.primary,
774
- false: theme.colors.disabled
775
- }}
776
- tintColor={theme.colors.disabled}
777
- onCheckColor={theme.colors.primary}
778
- onTintColor={theme.colors.primary}
779
- style={Platform.OS === 'ios' && style.checkBoxStyle}
780
- />
781
- )}
782
- name='termsAccept'
783
- rules={{
784
- required: t('VALIDATION_ERROR_ACCEPTED', 'The _attribute_ must be accepted.').replace('_attribute_', t('TERMS_AND_CONDITIONS', 'Terms & Conditions'))
785
- }}
786
- defaultValue={false}
787
- />
788
- <OText style={{ fontSize: 14, paddingHorizontal: 5 }}>{t('TERMS_AND_CONDITIONS_TEXT', 'I agree with')}</OText>
789
- <OButton
790
- imgRightSrc={null}
791
- text={t('TERMS_AND_CONDITIONS', 'Terms & Conditions')}
792
- bgColor={theme.colors.white}
793
- borderColor={theme.colors.white}
794
- style={{ paddingLeft: 0, paddingRight: 0, height: 30, shadowColor: theme.colors.white }}
795
- textStyle={{ color: theme.colors.primary, marginLeft: 0, marginRight: 0 }}
796
- onClick={() => handleOpenTermsUrl(configs?.terms_and_conditions_url?.value)}
797
- />
798
- </View>
799
- </>
800
-
801
- )}
802
-
803
- {signUpTab === 'default' && (
804
- <>
805
- {errors?.password && (
806
- <OText
807
- size={14}
808
- color={theme.colors.danger5}
809
- weight={'normal'}>
810
- {errors?.password?.message} {errors?.password?.type === 'required' && '*'}
811
- </OText>
812
- )}
813
- <Controller
814
- control={control}
815
- render={({ onChange, value }: any) => (
816
- <OInput
817
- isSecured={!passwordSee ? true : false}
818
- placeholder={t('PASSWORD', 'Password')}
819
- style={style.inputStyle}
820
- icon={theme.images.general.lock}
821
- iconCustomRight={
822
- !passwordSee ? (
823
- <MaterialCommunityIcons
824
- name="eye-outline"
825
- color={theme.colors.disabled}
826
- size={24}
827
- onPress={() => setPasswordSee(!passwordSee)}
828
- />
829
- ) : (
830
- <MaterialCommunityIcons
831
- name="eye-off-outline"
832
- color={theme.colors.disabled}
833
- size={24}
834
- onPress={() => setPasswordSee(!passwordSee)}
835
- />
836
- )
837
- }
838
- autoCapitalize='none'
839
- value={value}
840
- onChange={(val: any) => onChange(val)}
841
- returnKeyType="done"
842
- onSubmitEditing={handleSubmit(onSubmit)}
843
- blurOnSubmit
844
- forwardRef={passwordRef}
845
- borderColor={errors?.password ? theme.colors.danger5 : theme.colors.border}
846
- />
847
- )}
848
- name="password"
849
- rules={{
850
- required: isRequiredField('password')
851
- ? t(
852
- 'VALIDATION_ERROR_PASSWORD_REQUIRED',
853
- 'The field Password is required',
854
- ).replace('_attribute_', t('PASSWORD', 'password'))
855
- : null,
856
- minLength: {
857
- value: 8,
858
- message: t(
859
- 'VALIDATION_ERROR_PASSWORD_MIN_STRING',
860
- 'The Password must be at least 8 characters.',
861
- )
862
- .replace('_attribute_', t('PASSWORD', 'Password'))
863
- .replace('_min_', 8),
864
- },
865
- }}
866
- defaultValue=""
867
- />
868
- </>
869
-
870
- )}
871
- </>
872
- ) : (
873
- <Spinner visible />
874
- )}
875
-
876
- {(signUpTab === 'otpEmail' || signUpTab === 'otpCellphone') ? (
877
- <OButton
878
- onClick={handleSubmit(onSubmit)}
879
- text={t('GET_VERIFY_CODE', 'Get Verify Code')}
880
- imgRightSrc={null}
881
- isLoading={isLoadingVerifyModal}
882
- indicatorColor={theme.colors.white}
883
- style={{ borderRadius: 7.6, marginTop: 6 }}
884
- />
885
- ) : (
886
- <OButton
887
- onClick={handleSubmit(onSubmit)}
888
- text={signupButtonText}
889
- imgRightSrc={null}
890
- isDisabled={formState.loading || validationFields.loading}
891
- style={{ borderRadius: 7.6, marginTop: 6, shadowOpacity: 0 }}
892
- />
893
- )}
894
- </FormInput>
895
-
896
- {
897
- onNavigationRedirect && loginButtonText && (
898
- <View style={style.wrappText}>
899
- <OText size={14} style={{ marginRight: 5 }}>
900
- {t('MOBILE_FRONT_ALREADY_HAVE_AN_ACCOUNT', 'Already have an account?')}
901
- </OText>
902
- <Pressable onPress={() => onNavigationRedirect('Login')}>
903
- <OText size={14} color={theme.colors.primary}>
904
- {loginButtonText}
905
- </OText>
906
- </Pressable>
907
- </View>
908
- )
909
- }
910
- {configs && Object.keys(configs).length > 0 && !isGuest && (
911
- (((configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') && configs?.facebook_id?.value && facebookLoginEnabled) ||
912
- ((configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && googleLoginEnabled) ||
913
- ((configs?.apple_login_client_id?.value !== '' && configs?.apple_login_client_id?.value !== null) && appleLoginEnabled)) &&
914
- (
915
- <>
916
- <View
917
- style={{
918
- flexDirection: 'row',
919
- width: '100%',
920
- justifyContent: 'space-between',
921
- alignItems: 'center',
922
- marginVertical: 30,
923
- }}>
924
- <View style={style.line} />
925
- <OText
926
- size={14}
927
- mBottom={10}
928
- style={{ paddingHorizontal: 19 }}
929
- color={theme.colors.disabled}>
930
- {t('OR', 'or')}
931
- </OText>
932
- <View style={style.line} />
933
- </View>
934
- <ButtonsWrapper>
935
- <SocialButtons>
936
- {(configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') &&
937
- configs?.facebook_id?.value &&
938
- facebookLoginEnabled &&
939
- (
940
- <FacebookLogin
941
- notificationState={notificationState}
942
- handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
943
- handleLoading={(val: boolean) => setIsFBLoading(val)}
944
- handleSuccessFacebookLogin={handleSuccessFacebook}
945
- />
946
- )}
947
- {(configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && googleLoginEnabled && (
948
- <GoogleLogin
949
- notificationState={notificationState}
950
- webClientId={configs?.google_login_client_id?.value}
951
- handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
952
- handleLoading={(val: boolean) => setIsFBLoading(val)}
953
- handleSuccessGoogleLogin={handleSuccessFacebook}
954
- />
955
- )}
956
- {(configs?.apple_login_client_id?.value !== '' && configs?.apple_login_client_id?.value !== null) && appleLoginEnabled && (
957
- <AppleLogin
958
- notificationState={notificationState}
959
- handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
960
- handleLoading={(val: boolean) => setIsFBLoading(val)}
961
- handleSuccessAppleLogin={handleSuccessFacebook}
962
- />
963
- )}
964
- </SocialButtons>
965
- </ButtonsWrapper>
966
- </>
967
- )
968
- )}
969
- </FormSide>
970
- <OModal
971
- open={willVerifyOtpState}
972
- onClose={() => setWillVerifyOtpState && setWillVerifyOtpState(false)}
973
- entireModal
974
- title={t('ENTER_VERIFICATION_CODE', 'Enter verification code')}
975
- >
976
- <Otp
977
- pinCount={numOtpInputs || 6}
978
- willVerifyOtpState={willVerifyOtpState || false}
979
- setWillVerifyOtpState={() => setWillVerifyOtpState && setWillVerifyOtpState(false)}
980
- handleLoginOtp={handleSingUpOtp}
981
- onSubmit={onSubmit}
982
- setAlertState={setAlertState}
983
- />
984
- </OModal>
985
- <Spinner
986
- visible={formState.loading || validationFields.loading || isFBLoading}
987
- />
988
- <Alert
989
- open={alertState.open}
990
- content={alertState.content}
991
- title={alertState.title || ''}
992
- onAccept={closeAlert}
993
- onClose={closeAlert}
994
- />
995
- </View>
996
- );
52
+ const {
53
+ navigation,
54
+ loginButtonText,
55
+ signupButtonText,
56
+ onNavigationRedirect,
57
+ formState,
58
+ validationFields,
59
+ showField,
60
+ isRequiredField,
61
+ useChekoutFileds,
62
+ useSignupByEmail,
63
+ useSignupByCellphone,
64
+ handleSuccessSignup,
65
+ handleButtonSignupClick,
66
+ verifyPhoneState,
67
+ checkPhoneCodeState,
68
+ setCheckPhoneCodeState,
69
+ handleSendVerifyCode,
70
+ handleCheckPhoneCode,
71
+ notificationState,
72
+ handleChangePromotions,
73
+ enableReCaptcha,
74
+ handleReCaptcha,
75
+ generateOtpCode,
76
+ numOtpInputs,
77
+ setWillVerifyOtpState,
78
+ handleChangeInput,
79
+ willVerifyOtpState,
80
+ setOtpState,
81
+ setSignUpTab,
82
+ signUpTab,
83
+ useSignUpFullDetails,
84
+ useSignUpOtpEmail,
85
+ useSignUpOtpCellphone,
86
+ useSignUpOtpWhatsapp,
87
+ isGuest,
88
+ setCellphoneStartZero
89
+ } = props;
90
+
91
+ const theme = useTheme();
92
+
93
+ const style = StyleSheet.create({
94
+ btnOutline: {
95
+ backgroundColor: '#FFF',
96
+ color: theme.colors.primary,
97
+ },
98
+ inputStyle: {
99
+ marginBottom: 20,
100
+ borderWidth: 1,
101
+ borderRadius: 7.6,
102
+ },
103
+ wrappText: {
104
+ display: 'flex',
105
+ flexDirection: 'row',
106
+ justifyContent: 'space-between',
107
+ marginBottom: 30,
108
+ },
109
+ line: {
110
+ height: 1,
111
+ backgroundColor: theme.colors.border,
112
+ flexGrow: 1,
113
+ marginBottom: 7,
114
+ },
115
+ checkBoxStyle: {
116
+ width: 25,
117
+ height: 25,
118
+ }
119
+ });
120
+
121
+ const [, { showToast }] = useToast();
122
+ const [, t] = useLanguage();
123
+ const [, { login }] = useSession();
124
+ const [{ configs }] = useConfig();
125
+ const { control, handleSubmit, clearErrors, errors, register, unregister, setValue } = useForm();
126
+
127
+ const [passwordSee, setPasswordSee] = useState(false);
128
+ const [formValues, setFormValues] = useState(null);
129
+ const [isModalVisible, setIsModalVisible] = useState(false);
130
+ const [isLoadingVerifyModal, setIsLoadingVerifyModal] = useState(false);
131
+ const [isFBLoading, setIsFBLoading] = useState(false);
132
+ const [phoneInputData, setPhoneInputData] = useState({
133
+ error: '',
134
+ phone: {
135
+ country_phone_code: null,
136
+ cellphone: null,
137
+ country_code: null
138
+ },
139
+ });
140
+ const [alertState, setAlertState] = useState({ open: false, title: '', content: [] })
141
+ const [recaptchaConfig, setRecaptchaConfig] = useState<any>({})
142
+ const [recaptchaVerified, setRecaptchaVerified] = useState(false)
143
+ const [tabLayouts, setTabLayouts] = useState<any>({})
144
+ const [isCheckingCode, setCheckingCode] = useState(false)
145
+ const [otpError, setOtpError] = useState(null)
146
+
147
+ const tabsRef = useRef<any>(null)
148
+ const nameRef = useRef<any>(null);
149
+ const lastnameRef = useRef<any>(null);
150
+ const middleNameRef = useRef<any>(null);
151
+ const secondLastnameRef = useRef<any>(null);
152
+ const emailRef = useRef<any>(null);
153
+ const phoneRef = useRef<any>(null);
154
+ const passwordRef = useRef<any>(null);
155
+ const recaptchaRef = useRef<any>({});
156
+ const otpChannelRef = useRef<number>(2);
157
+
158
+ const showInputPhoneNumber = (validationFields?.fields?.checkout?.cellphone?.enabled ?? false) || configs?.verification_phone_required?.value === '1'
159
+ const googleLoginEnabled = configs?.google_login_enabled?.value === '1'
160
+ const facebookLoginEnabled = configs?.facebook_login_enabled?.value === '1'
161
+ const appleLoginEnabled = Platform.OS === 'ios' && configs?.apple_login_enabled?.value === '1'
162
+
163
+ const closeAlert = () => {
164
+ setAlertState({
165
+ open: false,
166
+ title: '',
167
+ content: []
168
+ })
169
+ }
170
+
171
+ const vibrateApp = (impact?: string) => {
172
+ const options = {
173
+ enableVibrateFallback: true,
174
+ ignoreAndroidSystemSettings: false
175
+ };
176
+ ReactNativeHapticFeedback.trigger(impact || "impactLight", options);
177
+ }
178
+
179
+ const handleRefs = (ref: any, code: string) => {
180
+ switch (code) {
181
+ case 'name': {
182
+ nameRef.current = ref;
183
+ break;
184
+ }
185
+ case 'middle_name': {
186
+ middleNameRef.current = ref;
187
+ }
188
+ case 'lastname': {
189
+ lastnameRef.current = ref;
190
+ break;
191
+ }
192
+ case 'second_lastname': {
193
+ secondLastnameRef.current = ref;
194
+ break;
195
+ }
196
+ case 'email': {
197
+ emailRef.current = ref;
198
+ break;
199
+ }
200
+ }
201
+ };
202
+
203
+ const handleOnLayout = (event: any, opc: string) => {
204
+ const _tabLayouts = { ...tabLayouts }
205
+ const categoryKey = opc
206
+ _tabLayouts[categoryKey] = event.nativeEvent.layout
207
+ setTabLayouts(_tabLayouts)
208
+ }
209
+
210
+ const handleFocusRef = (code: string) => {
211
+ switch (code) {
212
+ case 'name': {
213
+ nameRef?.current?.focus();
214
+ break;
215
+ }
216
+ case 'middle_name': {
217
+ middleNameRef?.current?.focus();
218
+ break;
219
+ }
220
+ case 'lastname': {
221
+ lastnameRef?.current?.focus();
222
+ break;
223
+ }
224
+ case 'second_lastname': {
225
+ secondLastnameRef?.current?.focus();
226
+ break;
227
+ }
228
+ case 'email': {
229
+ emailRef?.current?.focus();
230
+ break;
231
+ }
232
+ }
233
+ };
234
+
235
+ const getNextFieldCode = (index: number) => {
236
+ const fields = sortInputFields({
237
+ values: validationFields?.fields?.checkout,
238
+ })?.filter(
239
+ (field: any) =>
240
+ !notValidationFields.includes(field.code) && showField(field.code),
241
+ );
242
+ return fields[index + 1]?.code;
243
+ };
244
+
245
+ const handleSuccessFacebook = (user: any) => {
246
+ login({
247
+ user,
248
+ token: user.session.access_token,
249
+ });
250
+ navigation.navigate('Home');
251
+ };
252
+
253
+ const handleSignUpTab = (tab: string) => {
254
+ setSignUpTab && setSignUpTab(tab)
255
+ clearErrors()
256
+ }
257
+
258
+ const onSubmit = (values?: any) => {
259
+ if (phoneInputData.error && signUpTab !== 'otpEmail') {
260
+ showToast(ToastType.Error, phoneInputData.error);
261
+ vibrateApp()
262
+ return;
263
+ }
264
+ if (
265
+ !phoneInputData.phone.country_phone_code &&
266
+ !phoneInputData.phone.cellphone &&
267
+ ((validationFields?.fields?.checkout?.cellphone?.enabled &&
268
+ validationFields?.fields?.checkout?.cellphone?.required) ||
269
+ configs?.verification_phone_required?.value === '1') &&
270
+ signUpTab !== 'otpEmail'
271
+ ) {
272
+ showToast(
273
+ ToastType.Error,
274
+ t(
275
+ 'VALIDATION_ERROR_MOBILE_PHONE_REQUIRED',
276
+ 'The field Mobile phone is required.',
277
+ ),
278
+ );
279
+ vibrateApp()
280
+ return;
281
+ }
282
+ if (signUpTab === 'otpEmail' || signUpTab === 'otpCellphone') {
283
+ generateOtpCode && generateOtpCode({
284
+ ...values,
285
+ ...((phoneInputData.phone.cellphone !== null && phoneInputData.phone.country_phone_code !== null) && { ...phoneInputData.phone }),
286
+ country_code: phoneInputData.phone.country_code
287
+ }, otpChannelRef.current)
288
+ return
289
+ }
290
+ handleButtonSignupClick &&
291
+ handleButtonSignupClick({
292
+ ...values,
293
+ ...((phoneInputData.phone.cellphone !== null && phoneInputData.phone.country_phone_code !== null) && { ...phoneInputData.phone }),
294
+ country_code: phoneInputData.phone.country_code
295
+ });
296
+ if (!formState.loading && formState.result.result && !formState.result.error) {
297
+ handleSuccessSignup && handleSuccessSignup(formState.result.result);
298
+ }
299
+ };
300
+
301
+ const handleSingUpOtp = (value: string) => {
302
+ setOtpState && setOtpState(value)
303
+ }
304
+
305
+ const handleVerifyCodeClick = (values: any) => {
306
+ const formData = values || formValues;
307
+ handleSendVerifyCode &&
308
+ handleSendVerifyCode({
309
+ ...formData,
310
+ ...phoneInputData.phone,
311
+ });
312
+ setIsLoadingVerifyModal(true);
313
+ };
314
+
315
+ // get object with rules for hook form inputs
316
+ const getInputRules = (field: any) => {
317
+ const rules: any = {
318
+ required: isRequiredField(field.code)
319
+ ? t(
320
+ `VALIDATION_ERROR_${field.code.toUpperCase()}_REQUIRED`,
321
+ `${field.name} is required`,
322
+ ).replace('_attribute_', t(field.name, field.code))
323
+ : null,
324
+ };
325
+ if (field.code && field.code === 'email') {
326
+ rules.pattern = {
327
+ value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
328
+ message: t('INVALID_ERROR_EMAIL', 'Invalid email address').replace(
329
+ '_attribute_',
330
+ t('EMAIL', 'Email'),
331
+ ),
332
+ };
333
+ }
334
+ return rules;
335
+ };
336
+
337
+ const handleChangeInputEmail = (value: string, onChange: any) => {
338
+ onChange(value.toLowerCase().trim().replace(/[&,()%";:ç?<>{}\\[\]\s]/g, ''));
339
+ };
340
+
341
+ const handleOpenTermsUrl = async (url: any) => {
342
+ const supported = await Linking.canOpenURL(url);
343
+
344
+ if (supported) {
345
+ await Linking.openURL(url);
346
+ } else {
347
+ showToast(ToastType.Error, t('VALIDATION_ERROR_ACTIVE_URL', 'The _attribute_ is not a valid URL.').replace('_attribute_', t('URL', 'URL')))
348
+ vibrateApp()
349
+ }
350
+ }
351
+
352
+ const handleOpenRecaptcha = () => {
353
+ setRecaptchaVerified(false)
354
+ if (!recaptchaConfig?.siteKey) {
355
+ showToast(ToastType.Error, t('NO_RECAPTCHA_SITE_KEY', 'The config doesn\'t have recaptcha site key'));
356
+ vibrateApp()
357
+ return
358
+ }
359
+ if (!recaptchaConfig?.baseUrl) {
360
+ showToast(ToastType.Error, t('NO_RECAPTCHA_BASE_URL', 'The config doesn\'t have recaptcha base url'));
361
+ vibrateApp()
362
+ return
363
+ }
364
+ recaptchaRef.current.open()
365
+ }
366
+
367
+ const onRecaptchaVerify = (token: any) => {
368
+ setRecaptchaVerified(true)
369
+ handleReCaptcha && handleReCaptcha({ code: token, version: recaptchaConfig?.version })
370
+ }
371
+
372
+ const handleChangePhoneNumber = (number: any, rawNumber: any) => {
373
+ setPhoneInputData({
374
+ ...phoneInputData,
375
+ ...number,
376
+ phone: {
377
+ ...phoneInputData.phone,
378
+ ...number.phone,
379
+ country_code: phoneInputData.phone.country_code
380
+ }
381
+ })
382
+ setCellphoneStartZero && setCellphoneStartZero(rawNumber?.number && rawNumber?.countryCallingCode ? rawNumber?.number : null)
383
+ }
384
+
385
+ useEffect(() => {
386
+ if (configs && Object.keys(configs).length > 0 && enableReCaptcha) {
387
+ if (configs?.security_recaptcha_type?.value === 'v3' &&
388
+ configs?.security_recaptcha_score_v3?.value > 0 &&
389
+ configs?.security_recaptcha_site_key_v3?.value
390
+ ) {
391
+ setRecaptchaConfig({
392
+ version: 'v3',
393
+ siteKey: configs?.security_recaptcha_site_key_v3?.value || null,
394
+ baseUrl: configs?.security_recaptcha_base_url?.value || null
395
+ })
396
+ return
397
+ }
398
+ if (configs?.security_recaptcha_site_key?.value) {
399
+ setRecaptchaConfig({
400
+ version: 'v2',
401
+ siteKey: configs?.security_recaptcha_site_key?.value || null,
402
+ baseUrl: configs?.security_recaptcha_base_url?.value || null
403
+ })
404
+ }
405
+ }
406
+ }, [configs, enableReCaptcha])
407
+
408
+ useEffect(() => {
409
+ if (!formState.loading && formState.result?.error) {
410
+ if (formState.result?.result?.[0] === 'ERROR_AUTH_VERIFICATION_CODE') {
411
+ setRecaptchaVerified(false)
412
+ setRecaptchaConfig({
413
+ version: 'v2',
414
+ siteKey: configs?.security_recaptcha_site_key?.value || null,
415
+ baseUrl: configs?.security_recaptcha_base_url?.value || null
416
+ })
417
+ showToast(ToastType.Info, t('TRY_AGAIN', 'Please try again'))
418
+ vibrateApp()
419
+ return
420
+ }
421
+ formState.result?.result && formState.result?.result[0]?.includes("_") ?
422
+ showToast(ToastType.Error, t(`${formState.result?.result[0]}`, 'Phone number already used')) :
423
+ showToast(ToastType.Error, formState.result?.result[0])
424
+ formState.result?.result && vibrateApp()
425
+ setIsLoadingVerifyModal(false);
426
+ }
427
+ }, [formState]);
428
+
429
+ useEffect(() => {
430
+ if (Object.keys(errors).length > 0) {
431
+ setIsLoadingVerifyModal(false);
432
+ vibrateApp()
433
+ }
434
+ }, [errors])
435
+
436
+ useEffect(() => {
437
+ if (signUpTab === 'default' || signUpTab === 'otpCellphone') {
438
+ register('cellphone', {
439
+ required: isRequiredField('cellphone')
440
+ ? t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Mobile phone is required').replace('_attribute_', t('CELLPHONE', 'Cellphone'))
441
+ : null
442
+ })
443
+ } else {
444
+ unregister('cellphone')
445
+ }
446
+ }, [signUpTab])
447
+
448
+ useEffect(() => {
449
+ if (phoneInputData?.phone?.cellphone) setValue('cellphone', phoneInputData?.phone?.cellphone, '')
450
+ else setValue('cellphone', '')
451
+ }, [phoneInputData?.phone?.cellphone])
452
+
453
+ useEffect(() => {
454
+ if (verifyPhoneState && !verifyPhoneState?.loading) {
455
+ if (verifyPhoneState.result?.error) {
456
+ const message =
457
+ typeof verifyPhoneState?.result?.result === 'string'
458
+ ? verifyPhoneState?.result?.result
459
+ : verifyPhoneState?.result?.result[0];
460
+ verifyPhoneState.result?.result && showToast(ToastType.Error, message);
461
+ verifyPhoneState.result?.result && vibrateApp()
462
+ setIsLoadingVerifyModal(false);
463
+ return;
464
+ }
465
+
466
+ const okResult = verifyPhoneState.result?.result === 'OK';
467
+ if (okResult) {
468
+ !isModalVisible && setIsModalVisible(true);
469
+ setIsLoadingVerifyModal(false);
470
+ }
471
+ }
472
+ }, [verifyPhoneState]);
473
+
474
+ useEffect(() => {
475
+ setPhoneInputData({
476
+ ...phoneInputData,
477
+ phone: {
478
+ ...phoneInputData.phone,
479
+ country_code: configs?.default_country_code?.value
480
+ }
481
+ })
482
+ }, [configs])
483
+
484
+ useEffect(() => {
485
+ if (checkPhoneCodeState?.result?.error) {
486
+ const titleText = (
487
+ typeof checkPhoneCodeState?.result?.result === 'string'
488
+ ? checkPhoneCodeState?.result?.result
489
+ : checkPhoneCodeState?.result?.result[0].toString()
490
+ ) || t('ERROR', 'Error')
491
+ setCheckingCode(false)
492
+ setOtpError(titleText)
493
+ checkPhoneCodeState?.generate && setAlertState({
494
+ open: true,
495
+ title: titleText,
496
+ content: []
497
+ })
498
+ }
499
+ }, [checkPhoneCodeState])
500
+
501
+ return (
502
+ <View>
503
+ {isGuest ? (
504
+ <OText style={{ textAlign: 'center', marginBottom: 10 }} size={18}>{t('SIGNUP', 'Signup')}</OText>
505
+ ) : (
506
+ <NavBar
507
+ title={t('SIGNUP', 'Signup')}
508
+ titleAlign={'center'}
509
+ onActionLeft={() => navigation?.canGoBack() && navigation.goBack()}
510
+ showCall={false}
511
+ btnStyle={{ paddingLeft: 0 }}
512
+ titleWrapStyle={{ paddingHorizontal: 0 }}
513
+ titleStyle={{ marginLeft: 0, marginRight: 0 }}
514
+ />
515
+ )}
516
+ <FormSide>
517
+ {((Number(useSignUpFullDetails) + Number(useSignUpOtpEmail) + Number(useSignUpOtpCellphone)) > 1) && (
518
+ <SignupWith>
519
+ <OTabs
520
+ horizontal
521
+ showsHorizontalScrollIndicator={false}
522
+ ref={tabsRef}
523
+ >
524
+ {useSignUpFullDetails && (
525
+ <TabBtn
526
+ onPress={() => handleSignUpTab('default')}
527
+ onLayout={(event: any) => handleOnLayout(event, 'default')}
528
+ >
529
+ <OTab
530
+ style={{
531
+ borderBottomColor:
532
+ signUpTab === 'default'
533
+ ? theme.colors.textNormal
534
+ : theme.colors.border,
535
+ }}>
536
+ <OText
537
+ size={14}
538
+ color={
539
+ signUpTab === 'default'
540
+ ? theme.colors.textNormal
541
+ : theme.colors.disabled
542
+ }
543
+ weight={signUpTab === 'default' ? 'bold' : 'normal'}>
544
+ {t('DEFAULT', 'Default')}
545
+ </OText>
546
+ </OTab>
547
+ </TabBtn>
548
+ )}
549
+ {useSignUpOtpEmail && (
550
+ <TabBtn
551
+ onPress={() => handleSignUpTab('otpEmail')}
552
+ onLayout={(event: any) => handleOnLayout(event, 'otpEmail')}
553
+ >
554
+ <OTab
555
+ style={{
556
+ borderBottomColor:
557
+ signUpTab === 'otpEmail'
558
+ ? theme.colors.textNormal
559
+ : theme.colors.border,
560
+ }}>
561
+ <OText
562
+ size={14}
563
+ color={
564
+ signUpTab === 'otpEmail'
565
+ ? theme.colors.textNormal
566
+ : theme.colors.disabled
567
+ }
568
+ weight={signUpTab === 'otpEmail' ? 'bold' : 'normal'}>
569
+ {t('BY_OTP_EMAIL', 'by Otp Email')}
570
+ </OText>
571
+ </OTab>
572
+ </TabBtn>
573
+
574
+ )}
575
+ {useSignUpOtpCellphone && (
576
+ <TabBtn
577
+ onPress={() => handleSignUpTab('otpCellphone')}
578
+ onLayout={(event: any) => handleOnLayout(event, 'otpCellphone')}
579
+ >
580
+ <OTab
581
+ style={{
582
+ borderBottomColor:
583
+ signUpTab === 'otpCellphone'
584
+ ? theme.colors.textNormal
585
+ : theme.colors.border,
586
+ }}>
587
+ <OText
588
+ size={14}
589
+ color={
590
+ signUpTab === 'otpCellphone'
591
+ ? theme.colors.textNormal
592
+ : theme.colors.disabled
593
+ }
594
+ weight={signUpTab === 'otpCellphone' ? 'bold' : 'normal'}>
595
+ {t('BY_OTP_CELLPHONE', 'by Otp Cellphone')}
596
+ </OText>
597
+ </OTab>
598
+ </TabBtn>
599
+ )}
600
+ </OTabs>
601
+ </SignupWith>
602
+ )}
603
+ <FormInput>
604
+ {!(useChekoutFileds && validationFields?.loading) ? (
605
+ <>
606
+ {sortInputFields({
607
+ values: validationFields?.fields?.checkout,
608
+ }).map(
609
+ (item: any, i: number) => {
610
+ const field = item?.validation_field || item
611
+ return (!notValidationFields.includes(field.code) &&
612
+ showField &&
613
+ showField(field.code) &&
614
+ (signUpTab === 'default' ||
615
+ (signUpTab === 'otpEmail' && field.code === 'email')) && (
616
+ <React.Fragment key={field.id}>
617
+ {errors?.[`${field.code}`] && (
618
+ <OText
619
+ size={14}
620
+ color={theme.colors.danger5}
621
+ weight={'normal'}>
622
+ {errors?.[`${field.code}`]?.message} {errors?.[`${field.code}`]?.type === 'required' && '*'}
623
+ </OText>
624
+ )}
625
+ <Controller
626
+ control={control}
627
+ render={({ onChange, value }: any) => (
628
+ <OInput
629
+ placeholder={t(field.name?.replace(/\s/g, '_')?.toUpperCase(), field.name)}
630
+ style={style.inputStyle}
631
+ icon={
632
+ field.code === 'email'
633
+ ? theme.images.general.email
634
+ : theme.images.general.user
635
+ }
636
+ value={value}
637
+ onChange={(val: any) =>
638
+ field.code !== 'email'
639
+ ? (onChange(val))
640
+ : handleChangeInputEmail(val, onChange)
641
+ }
642
+ autoCapitalize={
643
+ field.code === 'email' ? 'none' : 'sentences'
644
+ }
645
+ autoCorrect={field.code === 'email' && false}
646
+ type={
647
+ field.code === 'email' ? 'email-address' : 'default'
648
+ }
649
+ autoCompleteType={
650
+ field.code === 'email' ? 'email' : 'off'
651
+ }
652
+ returnKeyType="next"
653
+ blurOnSubmit={false}
654
+ forwardRef={(ref: any) => handleRefs(ref, field.code)}
655
+ onSubmitEditing={() =>
656
+ field.code === 'email'
657
+ ? phoneRef?.current?.focus?.()
658
+ : handleFocusRef(getNextFieldCode(i))
659
+ }
660
+ borderColor={errors?.[`${field.code}`] ? theme.colors.danger5 : theme.colors.border}
661
+ />
662
+ )}
663
+ name={field.code}
664
+ rules={getInputRules(field)}
665
+ defaultValue=""
666
+ />
667
+ </React.Fragment>
668
+ ))
669
+ }
670
+ )}
671
+
672
+ {(!!showInputPhoneNumber && (signUpTab === 'default' || signUpTab === 'otpCellphone')) && (
673
+ <View style={{ marginBottom: 25 }}>
674
+ <PhoneInputNumber
675
+ data={phoneInputData}
676
+ handleData={handleChangePhoneNumber}
677
+ forwardRef={phoneRef}
678
+ changeCountry={(val: any) => setPhoneInputData({
679
+ ...phoneInputData,
680
+ phone: {
681
+ ...phoneInputData.phone,
682
+ country_code: val.cca2
683
+ }
684
+ })}
685
+ textInputProps={{
686
+ returnKeyType: 'next',
687
+ onSubmitEditing: () => passwordRef?.current?.focus?.(),
688
+ }}
689
+ isStartValidation={errors?.cellphone}
690
+ />
691
+ </View>
692
+ )}
693
+
694
+ {(enableReCaptcha && recaptchaConfig?.version) && (
695
+ <>
696
+ {recaptchaConfig?.version === 'v3' ? (
697
+ <ReCaptcha
698
+ url={recaptchaConfig?.baseUrl}
699
+ siteKey={recaptchaConfig?.siteKey}
700
+ containerStyle={{ height: 40 }}
701
+ onExecute={onRecaptchaVerify}
702
+ reCaptchaType={1}
703
+ />
704
+ ) : (
705
+ <>
706
+ <TouchableOpacity
707
+ onPress={handleOpenRecaptcha}
708
+ style={{ marginHorizontal: 4, marginBottom: 10 }}
709
+ >
710
+ <RecaptchaButton>
711
+ {recaptchaVerified ? (
712
+ <MaterialCommunityIcons
713
+ name="checkbox-marked"
714
+ size={23}
715
+ color={theme.colors.primary}
716
+ />
717
+ ) : (
718
+ <MaterialCommunityIcons
719
+ name="checkbox-blank-outline"
720
+ size={23}
721
+ color={theme.colors.disabled}
722
+ />
723
+ )}
724
+ <OText size={14} mLeft={8}>{t('VERIFY_ReCAPTCHA', 'Verify reCAPTCHA')}</OText>
725
+ </RecaptchaButton>
726
+ </TouchableOpacity>
727
+ <Recaptcha
728
+ ref={recaptchaRef}
729
+ siteKey={recaptchaConfig?.siteKey}
730
+ baseUrl={recaptchaConfig?.baseUrl}
731
+ onVerify={onRecaptchaVerify}
732
+ onExpire={() => setRecaptchaVerified(false)}
733
+ />
734
+ </>
735
+ )}
736
+
737
+ </>
738
+ )}
739
+ {(signUpTab === 'default') && (
740
+ <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
741
+ <Controller
742
+ control={control}
743
+ render={({ onChange, value }: any) => (
744
+ <CheckBox
745
+ value={value}
746
+ onValueChange={newValue => {
747
+ onChange(newValue)
748
+ handleChangePromotions()
749
+ }}
750
+ boxType={'square'}
751
+ tintColors={{
752
+ true: theme.colors.primary,
753
+ false: theme.colors.disabled
754
+ }}
755
+ tintColor={theme.colors.disabled}
756
+ onCheckColor={theme.colors.primary}
757
+ onTintColor={theme.colors.primary}
758
+ style={Platform.OS === 'ios' && style.checkBoxStyle}
759
+ />
760
+ )}
761
+ name='promotions'
762
+ defaultValue={false}
763
+ />
764
+ <OText style={{ fontSize: 14, paddingHorizontal: 5 }}>{t('RECEIVE_NEWS_EXCLUSIVE_PROMOTIONS', 'Receive newsletters and exclusive promotions')}</OText>
765
+ </View>
766
+ )}
767
+ {configs?.terms_and_conditions?.value === 'true' && (
768
+ <>
769
+ {errors?.termsAccept && (
770
+ <OText
771
+ size={14}
772
+ color={theme.colors.danger5}
773
+ weight={'normal'}>
774
+ {errors?.termsAccept?.message}*
775
+ </OText>
776
+ )}
777
+ <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
778
+ <Controller
779
+ control={control}
780
+ render={({ onChange, value }: any) => (
781
+ <CheckBox
782
+ value={value}
783
+ onValueChange={newValue => {
784
+ onChange(newValue)
785
+ }}
786
+ boxType={'square'}
787
+ tintColors={{
788
+ true: theme.colors.primary,
789
+ false: theme.colors.disabled
790
+ }}
791
+ tintColor={theme.colors.disabled}
792
+ onCheckColor={theme.colors.primary}
793
+ onTintColor={theme.colors.primary}
794
+ style={Platform.OS === 'ios' && style.checkBoxStyle}
795
+ />
796
+ )}
797
+ name='termsAccept'
798
+ rules={{
799
+ required: t('VALIDATION_ERROR_ACCEPTED', 'The _attribute_ must be accepted.').replace('_attribute_', t('TERMS_AND_CONDITIONS', 'Terms & Conditions'))
800
+ }}
801
+ defaultValue={false}
802
+ />
803
+ <OText style={{ fontSize: 14, paddingHorizontal: 5 }}>{t('TERMS_AND_CONDITIONS_TEXT', 'I agree with')}</OText>
804
+ <OButton
805
+ imgRightSrc={null}
806
+ text={t('TERMS_AND_CONDITIONS', 'Terms & Conditions')}
807
+ bgColor={theme.colors.white}
808
+ borderColor={theme.colors.white}
809
+ style={{ paddingLeft: 0, paddingRight: 0, height: 30, shadowColor: theme.colors.white }}
810
+ textStyle={{ color: theme.colors.primary, marginLeft: 0, marginRight: 0 }}
811
+ onClick={() => handleOpenTermsUrl(configs?.terms_and_conditions_url?.value)}
812
+ />
813
+ </View>
814
+ </>
815
+
816
+ )}
817
+
818
+ {signUpTab === 'default' && (
819
+ <>
820
+ {errors?.password && (
821
+ <OText
822
+ size={14}
823
+ color={theme.colors.danger5}
824
+ weight={'normal'}>
825
+ {errors?.password?.message} {errors?.password?.type === 'required' && '*'}
826
+ </OText>
827
+ )}
828
+ <Controller
829
+ control={control}
830
+ render={({ onChange, value }: any) => (
831
+ <OInput
832
+ isSecured={!passwordSee ? true : false}
833
+ placeholder={t('PASSWORD', 'Password')}
834
+ style={style.inputStyle}
835
+ icon={theme.images.general.lock}
836
+ iconCustomRight={
837
+ !passwordSee ? (
838
+ <MaterialCommunityIcons
839
+ name="eye-outline"
840
+ color={theme.colors.disabled}
841
+ size={24}
842
+ onPress={() => setPasswordSee(!passwordSee)}
843
+ />
844
+ ) : (
845
+ <MaterialCommunityIcons
846
+ name="eye-off-outline"
847
+ color={theme.colors.disabled}
848
+ size={24}
849
+ onPress={() => setPasswordSee(!passwordSee)}
850
+ />
851
+ )
852
+ }
853
+ autoCapitalize='none'
854
+ value={value}
855
+ onChange={(val: any) => onChange(val)}
856
+ returnKeyType="done"
857
+ onSubmitEditing={handleSubmit(onSubmit)}
858
+ blurOnSubmit
859
+ forwardRef={passwordRef}
860
+ borderColor={errors?.password ? theme.colors.danger5 : theme.colors.border}
861
+ />
862
+ )}
863
+ name="password"
864
+ rules={{
865
+ required: isRequiredField('password')
866
+ ? t(
867
+ 'VALIDATION_ERROR_PASSWORD_REQUIRED',
868
+ 'The field Password is required',
869
+ ).replace('_attribute_', t('PASSWORD', 'password'))
870
+ : null,
871
+ minLength: {
872
+ value: 8,
873
+ message: t(
874
+ 'VALIDATION_ERROR_PASSWORD_MIN_STRING',
875
+ 'The Password must be at least 8 characters.',
876
+ )
877
+ .replace('_attribute_', t('PASSWORD', 'Password'))
878
+ .replace('_min_', 8),
879
+ },
880
+ }}
881
+ defaultValue=""
882
+ />
883
+ </>
884
+
885
+ )}
886
+ </>
887
+ ) : (
888
+ <Spinner visible />
889
+ )}
890
+
891
+ {(signUpTab === 'otpCellphone' && useSignUpOtpWhatsapp) ? (
892
+ <View style={{ flexDirection: 'row', gap: 10, marginTop: 6 }}>
893
+ <OButton
894
+ onClick={() => { otpChannelRef.current = 2; handleSubmit(onSubmit)() }}
895
+ text={t('SEND_BY_SMS', 'Send by SMS')}
896
+ imgRightSrc={null}
897
+ isLoading={isLoadingVerifyModal}
898
+ indicatorColor={theme.colors.white}
899
+ parentStyle={{ flex: 1 }}
900
+ style={{ borderRadius: 7.6 }}
901
+ />
902
+ <OButton
903
+ onClick={() => { otpChannelRef.current = 4; handleSubmit(onSubmit)() }}
904
+ text={t('SEND_BY_WHATSAPP', 'Send by WhatsApp')}
905
+ imgRightSrc={null}
906
+ isLoading={isLoadingVerifyModal}
907
+ indicatorColor={theme.colors.white}
908
+ parentStyle={{ flex: 1 }}
909
+ style={{ borderRadius: 7.6 }}
910
+ />
911
+ </View>
912
+ ) : (signUpTab === 'otpEmail' || signUpTab === 'otpCellphone') ? (
913
+ <OButton
914
+ onClick={handleSubmit(onSubmit)}
915
+ text={t('GET_VERIFY_CODE', 'Get Verify Code')}
916
+ imgRightSrc={null}
917
+ isLoading={isLoadingVerifyModal}
918
+ indicatorColor={theme.colors.white}
919
+ style={{ borderRadius: 7.6, marginTop: 6 }}
920
+ />
921
+ ) : (
922
+ <OButton
923
+ onClick={handleSubmit(onSubmit)}
924
+ text={signupButtonText}
925
+ imgRightSrc={null}
926
+ isDisabled={formState.loading || validationFields.loading}
927
+ style={{ borderRadius: 7.6, marginTop: 6, shadowOpacity: 0 }}
928
+ />
929
+ )}
930
+ </FormInput>
931
+
932
+ {
933
+ onNavigationRedirect && loginButtonText && (
934
+ <View style={style.wrappText}>
935
+ <OText size={14} style={{ marginRight: 5 }}>
936
+ {t('MOBILE_FRONT_ALREADY_HAVE_AN_ACCOUNT', 'Already have an account?')}
937
+ </OText>
938
+ <Pressable onPress={() => onNavigationRedirect('Login')}>
939
+ <OText size={14} color={theme.colors.primary}>
940
+ {loginButtonText}
941
+ </OText>
942
+ </Pressable>
943
+ </View>
944
+ )
945
+ }
946
+ {configs && Object.keys(configs).length > 0 && !isGuest && (
947
+ (((configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') && configs?.facebook_id?.value && facebookLoginEnabled) ||
948
+ ((configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && googleLoginEnabled) ||
949
+ ((configs?.apple_login_client_id?.value !== '' && configs?.apple_login_client_id?.value !== null) && appleLoginEnabled)) &&
950
+ (
951
+ <>
952
+ <View
953
+ style={{
954
+ flexDirection: 'row',
955
+ width: '100%',
956
+ justifyContent: 'space-between',
957
+ alignItems: 'center',
958
+ marginVertical: 30,
959
+ }}>
960
+ <View style={style.line} />
961
+ <OText
962
+ size={14}
963
+ mBottom={10}
964
+ style={{ paddingHorizontal: 19 }}
965
+ color={theme.colors.disabled}>
966
+ {t('OR', 'or')}
967
+ </OText>
968
+ <View style={style.line} />
969
+ </View>
970
+ <ButtonsWrapper>
971
+ <SocialButtons>
972
+ {(configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') &&
973
+ configs?.facebook_id?.value &&
974
+ facebookLoginEnabled &&
975
+ (
976
+ <FacebookLogin
977
+ notificationState={notificationState}
978
+ handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
979
+ handleLoading={(val: boolean) => setIsFBLoading(val)}
980
+ handleSuccessFacebookLogin={handleSuccessFacebook}
981
+ />
982
+ )}
983
+ {(configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && googleLoginEnabled && (
984
+ <GoogleLogin
985
+ notificationState={notificationState}
986
+ webClientId={configs?.google_login_client_id?.value}
987
+ handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
988
+ handleLoading={(val: boolean) => setIsFBLoading(val)}
989
+ handleSuccessGoogleLogin={handleSuccessFacebook}
990
+ />
991
+ )}
992
+ {(configs?.apple_login_client_id?.value !== '' && configs?.apple_login_client_id?.value !== null) && appleLoginEnabled && (
993
+ <AppleLogin
994
+ notificationState={notificationState}
995
+ handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
996
+ handleLoading={(val: boolean) => setIsFBLoading(val)}
997
+ handleSuccessAppleLogin={handleSuccessFacebook}
998
+ />
999
+ )}
1000
+ </SocialButtons>
1001
+ </ButtonsWrapper>
1002
+ </>
1003
+ )
1004
+ )}
1005
+ </FormSide>
1006
+ <Modal
1007
+ visible={willVerifyOtpState}
1008
+ onDismiss={() => setWillVerifyOtpState && setWillVerifyOtpState(false)}
1009
+ animationType='slide'
1010
+ >
1011
+ <Otp
1012
+ isCheckingCode={isCheckingCode}
1013
+ setCheckingCode={setCheckingCode}
1014
+ otpError={otpError}
1015
+ setOtpError={setOtpError}
1016
+ pinCount={numOtpInputs || 6}
1017
+ willVerifyOtpState={willVerifyOtpState || false}
1018
+ setWillVerifyOtpState={() => setWillVerifyOtpState && setWillVerifyOtpState(false)}
1019
+ handleLoginOtp={handleSingUpOtp}
1020
+ onSubmit={onSubmit}
1021
+ setAlertState={setAlertState}
1022
+ />
1023
+ </Modal>
1024
+ <Spinner
1025
+ visible={formState.loading || validationFields.loading || isFBLoading}
1026
+ />
1027
+ <Alert
1028
+ open={alertState.open}
1029
+ content={alertState.content}
1030
+ title={alertState.title || ''}
1031
+ onAccept={closeAlert}
1032
+ onClose={closeAlert}
1033
+ />
1034
+ </View>
1035
+ );
997
1036
  };
998
1037
 
999
1038
  export const SignupForm = (props: any) => {
1000
- const _numOtpInputs = 6
1001
- const signupProps = {
1002
- ...props,
1003
- numOtpInputs: _numOtpInputs,
1004
- isRecaptchaEnable: true,
1005
- UIComponent: SignupFormUI,
1006
- };
1007
- return <SignUpController {...signupProps} />;
1039
+ const _numOtpInputs = 6
1040
+ const signupProps = {
1041
+ ...props,
1042
+ numOtpInputs: _numOtpInputs,
1043
+ isRecaptchaEnable: true,
1044
+ UIComponent: SignupFormUI,
1045
+ };
1046
+ return <SignUpController {...signupProps} />;
1008
1047
  };