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
@@ -9,31 +9,31 @@ import ReCaptcha from '@fatnlazycat/react-native-recaptcha-v3'
9
9
  import ReactNativeHapticFeedback from "react-native-haptic-feedback";
10
10
 
11
11
  import {
12
- LoginForm as LoginFormController,
13
- useLanguage,
14
- useConfig,
15
- useSession,
16
- ToastType,
17
- useToast,
12
+ LoginForm as LoginFormController,
13
+ useLanguage,
14
+ useConfig,
15
+ useSession,
16
+ ToastType,
17
+ useToast,
18
18
  } from 'ordering-components/native';
19
19
  import { useTheme } from 'styled-components/native';
20
20
  import { FacebookLogin } from '../FacebookLogin';
21
21
  import { VerifyPhone } from '../../../../../src/components/VerifyPhone';
22
22
  import { OModal } from '../../../../../src/components/shared';
23
23
  import {
24
- Container,
25
- ButtonsWrapper,
26
- LoginWith,
27
- FormSide,
28
- FormInput,
29
- OTabs,
30
- OTab,
31
- SocialButtons,
32
- OrSeparator,
33
- LineSeparator,
34
- SkeletonWrapper,
35
- TabBtn,
36
- RecaptchaButton
24
+ Container,
25
+ ButtonsWrapper,
26
+ LoginWith,
27
+ FormSide,
28
+ FormInput,
29
+ OTabs,
30
+ OTab,
31
+ SocialButtons,
32
+ OrSeparator,
33
+ LineSeparator,
34
+ SkeletonWrapper,
35
+ TabBtn,
36
+ RecaptchaButton
37
37
  } from './styles';
38
38
 
39
39
  import NavBar from '../NavBar';
@@ -48,840 +48,871 @@ import { TouchableOpacity } from 'react-native-gesture-handler';
48
48
  import Alert from '../../../../../src/providers/AlertProvider'
49
49
 
50
50
  const LoginFormUI = (props: LoginParams) => {
51
- const {
52
- loginTab,
53
- formState,
54
- navigation,
55
- useLoginByEmail,
56
- useLoginByCellphone,
57
- useLoginOtp,
58
- loginButtonText,
59
- forgotButtonText,
60
- verifyPhoneState,
61
- checkPhoneCodeState,
62
- registerButtonText,
63
- setCheckPhoneCodeState,
64
- handleButtonLoginClick,
65
- handleSendVerifyCode,
66
- handleCheckPhoneCode,
67
- onNavigationRedirect,
68
- notificationState,
69
- handleReCaptcha,
70
- enableReCaptcha,
71
- otpType,
72
- setOtpType,
73
- generateOtpCode,
74
- useLoginOtpEmail,
75
- useLoginOtpCellphone,
76
- isGuest
77
- } = props;
78
-
79
- const [, { showToast }] = useToast();
80
- const [, t] = useLanguage();
81
- const [{ configs }] = useConfig();
82
- const [, { login }] = useSession();
83
- const { control, handleSubmit, errors, reset, register, setValue } = useForm();
84
- const [passwordSee, setPasswordSee] = useState(false);
85
- const [isLoadingVerifyModal, setIsLoadingVerifyModal] = useState(false);
86
- const [isModalVisible, setIsModalVisible] = useState(false);
87
- const [isFBLoading, setIsFBLoading] = useState(false);
88
- const [willVerifyOtpState, setWillVerifyOtpState] = useState(false)
89
- const [phoneInputData, setPhoneInputData] = useState({
90
- error: '',
91
- phone: {
92
- country_phone_code: null,
93
- cellphone: null,
94
- },
95
- });
96
- const [recaptchaConfig, setRecaptchaConfig] = useState<any>({})
97
- const [recaptchaVerified, setRecaptchaVerified] = useState(false)
98
- const [alertState, setAlertState] = useState({ open: false, title: '', content: [] })
99
- const [tabLayouts, setTabLayouts] = useState<any>({})
100
- const [otpError, setOtpError] = useState(null)
101
- const tabsRef = useRef<any>(null)
102
- const enabledPoweredByOrdering = configs?.powered_by_ordering_module?.value
103
- const theme = useTheme();
104
- const isOtpEmail = loginTab === 'otp' && otpType === 'email'
105
- const isOtpCellphone = loginTab === 'otp' && otpType === 'cellphone'
106
-
107
- const [isCheckingCode, setCheckingCode] = useState(false)
108
-
109
- const googleLoginEnabled = configs?.google_login_enabled?.value === '1' || !configs?.google_login_enabled?.enabled
110
- const facebookLoginEnabled = configs?.facebook_login_enabled?.value === '1' || !configs?.facebook_login_enabled?.enabled
111
- const appleLoginEnabled = Platform.OS === 'ios' && (configs?.apple_login_enabled?.value === '1' || !configs?.apple_login_enabled?.enabled)
112
-
113
- const loginStyle = StyleSheet.create({
114
- btnOutline: {
115
- backgroundColor: '#FFF',
116
- color: theme.colors.primary,
117
- borderRadius: 7.6,
118
- },
119
- inputStyle: {
120
- marginBottom: 28,
121
- borderWidth: 1,
122
- // borderColor: theme.colors.border,
123
- borderRadius: 7.6,
124
- },
125
- line: {
126
- height: 1,
127
- backgroundColor: theme.colors.border,
128
- flexGrow: 1,
129
- marginBottom: 7,
130
- },
131
- recaptchaIcon: {
132
- width: 100,
133
- height: 100,
134
- },
135
- borderStyleBase: {
136
- width: 30,
137
- height: 45
138
- },
139
-
140
- borderStyleHighLighted: {
141
- borderColor: "#03DAC6",
142
- },
143
-
144
- underlineStyleBase: {
145
- width: 45,
146
- height: 60,
147
- borderWidth: 1,
148
- fontSize: 16
149
- },
150
-
151
- underlineStyleHighLighted: {
152
- borderColor: theme.colors.primary,
153
- color: theme.colors.primary,
154
- fontSize: 16
155
- },
156
- });
157
-
158
- const emailRef = useRef<any>({});
159
- const passwordRef = useRef<any>({});
160
- const recaptchaRef = useRef<any>({});
161
-
162
- const handleChangeTab = (val: string, otpType?: string) => {
163
- props.handleChangeTab(val);
164
- setPasswordSee(false);
165
- handleCategoryScroll(otpType ? `${val}_${otpType}` : val)
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 onSubmit = (values?: any) => {
177
- Keyboard.dismiss();
178
- if (loginTab === 'otp') {
179
- if (phoneInputData.error && (loginTab !== 'otp' || (otpType === 'cellphone' && loginTab === 'otp'))) {
180
- showToast(ToastType.Error, t('INVALID_PHONE_NUMBER', 'Invalid phone number'));
181
- vibrateApp()
182
- return
183
- }
184
- if (otpType === 'cellphone' && phoneInputData?.error && !phoneInputData?.phone?.cellphone) {
185
- showToast(ToastType.Error, t('PHONE_NUMBER_REQUIRED', 'Phone number is required'));
186
- return
187
- }
188
- if (loginTab === 'otp') {
189
- generateOtpCode({
190
- ...values,
191
- ...phoneInputData.phone
192
- })
193
- }
194
- setWillVerifyOtpState(true)
195
- } else {
196
- if (phoneInputData.error) {
197
- showToast(ToastType.Error, phoneInputData.error);
198
- vibrateApp()
199
- return;
200
- }
201
- handleButtonLoginClick({
202
- ...values,
203
- ...phoneInputData.phone,
204
- });
205
- }
206
-
207
- };
208
- const handleVerifyCodeClick = () => {
209
- if (phoneInputData.error) {
210
- showToast(ToastType.Error, phoneInputData.error);
211
- vibrateApp()
212
- return;
213
- }
214
- if (
215
- !phoneInputData.error &&
216
- !phoneInputData.phone.country_phone_code &&
217
- !phoneInputData.phone.cellphone
218
- ) {
219
- showToast(
220
- ToastType.Error,
221
- t(
222
- 'VALIDATION_ERROR_MOBILE_PHONE_REQUIRED',
223
- 'The field Mobile phone is required.',
224
- ),
225
- );
226
- vibrateApp()
227
- return;
228
- }
229
- handleSendVerifyCode && handleSendVerifyCode(phoneInputData.phone);
230
- setIsLoadingVerifyModal(true);
231
- };
232
-
233
- const handleSuccessFacebook = (user: any) => {
234
- login({
235
- user,
236
- token: user.session.access_token,
237
- });
238
- };
239
-
240
- const handleChangeInputEmail = (value: string, onChange: any) => {
241
- onChange(value.toLowerCase().trim().replace(/[&,()%";:ç?<>{}\\[\]\s]/g, ''));
242
- };
243
-
244
- const handleOpenRecaptcha = () => {
245
- setRecaptchaVerified(false)
246
- if (!recaptchaConfig?.siteKey) {
247
- showToast(ToastType.Error, t('NO_RECAPTCHA_SITE_KEY', 'The config doesn\'t have recaptcha site key'));
248
- vibrateApp()
249
- return
250
- }
251
- if (!recaptchaConfig?.baseUrl) {
252
- showToast(ToastType.Error, t('NO_RECAPTCHA_BASE_URL', 'The config doesn\'t have recaptcha base url'));
253
- vibrateApp()
254
- return
255
- }
256
-
257
- recaptchaRef.current.open()
258
- }
259
-
260
- const onRecaptchaVerify = (token: any) => {
261
- setRecaptchaVerified(true)
262
- handleReCaptcha({ code: token, version: recaptchaConfig?.version })
263
- }
264
-
265
- const handleChangeOtpType = (type: string) => {
266
- handleChangeTab('otp', type)
267
- setOtpType(type)
268
- }
269
-
270
- const handleLoginOtp = async (code: string) => {
271
- if (!code) return
272
- const logged = await handleButtonLoginClick({ code })
273
- setCheckingCode(false)
274
- if (logged) {
275
- setWillVerifyOtpState(false)
276
- } else {
277
- setOtpError(t('OTP_CODE_INCORRECT', 'Otp code incorrect'))
278
- }
279
- }
280
-
281
- const closeAlert = () => {
282
- setAlertState({
283
- open: false,
284
- title: '',
285
- content: []
286
- })
287
- }
288
-
289
- const handleCategoryScroll = (opc: string) => {
290
- tabsRef.current.scrollTo({
291
- x: tabLayouts?.[opc]?.x - 40,
292
- animated: true
293
- })
294
- }
295
-
296
- const handleOnLayout = (event: any, opc: string) => {
297
- const _tabLayouts = { ...tabLayouts }
298
- const categoryKey = opc
299
- _tabLayouts[categoryKey] = event.nativeEvent.layout
300
- setTabLayouts(_tabLayouts)
301
- }
302
-
303
- useEffect(() => {
304
- if (configs && Object.keys(configs).length > 0 && enableReCaptcha) {
305
- if (configs?.security_recaptcha_type?.value === 'v3' &&
306
- configs?.security_recaptcha_score_v3?.value > 0 &&
307
- configs?.security_recaptcha_site_key_v3?.value
308
- ) {
309
- setRecaptchaConfig({
310
- version: 'v3',
311
- siteKey: configs?.security_recaptcha_site_key_v3?.value || null,
312
- baseUrl: configs?.security_recaptcha_base_url?.value || null
313
- })
314
- return
315
- }
316
- if (configs?.security_recaptcha_site_key?.value) {
317
- setRecaptchaConfig({
318
- version: 'v2',
319
- siteKey: configs?.security_recaptcha_site_key?.value || null,
320
- baseUrl: configs?.security_recaptcha_base_url?.value || null
321
- })
322
- }
323
- }
324
- }, [configs, enableReCaptcha])
325
-
326
- useEffect(() => {
327
- if (!formState.loading && formState.result?.error) {
328
- if (formState.result?.result?.[0] === 'ERROR_AUTH_VERIFICATION_CODE') {
329
- setRecaptchaVerified(false)
330
- setRecaptchaConfig({
331
- version: 'v2',
332
- siteKey: configs?.security_recaptcha_site_key?.value || null,
333
- baseUrl: configs?.security_recaptcha_base_url?.value || null
334
- })
335
- showToast(ToastType.Info, t('TRY_AGAIN', 'Please try again'))
336
- vibrateApp()
337
- return
338
- }
339
- formState.result?.result &&
340
- showToast(
341
- ToastType.Error,
342
- typeof formState.result?.result === 'string'
343
- ? formState.result?.result
344
- : formState.result?.result[0],
345
- );
346
- formState.result?.result && vibrateApp()
347
- }
348
- }, [formState]);
349
-
350
- useEffect(() => {
351
- if (verifyPhoneState && !verifyPhoneState?.loading) {
352
- if (verifyPhoneState.result?.error) {
353
- const message =
354
- typeof verifyPhoneState?.result?.result === 'string'
355
- ? verifyPhoneState?.result?.result
356
- : verifyPhoneState?.result?.result[0];
357
- verifyPhoneState.result?.result && showToast(ToastType.Error, message);
358
- verifyPhoneState.result?.result && vibrateApp();
359
- setIsLoadingVerifyModal(false);
360
- return;
361
- }
362
-
363
- const okResult = verifyPhoneState.result?.result === 'OK';
364
- if (okResult) {
365
- !isModalVisible && setIsModalVisible(true);
366
- setIsLoadingVerifyModal(false);
367
- }
368
- }
369
- }, [verifyPhoneState]);
370
-
371
- useEffect(() => {
372
- if (phoneInputData?.phone?.cellphone) setValue('cellphone', phoneInputData?.phone?.cellphone, '')
373
- else setValue('cellphone', '')
374
- }, [phoneInputData?.phone?.cellphone])
375
-
376
- useEffect(() => {
377
- register('cellphone', {
378
- required: loginTab === 'cellphone'
379
- ? t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Mobile phone is required').replace('_attribute_', t('CELLPHONE', 'Cellphone'))
380
- : null
381
- })
382
- }, [register])
383
-
384
- useEffect(() => {
385
- reset()
386
- }, [loginTab])
387
-
388
- useEffect(() => {
389
- if (checkPhoneCodeState?.result?.error) {
390
- setAlertState({
391
- open: true,
392
- content: t(checkPhoneCodeState?.result?.error, checkPhoneCodeState?.result?.error),
393
- title: ''
394
- })
395
- }
396
- }, [checkPhoneCodeState])
397
-
398
- useEffect(() => {
399
- if (!!Object.values(errors)?.length) vibrateApp()
400
- }, [errors])
401
-
402
- return (
403
- <Container>
404
- {isGuest ? (
405
- <OText style={{ textAlign: 'center', marginBottom: 10 }} size={18}>{t('LOGIN', 'Login')}</OText>
406
- ) : (
407
- <NavBar
408
- title={t('LOGIN', 'Login')}
409
- titleAlign={'center'}
410
- onActionLeft={() => navigation?.canGoBack() && navigation.goBack()}
411
- showCall={false}
412
- btnStyle={{ paddingLeft: 0 }}
413
- titleWrapStyle={{ paddingHorizontal: 0 }}
414
- titleStyle={{ marginRight: 0, marginLeft: 0 }}
415
- />
416
- )}
417
- <FormSide>
418
- {(Number(useLoginByEmail) + Number(useLoginByCellphone) + Number(useLoginOtpEmail) + Number(useLoginOtpCellphone) > 1) && (
419
- <LoginWith>
420
- <OTabs
421
- horizontal
422
- showsHorizontalScrollIndicator={false}
423
- ref={tabsRef}
424
- >
425
- {useLoginByEmail && (
426
- <TabBtn
427
- onPress={() => handleChangeTab('email')}
428
- onLayout={(event: any) => handleOnLayout(event, 'email')}
429
- >
430
- <OTab
431
- style={{
432
- borderBottomColor:
433
- loginTab === 'email'
434
- ? theme.colors.textNormal
435
- : theme.colors.border,
436
- }}>
437
- <OText
438
- size={14}
439
- color={
440
- loginTab === 'email'
441
- ? theme.colors.textNormal
442
- : theme.colors.disabled
443
- }
444
- weight={loginTab === 'email' ? 'bold' : 'normal'}>
445
- {t('LOGIN_BY_EMAIL', 'by Email')}
446
- </OText>
447
- </OTab>
448
- </TabBtn>
449
- )}
450
- {useLoginByCellphone && (
451
- <TabBtn
452
- onPress={() => handleChangeTab('cellphone')}
453
- onLayout={(event: any) => handleOnLayout(event, 'cellphone')}
454
- >
455
- <OTab
456
- style={{
457
- borderBottomColor:
458
- loginTab === 'cellphone'
459
- ? theme.colors.textNormal
460
- : theme.colors.border,
461
- }}>
462
- <OText
463
- size={14}
464
- color={
465
- loginTab === 'cellphone'
466
- ? theme.colors.textNormal
467
- : theme.colors.disabled
468
- }
469
- weight={loginTab === 'cellphone' ? 'bold' : 'normal'}>
470
- {t('LOGIN_BY_PHONE', 'by Phone')}
471
- </OText>
472
- </OTab>
473
- </TabBtn>
474
- )}
475
- {useLoginOtpEmail && (
476
- <TabBtn
477
- onPress={() => handleChangeOtpType('email')}
478
- onLayout={(event: any) => handleOnLayout(event, 'otp_email')}
479
- >
480
- <OTab
481
- style={{
482
- borderBottomColor:
483
- isOtpEmail
484
- ? theme.colors.textNormal
485
- : theme.colors.border,
486
- }}>
487
- <OText
488
- size={14}
489
- color={
490
- isOtpEmail
491
- ? theme.colors.textNormal
492
- : theme.colors.disabled
493
- }
494
- weight={isOtpEmail ? 'bold' : 'normal'}>
495
- {t('BY_OTP_EMAIL', 'By Otp Email')}
496
- </OText>
497
- </OTab>
498
- </TabBtn>
499
- )}
500
- {useLoginOtpCellphone && (
501
- <TabBtn
502
- onPress={() => handleChangeOtpType('cellphone')}
503
- onLayout={(event: any) => handleOnLayout(event, 'otp_cellphone')}
504
- >
505
- <OTab
506
- style={{
507
- borderBottomColor:
508
- isOtpCellphone
509
- ? theme.colors.textNormal
510
- : theme.colors.border,
511
- }}>
512
- <OText
513
- size={14}
514
- color={
515
- isOtpCellphone
516
- ? theme.colors.textNormal
517
- : theme.colors.disabled
518
- }
519
- weight={isOtpCellphone ? 'bold' : 'normal'}>
520
- {t('BY_OTP_PHONE', 'By Otp Phone')}
521
- </OText>
522
- </OTab>
523
- </TabBtn>
524
- )}
525
- </OTabs>
526
- </LoginWith>
527
- )}
528
-
529
- {(useLoginByCellphone || useLoginByEmail || useLoginOtp) && (
530
- <FormInput>
531
- {((useLoginByEmail && loginTab === 'email') || (loginTab === 'otp' && otpType === 'email')) && (
532
- <>
533
- {errors?.email && (
534
- <OText
535
- size={14}
536
- color={theme.colors.danger5}
537
- weight={'normal'}>
538
- {errors?.email?.message}{errors?.email?.type === 'required' && '*'}
539
- </OText>
540
- )}
541
- <Controller
542
- control={control}
543
- render={({ onChange, value }: any) => (
544
- <OInput
545
- placeholder={t('EMAIL', 'Email')}
546
- style={loginStyle.inputStyle}
547
- icon={theme.images.general.email}
548
- onChange={(e: any) => {
549
- handleChangeInputEmail(e, onChange);
550
- }}
551
- value={value}
552
- autoCapitalize="none"
553
- autoCorrect={false}
554
- type="email-address"
555
- autoCompleteType="email"
556
- returnKeyType="next"
557
- onSubmitEditing={() => passwordRef.current?.focus()}
558
- blurOnSubmit={false}
559
- forwardRef={emailRef}
560
- borderColor={errors?.email ? theme.colors.danger5 : theme.colors.border}
561
- />
562
- )}
563
- name="email"
564
- rules={{
565
- required: {
566
- value: true,
567
- message: t(
568
- 'VALIDATION_ERROR_EMAIL_REQUIRED',
569
- 'The field Email is required',
570
- ).replace('_attribute_', t('EMAIL', 'Email'))
571
- },
572
- pattern: {
573
- value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
574
- message: t(
575
- 'INVALID_ERROR_EMAIL',
576
- 'Invalid email address',
577
- ).replace('_attribute_', t('EMAIL', 'Email')),
578
- }
579
- }}
580
- defaultValue=""
581
- />
582
- </>
583
-
584
- )}
585
- {((useLoginByCellphone && loginTab === 'cellphone') || (loginTab === 'otp' && otpType === 'cellphone')) && (
586
- <View style={{ marginBottom: 28 }}>
587
- <PhoneInputNumber
588
- data={phoneInputData}
589
- handleData={(val: any) => setPhoneInputData(val)}
590
- textInputProps={{
591
- returnKeyType: 'next',
592
- onSubmitEditing: () => passwordRef?.current?.focus?.(),
593
- }}
594
- isStartValidation={errors?.cellphone}
595
- />
596
- </View>
597
- )}
598
- {errors?.password && (
599
- <OText
600
- size={14}
601
- color={theme.colors.danger5}
602
- weight={'normal'}>
603
- {errors?.password?.message}{errors?.password?.type === 'required' && '*'}
604
- </OText>
605
- )}
606
- {loginTab !== 'otp' && (
607
-
608
- <Controller
609
- control={control}
610
- render={({ onChange, value }: any) => (
611
- <OInput
612
- isSecured={!passwordSee ? true : false}
613
- placeholder={t('PASSWORD', 'Password')}
614
- style={{ ...loginStyle.inputStyle, marginBottom: 14 }}
615
- icon={theme.images.general.lock}
616
- iconCustomRight={
617
- !passwordSee ? (
618
- <MaterialCommunityIcons
619
- name="eye-outline"
620
- size={24}
621
- onPress={() => setPasswordSee(!passwordSee)}
622
- color={theme.colors.disabled}
623
- />
624
- ) : (
625
- <MaterialCommunityIcons
626
- name="eye-off-outline"
627
- size={24}
628
- onPress={() => setPasswordSee(!passwordSee)}
629
- color={theme.colors.disabled}
630
- />
631
- )
632
- }
633
- autoCapitalize='none'
634
- value={value}
635
- forwardRef={passwordRef}
636
- onChange={(val: any) => onChange(val)}
637
- returnKeyType="done"
638
- onSubmitEditing={handleSubmit(onSubmit)}
639
- blurOnSubmit
640
- borderColor={errors?.password ? theme.colors.danger5 : theme.colors.border}
641
- />
642
- )}
643
- name="password"
644
- rules={{
645
- required: {
646
- value: true,
647
- message: t(
648
- 'VALIDATION_ERROR_PASSWORD_REQUIRED',
649
- 'The field Password is required',
650
- ).replace('_attribute_', t('PASSWORD', 'Password'))
651
- }
652
- }}
653
- defaultValue=""
654
- />
655
- )}
656
- {onNavigationRedirect && forgotButtonText && loginTab !== 'otp' && (
657
- <TouchableOpacity onPress={() => onNavigationRedirect('Forgot')}>
658
- <OText size={14} mBottom={18}>
659
- {forgotButtonText}
660
- </OText>
661
- </TouchableOpacity>
662
- )}
663
-
664
- {(enableReCaptcha && recaptchaConfig?.version) && (
665
- <>
666
- {recaptchaConfig?.version === 'v3' ? (
667
- <ReCaptcha
668
- url={recaptchaConfig?.baseUrl}
669
- siteKey={recaptchaConfig?.siteKey}
670
- containerStyle={{ height: 40 }}
671
- onExecute={onRecaptchaVerify}
672
- reCaptchaType={1}
673
- />
674
- ) : (
675
- <>
676
- <TouchableOpacity
677
- onPress={handleOpenRecaptcha}
678
- >
679
- <RecaptchaButton>
680
- {recaptchaVerified ? (
681
- <MaterialCommunityIcons
682
- name="checkbox-marked"
683
- size={26}
684
- color={theme.colors.primary}
685
- />
686
- ) : (
687
- <MaterialCommunityIcons
688
- name="checkbox-blank-outline"
689
- size={26}
690
- color={theme.colors.mediumGray}
691
- />
692
- )}
693
- <OText size={14} mLeft={8}>{t('VERIFY_ReCAPTCHA', 'Verify reCAPTCHA')}</OText>
694
- </RecaptchaButton>
695
- </TouchableOpacity>
696
- <Recaptcha
697
- ref={recaptchaRef}
698
- siteKey={recaptchaConfig?.siteKey}
699
- baseUrl={recaptchaConfig?.baseUrl}
700
- onVerify={onRecaptchaVerify}
701
- onExpire={() => setRecaptchaVerified(false)}
702
- />
703
- </>)
704
- }
705
- </>
706
- )}
707
- <OButton
708
- onClick={handleSubmit(onSubmit)}
709
- text={loginTab !== 'otp' ? loginButtonText : t('GET_VERIFY_CODE', 'Get verify code')}
710
- imgRightSrc={null}
711
- isLoading={formState.loading}
712
- style={{ borderRadius: 7.6, marginTop: 10, marginBottom: 25 }}
713
- />
714
- {onNavigationRedirect && registerButtonText && (
715
- <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center' }}>
716
- <OText size={14}>
717
- {t('NEW_ON_PLATFORM', 'New on Ordering?')}
718
- </OText>
719
- <TouchableOpacity onPress={() => onNavigationRedirect('Signup')}>
720
- <OText size={14} mLeft={5} color={theme.colors.primary}>
721
- {t('CREATE_ACCOUNT', 'Create account')}
722
- </OText>
723
- </TouchableOpacity>
724
- </View>
725
- )}
726
- </FormInput>
727
- )}
728
-
729
- {useLoginByCellphone &&
730
- loginTab === 'cellphone' &&
731
- configs && Object.keys(configs).length > 0 &&
732
- (configs?.twilio_service_enabled?.value === 'true' ||
733
- configs?.twilio_service_enabled?.value === '1') &&
734
- configs?.twilio_module?.value && (
735
- <>
736
- <OrSeparator>
737
- <LineSeparator />
738
- <OText size={18} mRight={20} mLeft={20}>
739
- {t('OR', 'Or')}
740
- </OText>
741
- <LineSeparator />
742
- </OrSeparator>
743
-
744
- <ButtonsWrapper mBottom={20}>
745
- <OButton
746
- onClick={handleVerifyCodeClick}
747
- text={t('GET_VERIFY_CODE', 'Get Verify Code')}
748
- style={loginStyle.btnOutline}
749
- imgRightSrc={null}
750
- isLoading={isLoadingVerifyModal}
751
- indicatorColor={theme.colors.primary}
752
- />
753
- </ButtonsWrapper>
754
- </>
755
- )}
756
-
757
- {configs && Object.keys(configs).length > 0 ? (
758
- (((configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') && configs?.facebook_id?.value && facebookLoginEnabled) ||
759
- ((configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && googleLoginEnabled) ||
760
- ((configs?.apple_login_client_id?.value !== '' && configs?.apple_login_client_id?.value !== null) && appleLoginEnabled)) && !isGuest &&
761
- (
762
- <>
763
- <View
764
- style={{
765
- flexDirection: 'row',
766
- width: '100%',
767
- justifyContent: 'space-between',
768
- alignItems: 'center',
769
- marginVertical: 15
770
- }}>
771
- <View style={loginStyle.line} />
772
- <OText
773
- size={14}
774
- mBottom={10}
775
- style={{ paddingHorizontal: 19 }}
776
- color={theme.colors.disabled}>
777
- {t('OR', 'or')}
778
- </OText>
779
- <View style={loginStyle.line} />
780
- </View>
781
- <ButtonsWrapper>
782
- <SocialButtons>
783
- {(configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') &&
784
- configs?.facebook_id?.value &&
785
- facebookLoginEnabled && (
786
- <FacebookLogin
787
- notificationState={notificationState}
788
- handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
789
- handleLoading={(val: boolean) => setIsFBLoading(val)}
790
- handleSuccessFacebookLogin={handleSuccessFacebook}
791
- />
792
- )}
793
- {(configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && googleLoginEnabled && (
794
- <GoogleLogin
795
- notificationState={notificationState}
796
- webClientId={configs?.google_login_client_id?.value}
797
- handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
798
- handleLoading={(val: boolean) => setIsFBLoading(val)}
799
- handleSuccessGoogleLogin={handleSuccessFacebook}
800
- />
801
- )}
802
- {(configs?.apple_login_client_id?.value !== '' && configs?.apple_login_client_id?.value !== null) && appleLoginEnabled && (
803
- <AppleLogin
804
- notificationState={notificationState}
805
- handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
806
- handleLoading={(val: boolean) => setIsFBLoading(val)}
807
- handleSuccessAppleLogin={handleSuccessFacebook}
808
- />
809
- )}
810
- </SocialButtons>
811
- </ButtonsWrapper>
812
- </>
813
- )
814
- ) : (
815
- <SkeletonWrapper>
816
- <Placeholder Animation={Fade}>
817
- <PlaceholderLine
818
- height={20}
819
- style={{ marginBottom: 15, marginTop: 10 }}
820
- />
821
- <PlaceholderLine
822
- height={50}
823
- style={{ borderRadius: 25, marginBottom: 25 }}
824
- />
825
- </Placeholder>
826
- </SkeletonWrapper>
827
- )}
828
-
829
- {enabledPoweredByOrdering && (
830
- <OText>
831
- Powered By Ordering.co
832
- </OText>
833
- )}
834
- </FormSide>
835
- <OModal
836
- open={isModalVisible}
837
- onClose={() => setIsModalVisible(false)}
838
- entireModal
839
- title={t('VERIFY_PHONE', 'Verify Phone')}
840
- >
841
- <VerifyPhone
842
- phone={phoneInputData.phone}
843
- verifyPhoneState={verifyPhoneState}
844
- checkPhoneCodeState={checkPhoneCodeState}
845
- handleCheckPhoneCode={handleCheckPhoneCode}
846
- setCheckPhoneCodeState={setCheckPhoneCodeState}
847
- handleVerifyCodeClick={handleVerifyCodeClick}
848
- onClose={() => setIsModalVisible(false)}
849
- />
850
- </OModal>
851
- <Modal
852
- visible={willVerifyOtpState}
853
- onDismiss={() => setWillVerifyOtpState(false)}
854
- animationType='slide'
855
- >
856
- <Otp
857
- isCheckingCode={isCheckingCode}
858
- setCheckingCode={setCheckingCode}
859
- willVerifyOtpState={willVerifyOtpState}
860
- otpError={otpError}
861
- setOtpError={setOtpError}
862
- setWillVerifyOtpState={setWillVerifyOtpState}
863
- handleLoginOtp={handleLoginOtp}
864
- onSubmit={onSubmit}
865
- setAlertState={setAlertState}
866
- />
867
- </Modal>
868
- <Alert
869
- open={alertState.open}
870
- content={alertState.content}
871
- title={alertState.title || ''}
872
- onAccept={closeAlert}
873
- onClose={closeAlert}
874
- />
875
- <Spinner visible={isFBLoading} />
876
- </Container>
877
- );
51
+ const {
52
+ loginTab,
53
+ formState,
54
+ navigation,
55
+ useLoginByEmail,
56
+ useLoginByCellphone,
57
+ useLoginOtp,
58
+ loginButtonText,
59
+ forgotButtonText,
60
+ verifyPhoneState,
61
+ checkPhoneCodeState,
62
+ registerButtonText,
63
+ setCheckPhoneCodeState,
64
+ handleButtonLoginClick,
65
+ handleSendVerifyCode,
66
+ handleCheckPhoneCode,
67
+ onNavigationRedirect,
68
+ notificationState,
69
+ handleReCaptcha,
70
+ enableReCaptcha,
71
+ otpType,
72
+ setOtpType,
73
+ generateOtpCode,
74
+ useLoginOtpEmail,
75
+ useLoginOtpCellphone,
76
+ useLoginOtpWhatsapp,
77
+ isGuest,
78
+ setCellphoneStartZero
79
+ } = props;
80
+
81
+ const [, { showToast }] = useToast();
82
+ const [, t] = useLanguage();
83
+ const [{ configs }] = useConfig();
84
+ const [, { login }] = useSession();
85
+ const { control, handleSubmit, errors, reset, register, setValue } = useForm();
86
+ const [passwordSee, setPasswordSee] = useState(false);
87
+ const [isLoadingVerifyModal, setIsLoadingVerifyModal] = useState(false);
88
+ const [isModalVisible, setIsModalVisible] = useState(false);
89
+ const [isFBLoading, setIsFBLoading] = useState(false);
90
+ const [willVerifyOtpState, setWillVerifyOtpState] = useState(false)
91
+ const [phoneInputData, setPhoneInputData] = useState({
92
+ error: '',
93
+ phone: {
94
+ country_phone_code: null,
95
+ cellphone: null,
96
+ },
97
+ });
98
+ const [recaptchaConfig, setRecaptchaConfig] = useState<any>({})
99
+ const [recaptchaVerified, setRecaptchaVerified] = useState(false)
100
+ const [alertState, setAlertState] = useState({ open: false, title: '', content: [] })
101
+ const [tabLayouts, setTabLayouts] = useState<any>({})
102
+ const [otpError, setOtpError] = useState(null)
103
+ const tabsRef = useRef<any>(null)
104
+ const enabledPoweredByOrdering = configs?.powered_by_ordering_module?.value
105
+ const theme = useTheme();
106
+ const isOtpEmail = loginTab === 'otp' && otpType === 'email'
107
+ const isOtpCellphone = loginTab === 'otp' && otpType === 'cellphone'
108
+
109
+ const [isCheckingCode, setCheckingCode] = useState(false)
110
+
111
+ const googleLoginEnabled = configs?.google_login_enabled?.value === '1'
112
+ const facebookLoginEnabled = configs?.facebook_login_enabled?.value === '1'
113
+ const appleLoginEnabled = Platform.OS === 'ios' && (configs?.apple_login_enabled?.value === '1')
114
+
115
+ const loginStyle = StyleSheet.create({
116
+ btnOutline: {
117
+ backgroundColor: '#FFF',
118
+ color: theme.colors.primary,
119
+ borderRadius: 7.6,
120
+ },
121
+ inputStyle: {
122
+ marginBottom: 28,
123
+ borderWidth: 1,
124
+ // borderColor: theme.colors.border,
125
+ borderRadius: 7.6,
126
+ },
127
+ line: {
128
+ height: 1,
129
+ backgroundColor: theme.colors.border,
130
+ flexGrow: 1,
131
+ marginBottom: 7,
132
+ },
133
+ recaptchaIcon: {
134
+ width: 100,
135
+ height: 100,
136
+ },
137
+ borderStyleBase: {
138
+ width: 30,
139
+ height: 45
140
+ },
141
+
142
+ borderStyleHighLighted: {
143
+ borderColor: "#03DAC6",
144
+ },
145
+
146
+ underlineStyleBase: {
147
+ width: 45,
148
+ height: 60,
149
+ borderWidth: 1,
150
+ fontSize: 16
151
+ },
152
+
153
+ underlineStyleHighLighted: {
154
+ borderColor: theme.colors.primary,
155
+ color: theme.colors.primary,
156
+ fontSize: 16
157
+ },
158
+ });
159
+
160
+ const emailRef = useRef<any>({});
161
+ const passwordRef = useRef<any>({});
162
+ const recaptchaRef = useRef<any>({});
163
+ const otpChannelRef = useRef<number>(2);
164
+
165
+ const handleChangeTab = (val: string, otpType?: string) => {
166
+ props.handleChangeTab(val);
167
+ setPasswordSee(false);
168
+ handleCategoryScroll(otpType ? `${val}_${otpType}` : val)
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 onSubmit = (values?: any) => {
180
+ Keyboard.dismiss();
181
+ if (loginTab === 'otp') {
182
+ if (phoneInputData.error && (loginTab !== 'otp' || (otpType === 'cellphone' && loginTab === 'otp'))) {
183
+ showToast(ToastType.Error, t('INVALID_PHONE_NUMBER', 'Invalid phone number'));
184
+ vibrateApp()
185
+ return
186
+ }
187
+ if (otpType === 'cellphone' && phoneInputData?.error && !phoneInputData?.phone?.cellphone) {
188
+ showToast(ToastType.Error, t('PHONE_NUMBER_REQUIRED', 'Phone number is required'));
189
+ return
190
+ }
191
+ if (loginTab === 'otp') {
192
+ generateOtpCode({
193
+ ...values,
194
+ ...phoneInputData.phone
195
+ }, otpChannelRef.current)
196
+ }
197
+ setWillVerifyOtpState(true)
198
+ } else {
199
+ if (phoneInputData.error) {
200
+ showToast(ToastType.Error, phoneInputData.error);
201
+ vibrateApp()
202
+ return;
203
+ }
204
+ handleButtonLoginClick({
205
+ ...values,
206
+ ...phoneInputData.phone,
207
+ });
208
+ }
209
+
210
+ };
211
+ const handleVerifyCodeClick = () => {
212
+ if (phoneInputData.error) {
213
+ showToast(ToastType.Error, phoneInputData.error);
214
+ vibrateApp()
215
+ return;
216
+ }
217
+ if (
218
+ !phoneInputData.error &&
219
+ !phoneInputData.phone.country_phone_code &&
220
+ !phoneInputData.phone.cellphone
221
+ ) {
222
+ showToast(
223
+ ToastType.Error,
224
+ t(
225
+ 'VALIDATION_ERROR_MOBILE_PHONE_REQUIRED',
226
+ 'The field Mobile phone is required.',
227
+ ),
228
+ );
229
+ vibrateApp()
230
+ return;
231
+ }
232
+ handleSendVerifyCode && handleSendVerifyCode(phoneInputData.phone);
233
+ setIsLoadingVerifyModal(true);
234
+ };
235
+
236
+ const handleSuccessFacebook = (user: any) => {
237
+ login({
238
+ user,
239
+ token: user.session.access_token,
240
+ });
241
+ };
242
+
243
+ const handleChangeInputEmail = (value: string, onChange: any) => {
244
+ onChange(value.toLowerCase().trim().replace(/[&,()%";:ç?<>{}\\[\]\s]/g, ''));
245
+ };
246
+
247
+ const handleOpenRecaptcha = () => {
248
+ setRecaptchaVerified(false)
249
+ if (!recaptchaConfig?.siteKey) {
250
+ showToast(ToastType.Error, t('NO_RECAPTCHA_SITE_KEY', 'The config doesn\'t have recaptcha site key'));
251
+ vibrateApp()
252
+ return
253
+ }
254
+ if (!recaptchaConfig?.baseUrl) {
255
+ showToast(ToastType.Error, t('NO_RECAPTCHA_BASE_URL', 'The config doesn\'t have recaptcha base url'));
256
+ vibrateApp()
257
+ return
258
+ }
259
+
260
+ recaptchaRef.current.open()
261
+ }
262
+
263
+ const onRecaptchaVerify = (token: any) => {
264
+ setRecaptchaVerified(true)
265
+ handleReCaptcha({ code: token, version: recaptchaConfig?.version })
266
+ }
267
+
268
+ const handleChangeOtpType = (type: string) => {
269
+ handleChangeTab('otp', type)
270
+ setOtpType(type)
271
+ }
272
+
273
+ const handleLoginOtp = async (code: string) => {
274
+ if (!code) return
275
+ const logged = await handleButtonLoginClick({ code })
276
+ setCheckingCode(false)
277
+ if (logged) {
278
+ setWillVerifyOtpState(false)
279
+ } else {
280
+ setOtpError(t('OTP_CODE_INCORRECT', 'Otp code incorrect'))
281
+ }
282
+ }
283
+
284
+ const closeAlert = () => {
285
+ setAlertState({
286
+ open: false,
287
+ title: '',
288
+ content: []
289
+ })
290
+ }
291
+
292
+ const handleCategoryScroll = (opc: string) => {
293
+ tabsRef.current.scrollTo({
294
+ x: tabLayouts?.[opc]?.x - 40,
295
+ animated: true
296
+ })
297
+ }
298
+
299
+ const handleOnLayout = (event: any, opc: string) => {
300
+ const _tabLayouts = { ...tabLayouts }
301
+ const categoryKey = opc
302
+ _tabLayouts[categoryKey] = event.nativeEvent.layout
303
+ setTabLayouts(_tabLayouts)
304
+ }
305
+
306
+ const handleChangePhoneNumber = (number: any, rawNumber: any) => {
307
+ setPhoneInputData(number)
308
+ setCellphoneStartZero && setCellphoneStartZero(rawNumber?.number && rawNumber?.countryCallingCode ? rawNumber?.number : null)
309
+ }
310
+
311
+ useEffect(() => {
312
+ if (configs && Object.keys(configs).length > 0 && enableReCaptcha) {
313
+ if (configs?.security_recaptcha_type?.value === 'v3' &&
314
+ configs?.security_recaptcha_score_v3?.value > 0 &&
315
+ configs?.security_recaptcha_site_key_v3?.value
316
+ ) {
317
+ setRecaptchaConfig({
318
+ version: 'v3',
319
+ siteKey: configs?.security_recaptcha_site_key_v3?.value || null,
320
+ baseUrl: configs?.security_recaptcha_base_url?.value || null
321
+ })
322
+ return
323
+ }
324
+ if (configs?.security_recaptcha_site_key?.value) {
325
+ setRecaptchaConfig({
326
+ version: 'v2',
327
+ siteKey: configs?.security_recaptcha_site_key?.value || null,
328
+ baseUrl: configs?.security_recaptcha_base_url?.value || null
329
+ })
330
+ }
331
+ }
332
+ }, [configs, enableReCaptcha])
333
+
334
+ useEffect(() => {
335
+ if (!formState.loading && formState.result?.error) {
336
+ if (formState.result?.result?.[0] === 'ERROR_AUTH_VERIFICATION_CODE') {
337
+ setRecaptchaVerified(false)
338
+ setRecaptchaConfig({
339
+ version: 'v2',
340
+ siteKey: configs?.security_recaptcha_site_key?.value || null,
341
+ baseUrl: configs?.security_recaptcha_base_url?.value || null
342
+ })
343
+ showToast(ToastType.Info, t('TRY_AGAIN', 'Please try again'))
344
+ vibrateApp()
345
+ return
346
+ }
347
+ formState.result?.result &&
348
+ showToast(
349
+ ToastType.Error,
350
+ typeof formState.result?.result === 'string'
351
+ ? formState.result?.result
352
+ : formState.result?.result[0],
353
+ );
354
+ formState.result?.result && vibrateApp()
355
+ }
356
+ }, [formState]);
357
+
358
+ useEffect(() => {
359
+ if (verifyPhoneState && !verifyPhoneState?.loading) {
360
+ if (verifyPhoneState.result?.error) {
361
+ const message =
362
+ typeof verifyPhoneState?.result?.result === 'string'
363
+ ? verifyPhoneState?.result?.result
364
+ : verifyPhoneState?.result?.result[0];
365
+ verifyPhoneState.result?.result && showToast(ToastType.Error, message);
366
+ verifyPhoneState.result?.result && vibrateApp();
367
+ setIsLoadingVerifyModal(false);
368
+ return;
369
+ }
370
+
371
+ const okResult = verifyPhoneState.result?.result === 'OK';
372
+ if (okResult) {
373
+ !isModalVisible && setIsModalVisible(true);
374
+ setIsLoadingVerifyModal(false);
375
+ }
376
+ }
377
+ }, [verifyPhoneState]);
378
+
379
+ useEffect(() => {
380
+ if (phoneInputData?.phone?.cellphone) setValue('cellphone', phoneInputData?.phone?.cellphone, '')
381
+ else setValue('cellphone', '')
382
+ }, [phoneInputData?.phone?.cellphone])
383
+
384
+ useEffect(() => {
385
+ register('cellphone', {
386
+ required: loginTab === 'cellphone'
387
+ ? t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Mobile phone is required').replace('_attribute_', t('CELLPHONE', 'Cellphone'))
388
+ : null
389
+ })
390
+ }, [register])
391
+
392
+ useEffect(() => {
393
+ reset()
394
+ }, [loginTab])
395
+
396
+ useEffect(() => {
397
+ if (checkPhoneCodeState?.result?.error) {
398
+ setAlertState({
399
+ open: true,
400
+ content: t(checkPhoneCodeState?.result?.error, checkPhoneCodeState?.result?.error),
401
+ title: ''
402
+ })
403
+ }
404
+ }, [checkPhoneCodeState])
405
+
406
+ useEffect(() => {
407
+ if (!!Object.values(errors)?.length) vibrateApp()
408
+ }, [errors])
409
+
410
+ return (
411
+ <Container>
412
+ {isGuest ? (
413
+ <OText style={{ textAlign: 'center', marginBottom: 10 }} size={18}>{t('LOGIN', 'Login')}</OText>
414
+ ) : (
415
+ <NavBar
416
+ title={t('LOGIN', 'Login')}
417
+ titleAlign={'center'}
418
+ onActionLeft={() => navigation?.canGoBack() && navigation.goBack()}
419
+ showCall={false}
420
+ btnStyle={{ paddingLeft: 0 }}
421
+ titleWrapStyle={{ paddingHorizontal: 0 }}
422
+ titleStyle={{ marginRight: 0, marginLeft: 0 }}
423
+ />
424
+ )}
425
+ <FormSide>
426
+ {(Number(useLoginByEmail) + Number(useLoginByCellphone) + Number(useLoginOtpEmail) + Number(useLoginOtpCellphone) > 1) && (
427
+ <LoginWith>
428
+ <OTabs
429
+ horizontal
430
+ showsHorizontalScrollIndicator={false}
431
+ ref={tabsRef}
432
+ >
433
+ {useLoginByEmail && (
434
+ <TabBtn
435
+ onPress={() => handleChangeTab('email')}
436
+ onLayout={(event: any) => handleOnLayout(event, 'email')}
437
+ >
438
+ <OTab
439
+ style={{
440
+ borderBottomColor:
441
+ loginTab === 'email'
442
+ ? theme.colors.textNormal
443
+ : theme.colors.border,
444
+ }}>
445
+ <OText
446
+ size={14}
447
+ color={
448
+ loginTab === 'email'
449
+ ? theme.colors.textNormal
450
+ : theme.colors.disabled
451
+ }
452
+ weight={loginTab === 'email' ? 'bold' : 'normal'}>
453
+ {t('LOGIN_BY_EMAIL', 'by Email')}
454
+ </OText>
455
+ </OTab>
456
+ </TabBtn>
457
+ )}
458
+ {useLoginByCellphone && (
459
+ <TabBtn
460
+ onPress={() => handleChangeTab('cellphone')}
461
+ onLayout={(event: any) => handleOnLayout(event, 'cellphone')}
462
+ >
463
+ <OTab
464
+ style={{
465
+ borderBottomColor:
466
+ loginTab === 'cellphone'
467
+ ? theme.colors.textNormal
468
+ : theme.colors.border,
469
+ }}>
470
+ <OText
471
+ size={14}
472
+ color={
473
+ loginTab === 'cellphone'
474
+ ? theme.colors.textNormal
475
+ : theme.colors.disabled
476
+ }
477
+ weight={loginTab === 'cellphone' ? 'bold' : 'normal'}>
478
+ {t('LOGIN_BY_PHONE', 'by Phone')}
479
+ </OText>
480
+ </OTab>
481
+ </TabBtn>
482
+ )}
483
+ {useLoginOtpEmail && (
484
+ <TabBtn
485
+ onPress={() => handleChangeOtpType('email')}
486
+ onLayout={(event: any) => handleOnLayout(event, 'otp_email')}
487
+ >
488
+ <OTab
489
+ style={{
490
+ borderBottomColor:
491
+ isOtpEmail
492
+ ? theme.colors.textNormal
493
+ : theme.colors.border,
494
+ }}>
495
+ <OText
496
+ size={14}
497
+ color={
498
+ isOtpEmail
499
+ ? theme.colors.textNormal
500
+ : theme.colors.disabled
501
+ }
502
+ weight={isOtpEmail ? 'bold' : 'normal'}>
503
+ {t('BY_OTP_EMAIL', 'By Otp Email')}
504
+ </OText>
505
+ </OTab>
506
+ </TabBtn>
507
+ )}
508
+ {useLoginOtpCellphone && (
509
+ <TabBtn
510
+ onPress={() => handleChangeOtpType('cellphone')}
511
+ onLayout={(event: any) => handleOnLayout(event, 'otp_cellphone')}
512
+ >
513
+ <OTab
514
+ style={{
515
+ borderBottomColor:
516
+ isOtpCellphone
517
+ ? theme.colors.textNormal
518
+ : theme.colors.border,
519
+ }}>
520
+ <OText
521
+ size={14}
522
+ color={
523
+ isOtpCellphone
524
+ ? theme.colors.textNormal
525
+ : theme.colors.disabled
526
+ }
527
+ weight={isOtpCellphone ? 'bold' : 'normal'}>
528
+ {t('BY_OTP_PHONE', 'By Otp Phone')}
529
+ </OText>
530
+ </OTab>
531
+ </TabBtn>
532
+ )}
533
+ </OTabs>
534
+ </LoginWith>
535
+ )}
536
+
537
+ {(useLoginByCellphone || useLoginByEmail || useLoginOtp) && (
538
+ <FormInput>
539
+ {((useLoginByEmail && loginTab === 'email') || (loginTab === 'otp' && otpType === 'email')) && (
540
+ <>
541
+ {errors?.email && (
542
+ <OText
543
+ size={14}
544
+ color={theme.colors.danger5}
545
+ weight={'normal'}>
546
+ {errors?.email?.message}{errors?.email?.type === 'required' && '*'}
547
+ </OText>
548
+ )}
549
+ <Controller
550
+ control={control}
551
+ render={({ onChange, value }: any) => (
552
+ <OInput
553
+ placeholder={t('EMAIL', 'Email')}
554
+ style={loginStyle.inputStyle}
555
+ icon={theme.images.general.email}
556
+ onChange={(e: any) => {
557
+ handleChangeInputEmail(e, onChange);
558
+ }}
559
+ value={value}
560
+ autoCapitalize="none"
561
+ autoCorrect={false}
562
+ type="email-address"
563
+ autoCompleteType="email"
564
+ returnKeyType="next"
565
+ onSubmitEditing={() => passwordRef.current?.focus()}
566
+ blurOnSubmit={false}
567
+ forwardRef={emailRef}
568
+ borderColor={errors?.email ? theme.colors.danger5 : theme.colors.border}
569
+ />
570
+ )}
571
+ name="email"
572
+ rules={{
573
+ required: {
574
+ value: true,
575
+ message: t(
576
+ 'VALIDATION_ERROR_EMAIL_REQUIRED',
577
+ 'The field Email is required',
578
+ ).replace('_attribute_', t('EMAIL', 'Email'))
579
+ },
580
+ pattern: {
581
+ value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
582
+ message: t(
583
+ 'INVALID_ERROR_EMAIL',
584
+ 'Invalid email address',
585
+ ).replace('_attribute_', t('EMAIL', 'Email')),
586
+ }
587
+ }}
588
+ defaultValue=""
589
+ />
590
+ </>
591
+
592
+ )}
593
+ {((useLoginByCellphone && loginTab === 'cellphone') || (loginTab === 'otp' && otpType === 'cellphone')) && (
594
+ <View style={{ marginBottom: 28 }}>
595
+ <PhoneInputNumber
596
+ data={phoneInputData}
597
+ handleData={handleChangePhoneNumber}
598
+ textInputProps={{
599
+ returnKeyType: 'next',
600
+ onSubmitEditing: () => passwordRef?.current?.focus?.(),
601
+ }}
602
+ isStartValidation={errors?.cellphone}
603
+ />
604
+ </View>
605
+ )}
606
+ {errors?.password && (
607
+ <OText
608
+ size={14}
609
+ color={theme.colors.danger5}
610
+ weight={'normal'}>
611
+ {errors?.password?.message}{errors?.password?.type === 'required' && '*'}
612
+ </OText>
613
+ )}
614
+ {loginTab !== 'otp' && (
615
+
616
+ <Controller
617
+ control={control}
618
+ render={({ onChange, value }: any) => (
619
+ <OInput
620
+ isSecured={!passwordSee ? true : false}
621
+ placeholder={t('PASSWORD', 'Password')}
622
+ style={{ ...loginStyle.inputStyle, marginBottom: 14 }}
623
+ icon={theme.images.general.lock}
624
+ iconCustomRight={
625
+ !passwordSee ? (
626
+ <MaterialCommunityIcons
627
+ name="eye-outline"
628
+ size={24}
629
+ onPress={() => setPasswordSee(!passwordSee)}
630
+ color={theme.colors.disabled}
631
+ />
632
+ ) : (
633
+ <MaterialCommunityIcons
634
+ name="eye-off-outline"
635
+ size={24}
636
+ onPress={() => setPasswordSee(!passwordSee)}
637
+ color={theme.colors.disabled}
638
+ />
639
+ )
640
+ }
641
+ autoCapitalize='none'
642
+ value={value}
643
+ forwardRef={passwordRef}
644
+ onChange={(val: any) => onChange(val)}
645
+ returnKeyType="done"
646
+ onSubmitEditing={handleSubmit(onSubmit)}
647
+ blurOnSubmit
648
+ borderColor={errors?.password ? theme.colors.danger5 : theme.colors.border}
649
+ />
650
+ )}
651
+ name="password"
652
+ rules={{
653
+ required: {
654
+ value: true,
655
+ message: t(
656
+ 'VALIDATION_ERROR_PASSWORD_REQUIRED',
657
+ 'The field Password is required',
658
+ ).replace('_attribute_', t('PASSWORD', 'Password'))
659
+ }
660
+ }}
661
+ defaultValue=""
662
+ />
663
+ )}
664
+ {onNavigationRedirect && forgotButtonText && loginTab !== 'otp' && (
665
+ <TouchableOpacity onPress={() => onNavigationRedirect('Forgot')}>
666
+ <OText size={14} mBottom={18}>
667
+ {forgotButtonText}
668
+ </OText>
669
+ </TouchableOpacity>
670
+ )}
671
+
672
+ {(enableReCaptcha && recaptchaConfig?.version) && (
673
+ <>
674
+ {recaptchaConfig?.version === 'v3' ? (
675
+ <ReCaptcha
676
+ url={recaptchaConfig?.baseUrl}
677
+ siteKey={recaptchaConfig?.siteKey}
678
+ containerStyle={{ height: 40 }}
679
+ onExecute={onRecaptchaVerify}
680
+ reCaptchaType={1}
681
+ />
682
+ ) : (
683
+ <>
684
+ <TouchableOpacity
685
+ onPress={handleOpenRecaptcha}
686
+ >
687
+ <RecaptchaButton>
688
+ {recaptchaVerified ? (
689
+ <MaterialCommunityIcons
690
+ name="checkbox-marked"
691
+ size={26}
692
+ color={theme.colors.primary}
693
+ />
694
+ ) : (
695
+ <MaterialCommunityIcons
696
+ name="checkbox-blank-outline"
697
+ size={26}
698
+ color={theme.colors.mediumGray}
699
+ />
700
+ )}
701
+ <OText size={14} mLeft={8}>{t('VERIFY_ReCAPTCHA', 'Verify reCAPTCHA')}</OText>
702
+ </RecaptchaButton>
703
+ </TouchableOpacity>
704
+ <Recaptcha
705
+ ref={recaptchaRef}
706
+ siteKey={recaptchaConfig?.siteKey}
707
+ baseUrl={recaptchaConfig?.baseUrl}
708
+ onVerify={onRecaptchaVerify}
709
+ onExpire={() => setRecaptchaVerified(false)}
710
+ />
711
+ </>)
712
+ }
713
+ </>
714
+ )}
715
+ {(loginTab === 'otp' && otpType === 'cellphone' && useLoginOtpWhatsapp)
716
+ ? (
717
+ <View style={{ flexDirection: 'row', gap: 10, marginTop: 10, marginBottom: 25 }}>
718
+ <OButton
719
+ onClick={() => { otpChannelRef.current = 2; handleSubmit(onSubmit)() }}
720
+ text={t('SEND_BY_SMS', 'Send by SMS')}
721
+ imgRightSrc={null}
722
+ isLoading={formState.loading}
723
+ parentStyle={{ flex: 1 }}
724
+ style={{ borderRadius: 7.6 }}
725
+ />
726
+ <OButton
727
+ onClick={() => { otpChannelRef.current = 4; handleSubmit(onSubmit)() }}
728
+ text={t('SEND_BY_WHATSAPP', 'Send by WhatsApp')}
729
+ imgRightSrc={null}
730
+ isLoading={formState.loading}
731
+ parentStyle={{ flex: 1 }}
732
+ style={{ borderRadius: 7.6 }}
733
+ />
734
+ </View>
735
+ )
736
+ : (
737
+ <OButton
738
+ onClick={handleSubmit(onSubmit)}
739
+ text={loginTab !== 'otp' ? loginButtonText : t('GET_VERIFY_CODE', 'Get verify code')}
740
+ imgRightSrc={null}
741
+ isLoading={formState.loading}
742
+ style={{ borderRadius: 7.6, marginTop: 10, marginBottom: 25 }}
743
+ />
744
+ )}
745
+ {onNavigationRedirect && registerButtonText && (
746
+ <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center' }}>
747
+ <OText size={14}>
748
+ {t('NEW_ON_PLATFORM', 'New on Ordering?')}
749
+ </OText>
750
+ <TouchableOpacity onPress={() => onNavigationRedirect('Signup')}>
751
+ <OText size={14} mLeft={5} color={theme.colors.primary}>
752
+ {t('CREATE_ACCOUNT', 'Create account')}
753
+ </OText>
754
+ </TouchableOpacity>
755
+ </View>
756
+ )}
757
+ </FormInput>
758
+ )}
759
+
760
+ {useLoginByCellphone &&
761
+ loginTab === 'cellphone' &&
762
+ configs && Object.keys(configs).length > 0 &&
763
+ (configs?.twilio_service_enabled?.value === 'true' ||
764
+ configs?.twilio_service_enabled?.value === '1') &&
765
+ configs?.twilio_module?.value && (
766
+ <>
767
+ <OrSeparator>
768
+ <LineSeparator />
769
+ <OText size={18} mRight={20} mLeft={20}>
770
+ {t('OR', 'Or')}
771
+ </OText>
772
+ <LineSeparator />
773
+ </OrSeparator>
774
+
775
+ <ButtonsWrapper mBottom={20}>
776
+ <OButton
777
+ onClick={handleVerifyCodeClick}
778
+ text={t('GET_VERIFY_CODE', 'Get Verify Code')}
779
+ style={loginStyle.btnOutline}
780
+ imgRightSrc={null}
781
+ isLoading={isLoadingVerifyModal}
782
+ indicatorColor={theme.colors.primary}
783
+ />
784
+ </ButtonsWrapper>
785
+ </>
786
+ )}
787
+
788
+ {configs && Object.keys(configs).length > 0 ? (
789
+ (((configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') && configs?.facebook_id?.value && facebookLoginEnabled) ||
790
+ ((configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && googleLoginEnabled) ||
791
+ ((configs?.apple_login_client_id?.value !== '' && configs?.apple_login_client_id?.value !== null) && appleLoginEnabled)) && !isGuest &&
792
+ (
793
+ <>
794
+ <View
795
+ style={{
796
+ flexDirection: 'row',
797
+ width: '100%',
798
+ justifyContent: 'space-between',
799
+ alignItems: 'center',
800
+ marginVertical: 15
801
+ }}>
802
+ <View style={loginStyle.line} />
803
+ <OText
804
+ size={14}
805
+ mBottom={10}
806
+ style={{ paddingHorizontal: 19 }}
807
+ color={theme.colors.disabled}>
808
+ {t('OR', 'or')}
809
+ </OText>
810
+ <View style={loginStyle.line} />
811
+ </View>
812
+ <ButtonsWrapper>
813
+ <SocialButtons>
814
+ {(configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') &&
815
+ configs?.facebook_id?.value &&
816
+ facebookLoginEnabled && (
817
+ <FacebookLogin
818
+ notificationState={notificationState}
819
+ handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
820
+ handleLoading={(val: boolean) => setIsFBLoading(val)}
821
+ handleSuccessFacebookLogin={handleSuccessFacebook}
822
+ />
823
+ )}
824
+ {(configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && googleLoginEnabled && (
825
+ <GoogleLogin
826
+ notificationState={notificationState}
827
+ webClientId={configs?.google_login_client_id?.value}
828
+ handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
829
+ handleLoading={(val: boolean) => setIsFBLoading(val)}
830
+ handleSuccessGoogleLogin={handleSuccessFacebook}
831
+ />
832
+ )}
833
+ {(configs?.apple_login_client_id?.value !== '' && configs?.apple_login_client_id?.value !== null) && appleLoginEnabled && (
834
+ <AppleLogin
835
+ notificationState={notificationState}
836
+ handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
837
+ handleLoading={(val: boolean) => setIsFBLoading(val)}
838
+ handleSuccessAppleLogin={handleSuccessFacebook}
839
+ />
840
+ )}
841
+ </SocialButtons>
842
+ </ButtonsWrapper>
843
+ </>
844
+ )
845
+ ) : (
846
+ <SkeletonWrapper>
847
+ <Placeholder Animation={Fade}>
848
+ <PlaceholderLine
849
+ height={20}
850
+ style={{ marginBottom: 15, marginTop: 10 }}
851
+ />
852
+ <PlaceholderLine
853
+ height={50}
854
+ style={{ borderRadius: 25, marginBottom: 25 }}
855
+ />
856
+ </Placeholder>
857
+ </SkeletonWrapper>
858
+ )}
859
+
860
+ {enabledPoweredByOrdering && (
861
+ <OText>
862
+ Powered By Ordering.co
863
+ </OText>
864
+ )}
865
+ </FormSide>
866
+ <OModal
867
+ open={isModalVisible}
868
+ onClose={() => setIsModalVisible(false)}
869
+ entireModal
870
+ title={t('VERIFY_PHONE', 'Verify Phone')}
871
+ >
872
+ <VerifyPhone
873
+ phone={phoneInputData.phone}
874
+ verifyPhoneState={verifyPhoneState}
875
+ checkPhoneCodeState={checkPhoneCodeState}
876
+ handleCheckPhoneCode={handleCheckPhoneCode}
877
+ setCheckPhoneCodeState={setCheckPhoneCodeState}
878
+ handleVerifyCodeClick={handleVerifyCodeClick}
879
+ onClose={() => setIsModalVisible(false)}
880
+ />
881
+ </OModal>
882
+ <Modal
883
+ visible={willVerifyOtpState}
884
+ onDismiss={() => setWillVerifyOtpState(false)}
885
+ animationType='slide'
886
+ >
887
+ <Otp
888
+ isCheckingCode={isCheckingCode}
889
+ setCheckingCode={setCheckingCode}
890
+ willVerifyOtpState={willVerifyOtpState}
891
+ otpError={otpError}
892
+ setOtpError={setOtpError}
893
+ setWillVerifyOtpState={setWillVerifyOtpState}
894
+ handleLoginOtp={handleLoginOtp}
895
+ onSubmit={onSubmit}
896
+ setAlertState={setAlertState}
897
+ />
898
+ </Modal>
899
+ <Alert
900
+ open={alertState.open}
901
+ content={alertState.content}
902
+ title={alertState.title || ''}
903
+ onAccept={closeAlert}
904
+ onClose={closeAlert}
905
+ />
906
+ <Spinner visible={isFBLoading} />
907
+ </Container>
908
+ );
878
909
  };
879
910
 
880
911
  export const LoginForm = (props: any) => {
881
- const loginProps = {
882
- ...props,
883
- isRecaptchaEnable: true,
884
- UIComponent: LoginFormUI,
885
- };
886
- return <LoginFormController {...loginProps} />;
912
+ const loginProps = {
913
+ ...props,
914
+ isRecaptchaEnable: true,
915
+ UIComponent: LoginFormUI,
916
+ };
917
+ return <LoginFormController {...loginProps} />;
887
918
  };