ordering-ui-react-native 0.12.14 → 0.12.18

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 (105) hide show
  1. package/package.json +1 -1
  2. package/src/components/AddressList/index.tsx +3 -1
  3. package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +168 -156
  4. package/themes/business/src/components/NewOrderNotification/index.tsx +14 -1
  5. package/themes/business/src/components/OrderDetails/Delivery.tsx +3 -1
  6. package/themes/business/src/components/OrdersOption/index.tsx +19 -15
  7. package/themes/business/src/components 2/AcceptOrRejectOrder/index.tsx +389 -0
  8. package/themes/business/src/components 2/AcceptOrRejectOrder/styles.tsx +36 -0
  9. package/themes/business/src/components 2/BusinessController/index.tsx +155 -0
  10. package/themes/business/src/components 2/BusinessController/styles.tsx +19 -0
  11. package/themes/business/src/components 2/Chat/index.tsx +1152 -0
  12. package/themes/business/src/components 2/Chat/styles.tsx +12 -0
  13. package/themes/business/src/components 2/Contacts/index.tsx +299 -0
  14. package/themes/business/src/components 2/Contacts/styles.tsx +42 -0
  15. package/themes/business/src/components 2/DriverMap/index.tsx +525 -0
  16. package/themes/business/src/components 2/FloatingButton/index.tsx +141 -0
  17. package/themes/business/src/components 2/FloatingButton/styles.tsx +35 -0
  18. package/themes/business/src/components 2/ForgotPasswordForm/index.tsx +204 -0
  19. package/themes/business/src/components 2/ForgotPasswordForm/styles.tsx +11 -0
  20. package/themes/business/src/components 2/GoogleMap/index.tsx +347 -0
  21. package/themes/business/src/components 2/Home/index.tsx +111 -0
  22. package/themes/business/src/components 2/Home/styles.tsx +27 -0
  23. package/themes/business/src/components 2/LanguageSelector/index.tsx +124 -0
  24. package/themes/business/src/components 2/LanguageSelector/lang_country.json +152 -0
  25. package/themes/business/src/components 2/LanguageSelector/styles.tsx +17 -0
  26. package/themes/business/src/components 2/LoginForm/index.tsx +663 -0
  27. package/themes/business/src/components 2/LoginForm/styles.tsx +48 -0
  28. package/themes/business/src/components 2/LogoutButton/index.tsx +63 -0
  29. package/themes/business/src/components 2/MapView/index.tsx +317 -0
  30. package/themes/business/src/components 2/MessagesOption/index.tsx +337 -0
  31. package/themes/business/src/components 2/MessagesOption/styles.tsx +27 -0
  32. package/themes/business/src/components 2/NewOrderNotification/index.tsx +167 -0
  33. package/themes/business/src/components 2/NewOrderNotification/styles.tsx +8 -0
  34. package/themes/business/src/components 2/NotFoundSource/index.tsx +52 -0
  35. package/themes/business/src/components 2/NotFoundSource/styles.tsx +17 -0
  36. package/themes/business/src/components 2/OrderDetails/Business.tsx +683 -0
  37. package/themes/business/src/components 2/OrderDetails/Delivery.tsx +454 -0
  38. package/themes/business/src/components 2/OrderDetails/OrderContentComponent.tsx +391 -0
  39. package/themes/business/src/components 2/OrderDetails/OrderHeaderComponent.tsx +148 -0
  40. package/themes/business/src/components 2/OrderDetails/styles.tsx +84 -0
  41. package/themes/business/src/components 2/OrderMessage/index.tsx +344 -0
  42. package/themes/business/src/components 2/OrderMessage/styles.tsx +5 -0
  43. package/themes/business/src/components 2/OrderSummary/index.tsx +700 -0
  44. package/themes/business/src/components 2/OrderSummary/styles.tsx +61 -0
  45. package/themes/business/src/components 2/OrdersOption/index.tsx +755 -0
  46. package/themes/business/src/components 2/OrdersOption/styles.tsx +54 -0
  47. package/themes/business/src/components 2/OrdersOptionBusiness/index.tsx +51 -0
  48. package/themes/business/src/components 2/OrdersOptionBusiness/styles.tsx +8 -0
  49. package/themes/business/src/components 2/OrdersOptionCity/index.tsx +52 -0
  50. package/themes/business/src/components 2/OrdersOptionCity/styles.tsx +8 -0
  51. package/themes/business/src/components 2/OrdersOptionDate/index.tsx +52 -0
  52. package/themes/business/src/components 2/OrdersOptionDate/styles.tsx +8 -0
  53. package/themes/business/src/components 2/OrdersOptionDelivery/index.tsx +35 -0
  54. package/themes/business/src/components 2/OrdersOptionDelivery/styles.tsx +8 -0
  55. package/themes/business/src/components 2/OrdersOptionDriver/index.tsx +50 -0
  56. package/themes/business/src/components 2/OrdersOptionDriver/styles.tsx +8 -0
  57. package/themes/business/src/components 2/OrdersOptionPaymethod/index.tsx +49 -0
  58. package/themes/business/src/components 2/OrdersOptionPaymethod/styles.tsx +8 -0
  59. package/themes/business/src/components 2/OrdersOptionStatus/index.tsx +46 -0
  60. package/themes/business/src/components 2/OrdersOptionStatus/styles.tsx +8 -0
  61. package/themes/business/src/components 2/PhoneInputNumber/index.tsx +160 -0
  62. package/themes/business/src/components 2/PhoneInputNumber/styles.tsx +3 -0
  63. package/themes/business/src/components 2/PreviousMessages/index.tsx +304 -0
  64. package/themes/business/src/components 2/PreviousMessages/styles.tsx +32 -0
  65. package/themes/business/src/components 2/PreviousOrders/index.tsx +180 -0
  66. package/themes/business/src/components 2/PreviousOrders/styles.tsx +38 -0
  67. package/themes/business/src/components 2/ProductItemAccordion/index.tsx +301 -0
  68. package/themes/business/src/components 2/ProductItemAccordion/styles.tsx +61 -0
  69. package/themes/business/src/components 2/SearchBar/index.tsx +112 -0
  70. package/themes/business/src/components 2/SignupForm/index.tsx +530 -0
  71. package/themes/business/src/components 2/SignupForm/styles.tsx +16 -0
  72. package/themes/business/src/components 2/StoresList/index.tsx +208 -0
  73. package/themes/business/src/components 2/StoresList/styles.tsx +26 -0
  74. package/themes/business/src/components 2/UserFormDetails/index.tsx +513 -0
  75. package/themes/business/src/components 2/UserFormDetails/styles.tsx +40 -0
  76. package/themes/business/src/components 2/UserProfileForm/index.tsx +496 -0
  77. package/themes/business/src/components 2/UserProfileForm/styles.tsx +36 -0
  78. package/themes/business/src/components 2/VerifyPhone/index.tsx +201 -0
  79. package/themes/business/src/components 2/VerifyPhone/styles.tsx +43 -0
  80. package/themes/business/src/components 2/shared/OAlert.tsx +52 -0
  81. package/themes/business/src/components 2/shared/OButton.tsx +149 -0
  82. package/themes/business/src/components 2/shared/OChatBubble.tsx +100 -0
  83. package/themes/business/src/components 2/shared/ODropDown.tsx +195 -0
  84. package/themes/business/src/components 2/shared/ODropDownCalendar.tsx +328 -0
  85. package/themes/business/src/components 2/shared/OFab.tsx +54 -0
  86. package/themes/business/src/components 2/shared/OIcon.tsx +67 -0
  87. package/themes/business/src/components 2/shared/OIconButton.tsx +127 -0
  88. package/themes/business/src/components 2/shared/OInput.tsx +144 -0
  89. package/themes/business/src/components 2/shared/OLink.tsx +76 -0
  90. package/themes/business/src/components 2/shared/OModal.tsx +275 -0
  91. package/themes/business/src/components 2/shared/OSegment.tsx +86 -0
  92. package/themes/business/src/components 2/shared/OText.tsx +55 -0
  93. package/themes/business/src/components 2/shared/OTextarea.tsx +46 -0
  94. package/themes/business/src/components 2/shared/OToast.tsx +92 -0
  95. package/themes/business/src/components 2/shared/index.tsx +27 -0
  96. package/themes/business/src/types/index.tsx +4 -1
  97. package/themes/kiosk/src/components/CategoriesMenu/index.tsx +128 -83
  98. package/themes/kiosk/src/components/DrawerView/index.tsx +57 -0
  99. package/themes/kiosk/src/components/DrawerView/styles.tsx +30 -0
  100. package/themes/kiosk/src/components/LanguageSelector/index.tsx +78 -58
  101. package/themes/kiosk/src/components/OrderDetails/index.tsx +3 -1
  102. package/themes/kiosk/src/components/ProductForm/index.tsx +129 -127
  103. package/themes/kiosk/src/components/ProductForm/styles.tsx +1 -1
  104. package/themes/original/src/components/BusinessesListing/index.tsx +9 -6
  105. package/themes/original/src/components/OrderProgress/index.tsx +32 -18
@@ -0,0 +1,663 @@
1
+ import React, { useEffect, useState, useRef } from 'react';
2
+ import {
3
+ Pressable,
4
+ StyleSheet,
5
+ Keyboard,
6
+ View,
7
+ Dimensions,
8
+ ScrollView,
9
+ } from 'react-native';
10
+ import { useForm, Controller } from 'react-hook-form';
11
+ import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
12
+ import {
13
+ ToastType,
14
+ useToast,
15
+ LoginForm as LoginFormController,
16
+ useLanguage,
17
+ useConfig,
18
+ useApi
19
+ } from 'ordering-components/native';
20
+ import { useTheme } from 'styled-components/native';
21
+ import {
22
+ LoginWith,
23
+ ButtonsWrapper,
24
+ FormInput,
25
+ TabsContainer,
26
+ OrSeparator,
27
+ LineSeparator,
28
+ } from './styles';
29
+ import { _setStoreData } from '../../providers/StoreUtil'
30
+ import { OText, OButton, OInput, OIconButton, OModal } from '../shared';
31
+ import { PhoneInputNumber } from '../PhoneInputNumber';
32
+ import { VerifyPhone } from '../VerifyPhone';
33
+ import { LoginParams } from '../../types';
34
+
35
+ const LoginFormUI = (props: LoginParams) => {
36
+ const {
37
+ navigation,
38
+ formState,
39
+ handleButtonLoginClick,
40
+ onNavigationRedirect,
41
+ loginTab,
42
+ useLoginByCellphone,
43
+ useLoginByEmail,
44
+ handleSendVerifyCode,
45
+ verifyPhoneState,
46
+ checkPhoneCodeState,
47
+ handleCheckPhoneCode,
48
+ setCheckPhoneCodeState,
49
+ allowedLevels,
50
+ useRootPoint
51
+ } = props;
52
+
53
+ const [ordering, { setOrdering }] = useApi();
54
+ const [, { showToast }] = useToast();
55
+ const [, t] = useLanguage();
56
+ const theme = useTheme();
57
+ const [{ configs }] = useConfig();
58
+ const { control, handleSubmit, errors, clearErrors } = useForm();
59
+
60
+ const scrollRefTab = useRef() as React.MutableRefObject<ScrollView>;
61
+ const inputRef = useRef<any>(null);
62
+ const inputMailRef = useRef<any>(null);
63
+
64
+ const [passwordSee, setPasswordSee] = useState(false);
65
+ const [isLoadingVerifyModal, setIsLoadingVerifyModal] = useState(false);
66
+ const [isModalVisible, setIsModalVisible] = useState(false);
67
+ const [loading, setLoading] = useState(false);
68
+ const [phoneInputData, setPhoneInputData] = useState({
69
+ error: '',
70
+ phone: {
71
+ country_phone_code: null,
72
+ cellphone: null,
73
+ },
74
+ });
75
+ const [windowWidth, setWindowWidth] = useState(
76
+ parseInt(parseFloat(String(Dimensions.get('window').width)).toFixed(0)),
77
+ );
78
+ const [orientation, setOrientation] = useState(
79
+ Dimensions.get('window').width < Dimensions.get('window').height
80
+ ? 'Portrait'
81
+ : 'Landscape',
82
+ );
83
+
84
+ const [submitted, setSubmitted] = useState(false);
85
+ const [formValues, setFormValues] = useState(null);
86
+
87
+ const getTraduction = (key: string) => {
88
+ const keyList: any = {
89
+ // Add the key and traduction that you need below
90
+ ERROR_ORDER_WITHOUT_CART: 'The order was placed without a cart',
91
+ ERROR_INVALID_COUPON: "The coupon doesn't exist",
92
+ ERROR_IVALID_COUPON_MINIMUM:
93
+ 'You must have more products in your cart to use the coupon',
94
+ ERROR_ADD_PRODUCT_VERY_FAR_FOR_PICKUP:
95
+ 'The business is too far for order type pickup',
96
+ ERROR_PLACE_PAY_WITH_CARD2:
97
+ 'An error occurred while trying to pay by card',
98
+ ERROR_ADD_PRODUCT_BUSINESS_CLOSED: 'The business is closed at the moment',
99
+ INTERNAL_ERROR: 'Server Error, please wait, we are working to fix it',
100
+ ERROR_NOT_FOUND_BUSINESSES: 'No businesses found near your location',
101
+ YOU_DO_NOT_HAVE_PERMISSION: 'You do not have permission',
102
+ INVALID_CODE: 'Invalid verify code',
103
+ STRIPE_ERROR: 'Payment service error. Try again later.',
104
+ ERROR_AUTH_TWILIO_DISABLED: 'Auth error, twilio is disabled',
105
+ ERROR_CART_SELECT_PAYMETHOD: 'An error occurred with selected pay method',
106
+ ERROR_YOU_HAVE_ACTIVE_CART: "You can't reorder this cart",
107
+ ERROR_YOU_HAVE_NOT_CART: 'Cart not found',
108
+ ERROR_PLACE_PAY_WITH_REDIRECT:
109
+ 'An error occurred while trying to pay by redirect',
110
+ ERROR_PLACE_PAY_WITH_CARD1:
111
+ 'An error occurred while trying to pay by card',
112
+ ERROR_PLACE_PAY_WITH_PAYPAL_CAPTURE:
113
+ 'An error occurred while trying to pay by PayPal',
114
+ ERROR_ADD_PRODUCT_VERY_FAR_FOR_DELIVERY:
115
+ 'Error adding product, very far for delivery',
116
+ };
117
+
118
+ return keyList[key] ? t(key, keyList[key]) : t(key);
119
+ };
120
+
121
+ const handleChangeTab = (val: string) => {
122
+ setPhoneInputData({ ...phoneInputData, error: '' });
123
+ clearErrors([val]);
124
+ props.handleChangeTab(val);
125
+
126
+ if (loginTab === 'email') {
127
+ scrollRefTab.current?.scrollToEnd({ animated: true });
128
+ }
129
+
130
+ if (loginTab === 'cellphone') {
131
+ scrollRefTab.current?.scrollTo({ animated: true });
132
+ }
133
+ };
134
+
135
+ const handleChangeInputEmail = (value: string, onChange: any) => {
136
+ onChange(value.toLowerCase().replace(/[&,()%";:ç?<>{}\\[\]\s]/g, ''));
137
+ };
138
+
139
+ const handleLogin = () => {
140
+ setLoading(true);
141
+
142
+ handleSubmit(onSubmit)();
143
+ };
144
+
145
+ const onSubmit = (values: any) => {
146
+ Keyboard.dismiss();
147
+
148
+ if (phoneInputData.error) {
149
+ showToast(ToastType.Error, phoneInputData.error);
150
+ return;
151
+ }
152
+
153
+ if (values?.project_name) {
154
+ setOrdering({
155
+ ...ordering,
156
+ project: values?.project_name
157
+ })
158
+ _setStoreData('project_name', values?.project_name)
159
+ setFormValues({ ...values, ...phoneInputData.phone })
160
+ setSubmitted(true)
161
+ return
162
+ }
163
+
164
+ handleButtonLoginClick({
165
+ ...values,
166
+ ...phoneInputData.phone
167
+ });
168
+ };
169
+
170
+ const handleVerifyCodeClick = () => {
171
+ if (phoneInputData.error) {
172
+ showToast(ToastType.Error, phoneInputData.error);
173
+ return;
174
+ }
175
+
176
+ if (
177
+ !phoneInputData.error &&
178
+ !phoneInputData.phone.country_phone_code &&
179
+ !phoneInputData.phone.cellphone
180
+ ) {
181
+ showToast(
182
+ ToastType.Error,
183
+ t(
184
+ 'VALIDATION_ERROR_MOBILE_PHONE_REQUIRED',
185
+ 'The field Mobile phone is required.',
186
+ ),
187
+ );
188
+ return;
189
+ }
190
+
191
+ handleSendVerifyCode && handleSendVerifyCode(phoneInputData.phone);
192
+ setIsLoadingVerifyModal(true);
193
+ };
194
+
195
+ useEffect(() => {
196
+ if (!formState?.loading && formState?.result?.error) {
197
+ formState?.result?.result &&
198
+ showToast(
199
+ ToastType.Error,
200
+ loginTab === 'email' && typeof formState.result?.result === 'string'
201
+ ? getTraduction(formState.result?.result)
202
+ : loginTab === 'email' &&
203
+ typeof formState.result?.result !== 'string'
204
+ ? getTraduction(formState.result?.result[0])
205
+ : loginTab === 'cellphone' &&
206
+ typeof formState.result?.result === 'string'
207
+ ? getTraduction(formState.result?.result).replace(
208
+ t('USER', 'user').toLowerCase(),
209
+ t('PHONE_NUMER', 'Phone number'),
210
+ )
211
+ : getTraduction(formState.result?.result[0]).replace(
212
+ t('USER', 'user').toLowerCase(),
213
+ t('PHONE_NUMER', 'Phone number'),
214
+ ),
215
+ );
216
+ setSubmitted(false)
217
+ }
218
+ }, [formState]);
219
+
220
+ useEffect(() => {
221
+ if (verifyPhoneState && !verifyPhoneState?.loading) {
222
+ if (verifyPhoneState.result?.error) {
223
+ const message =
224
+ typeof verifyPhoneState?.result?.result === 'string'
225
+ ? verifyPhoneState?.result?.result
226
+ : verifyPhoneState?.result?.result[0];
227
+ verifyPhoneState.result?.result && showToast(ToastType.Error, message);
228
+ setIsLoadingVerifyModal(false);
229
+ return;
230
+ }
231
+
232
+ const okResult = verifyPhoneState.result?.result === 'OK';
233
+ if (okResult) {
234
+ !isModalVisible && setIsModalVisible(true);
235
+ setIsLoadingVerifyModal(false);
236
+ }
237
+ }
238
+ }, [verifyPhoneState]);
239
+
240
+ useEffect(() => {
241
+ if (Object.keys(errors).length > 0) {
242
+ // Convert all errors in one string to show in toast provider
243
+ const list = Object.values(errors);
244
+ let stringError = '';
245
+
246
+ if (phoneInputData.error) {
247
+ list.unshift({ message: phoneInputData.error });
248
+ }
249
+
250
+ if (
251
+ loginTab === 'cellphone' &&
252
+ !phoneInputData.error &&
253
+ !phoneInputData.phone.country_phone_code &&
254
+ !phoneInputData.phone.cellphone
255
+ ) {
256
+ list.unshift({
257
+ message: t(
258
+ 'VALIDATION_ERROR_MOBILE_PHONE_REQUIRED',
259
+ 'The field Mobile phone is required.',
260
+ ),
261
+ });
262
+ }
263
+
264
+ list.map((item: any, i: number) => {
265
+ stringError +=
266
+ i + 1 === list.length ? `- ${item.message}` : `- ${item.message}\n`;
267
+ });
268
+
269
+ showToast(ToastType.Error, stringError);
270
+ }
271
+ }, [errors]);
272
+
273
+ useEffect(() => {
274
+ if (loading && !formState?.loading) {
275
+ setLoading(false);
276
+ }
277
+ }, [loading]);
278
+
279
+ useEffect(() => {
280
+ if (ordering.project === null || !submitted || !useRootPoint) return
281
+ const values: any = formValues
282
+ if (values?.project_name) {
283
+ delete values.project_name
284
+ }
285
+ handleButtonLoginClick({ ...values })
286
+ }, [ordering, submitted])
287
+
288
+ Dimensions.addEventListener('change', ({ window: { width, height } }) => {
289
+ setWindowWidth(
290
+ parseInt(parseFloat(String(Dimensions.get('window').width)).toFixed(0)),
291
+ );
292
+
293
+ if (width < height) {
294
+ setOrientation('Portrait');
295
+ } else {
296
+ setOrientation('Landscape');
297
+ }
298
+ });
299
+
300
+ const styles = StyleSheet.create({
301
+ container: {
302
+ justifyContent: 'center',
303
+ alignItems: 'center',
304
+ paddingBottom: 40,
305
+ },
306
+ header: {
307
+ marginBottom: 30,
308
+ justifyContent: 'space-between',
309
+ width: '100%',
310
+ },
311
+ arrowLeft: {
312
+ maxWidth: 40,
313
+ height: 25,
314
+ justifyContent: 'flex-end',
315
+ marginBottom: 25,
316
+ },
317
+ title: {
318
+ fontFamily: 'Poppins',
319
+ fontStyle: 'normal',
320
+ fontWeight: '600',
321
+ fontSize: 26,
322
+ color: theme.colors.textGray,
323
+ },
324
+ btnTab: {
325
+ flex: 1,
326
+ minWidth: 88,
327
+ alignItems: 'center',
328
+ },
329
+ btnTabText: {
330
+ fontFamily: 'Poppins',
331
+ fontStyle: 'normal',
332
+ fontSize: 16,
333
+ marginBottom: 10,
334
+ paddingLeft: 8,
335
+ paddingRight: 8,
336
+ },
337
+ input: {
338
+ color: theme.colors.arrowColor,
339
+ marginBottom: 20,
340
+ borderWidth: 1,
341
+ borderRadius: 7.6,
342
+ borderColor: theme.colors.inputSignup,
343
+ backgroundColor: theme.colors.transparent,
344
+ },
345
+ btn: {
346
+ borderRadius: 7.6,
347
+ height: 44,
348
+ },
349
+ btnText: {
350
+ color: theme.colors.inputTextColor,
351
+ fontFamily: 'Poppins',
352
+ fontStyle: 'normal',
353
+ fontWeight: 'normal',
354
+ fontSize: 18,
355
+ },
356
+ btnFlag: {
357
+ width: 79,
358
+ borderWidth: 1,
359
+ borderRadius: 7.6,
360
+ marginRight: 9,
361
+ borderColor: theme.colors.inputSignup,
362
+ },
363
+ textForgot: {
364
+ color: theme.colors.arrowColor,
365
+ fontFamily: 'Poppins',
366
+ fontStyle: 'normal',
367
+ fontWeight: 'normal',
368
+ fontSize: 16,
369
+ },
370
+ });
371
+
372
+ return (
373
+ <View style={styles.container}>
374
+ <View style={styles.header}>
375
+ <OIconButton
376
+ icon={theme.images.general.arrow_left}
377
+ borderColor={theme.colors.clear}
378
+ iconStyle={{ width: 20, height: 20 }}
379
+ style={styles.arrowLeft}
380
+ onClick={() => navigation?.canGoBack() && navigation.goBack()}
381
+ />
382
+
383
+ <OText style={styles.title}>{t('LOGIN', 'Login')}</OText>
384
+ </View>
385
+
386
+ {(useLoginByEmail || useLoginByCellphone) && (
387
+ <LoginWith>
388
+ <ScrollView
389
+ ref={scrollRefTab}
390
+ showsVerticalScrollIndicator={false}
391
+ showsHorizontalScrollIndicator={false}
392
+ horizontal>
393
+ <TabsContainer width={windowWidth - 42}>
394
+ {useLoginByEmail && (
395
+ <Pressable
396
+ style={styles.btnTab}
397
+ onPress={() => handleChangeTab('email')}>
398
+ <OText
399
+ style={styles.btnTabText}
400
+ color={
401
+ loginTab === 'email'
402
+ ? theme.colors.textGray
403
+ : theme.colors.unselectText
404
+ }
405
+ weight={loginTab === 'email' ? '600' : 'normal'}>
406
+ {t('BY_EMAIL', 'by Email')}
407
+ </OText>
408
+
409
+ <View
410
+ style={{
411
+ width: '100%',
412
+ borderBottomColor:
413
+ loginTab === 'email'
414
+ ? theme.colors.textGray
415
+ : theme.colors.tabBar,
416
+ borderBottomWidth: 2,
417
+ }}></View>
418
+ </Pressable>
419
+ )}
420
+
421
+ {useLoginByCellphone && (
422
+ <Pressable
423
+ style={styles.btnTab}
424
+ onPress={() => handleChangeTab('cellphone')}>
425
+ <OText
426
+ style={styles.btnTabText}
427
+ color={
428
+ loginTab === 'cellphone'
429
+ ? theme.colors.textGray
430
+ : theme.colors.unselectText
431
+ }
432
+ weight={loginTab === 'cellphone' ? '600' : 'normal'}>
433
+ {t('BY_PHONE', 'by Phone')}
434
+ </OText>
435
+
436
+ <View
437
+ style={{
438
+ width: '100%',
439
+ borderBottomColor:
440
+ loginTab === 'cellphone'
441
+ ? theme.colors.textGray
442
+ : theme.colors.tabBar,
443
+ borderBottomWidth: 2,
444
+ }}></View>
445
+ </Pressable>
446
+ )}
447
+ </TabsContainer>
448
+ </ScrollView>
449
+ </LoginWith>
450
+ )}
451
+
452
+ {(useLoginByCellphone || useLoginByEmail) && (
453
+ <FormInput>
454
+ {useRootPoint && (
455
+ <Controller
456
+ control={control}
457
+ name='project_name'
458
+ rules={{ required: t(`VALIDATION_ERROR_PROJECT_NAME_REQUIRED`, 'The field project name is required') }}
459
+ defaultValue=""
460
+ render={({ onChange, value }: any) => (
461
+ <OInput
462
+ name='project_name'
463
+ placeholderTextColor={theme.colors.arrowColor}
464
+ placeholder={t('PROJECT_NAME', 'Project Name')}
465
+ icon={theme.images.general.project}
466
+ iconColor={theme.colors.arrowColor}
467
+ onChange={(e: any) => {
468
+ onChange(e?.target?.value);
469
+ setSubmitted(false);
470
+ }}
471
+ selectionColor={theme.colors.primary}
472
+ color={theme.colors.textGray}
473
+ value={value}
474
+ style={styles.input}
475
+ returnKeyType='next'
476
+ autoCorrect={false}
477
+ autoCapitalize='none'
478
+ onSubmitEditing={() => inputMailRef.current?.focus()}
479
+ blurOnSubmit={false}
480
+ />
481
+ )}
482
+ />
483
+ )}
484
+
485
+ {useLoginByEmail && loginTab === 'email' && (
486
+ <Controller
487
+ control={control}
488
+ render={({ onChange, value }: any) => (
489
+ <OInput
490
+ placeholder={t('EMAIL', 'Email')}
491
+ placeholderTextColor={theme.colors.arrowColor}
492
+ style={styles.input}
493
+ icon={theme.images.logos.emailInputIcon}
494
+ iconColor={theme.colors.arrowColor}
495
+ onChange={(e: any) => {
496
+ handleChangeInputEmail(e, onChange);
497
+ }}
498
+ selectionColor={theme.colors.primary}
499
+ color={theme.colors.textGray}
500
+ value={value}
501
+ autoCapitalize="none"
502
+ autoCorrect={false}
503
+ type="email-address"
504
+ autoCompleteType="email"
505
+ forwardRef={inputMailRef}
506
+ returnKeyType="next"
507
+ onSubmitEditing={() => inputRef.current?.focus()}
508
+ blurOnSubmit={false}
509
+ />
510
+ )}
511
+ name="email"
512
+ rules={{
513
+ required: t(
514
+ 'VALIDATION_ERROR_EMAIL_REQUIRED',
515
+ 'The field Email is required',
516
+ ).replace('_attribute_', t('EMAIL', 'Email')),
517
+ pattern: {
518
+ value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
519
+ message: t(
520
+ 'INVALID_ERROR_EMAIL',
521
+ 'Invalid email address',
522
+ ).replace('_attribute_', t('EMAIL', 'Email')),
523
+ },
524
+ }}
525
+ defaultValue=""
526
+ />
527
+ )}
528
+
529
+ {useLoginByCellphone && loginTab === 'cellphone' && (
530
+ <View style={{ marginBottom: 20 }}>
531
+ <PhoneInputNumber
532
+ data={phoneInputData}
533
+ handleData={(val: any) => setPhoneInputData(val)}
534
+ flagProps={styles.btnFlag}
535
+ onSubmitEditing={() => null}
536
+ textInputProps={{
537
+ returnKeyType: 'next',
538
+ onSubmitEditing: () => inputRef.current.focus(),
539
+ }}
540
+ />
541
+ </View>
542
+ )}
543
+
544
+ <Controller
545
+ control={control}
546
+ render={({ onChange, value }: any) => (
547
+ <OInput
548
+ isSecured={!passwordSee ? true : false}
549
+ placeholder={t('PASSWORD', 'Password')}
550
+ placeholderTextColor={theme.colors.arrowColor}
551
+ style={styles.input}
552
+ icon={theme.images.logos.passwordInputIcon}
553
+ iconColor={theme.colors.arrowColor}
554
+ iconCustomRight={
555
+ !passwordSee ? (
556
+ <MaterialCommunityIcons
557
+ name="eye-outline"
558
+ size={24}
559
+ color={theme.colors.arrowColor}
560
+ onPress={() => setPasswordSee(!passwordSee)}
561
+ />
562
+ ) : (
563
+ <MaterialCommunityIcons
564
+ name="eye-off-outline"
565
+ size={24}
566
+ color={theme.colors.arrowColor}
567
+ onPress={() => setPasswordSee(!passwordSee)}
568
+ />
569
+ )
570
+ }
571
+ selectionColor={theme.colors.primary}
572
+ color={theme.colors.textGray}
573
+ value={value}
574
+ forwardRef={inputRef}
575
+ onChange={(val: any) => onChange(val)}
576
+ returnKeyType="done"
577
+ blurOnSubmit
578
+ />
579
+ )}
580
+ name="password"
581
+ rules={{
582
+ required: t(
583
+ 'VALIDATION_ERROR_PASSWORD_REQUIRED',
584
+ 'The field Password is required',
585
+ ).replace('_attribute_', t('PASSWORD', 'Password')),
586
+ }}
587
+ defaultValue=""
588
+ />
589
+
590
+ {onNavigationRedirect && (
591
+ <Pressable
592
+ style={{ marginRight: 'auto', marginBottom: 35 }}
593
+ onPress={() => onNavigationRedirect('Forgot')}>
594
+ <OText style={styles.textForgot}>
595
+ {t('FORGOT_YOUR_PASSWORD', 'Forgot your password?')}
596
+ </OText>
597
+ </Pressable>
598
+ )}
599
+
600
+ <OButton
601
+ onClick={handleLogin}
602
+ text={t('LOGIN', 'Login')}
603
+ bgColor={theme.colors.primary}
604
+ borderColor={theme.colors.primary}
605
+ textStyle={styles.btnText}
606
+ imgRightSrc={null}
607
+ isLoading={formState?.loading || loading}
608
+ style={styles.btn}
609
+ />
610
+ </FormInput>
611
+ )}
612
+
613
+ {useLoginByCellphone &&
614
+ loginTab === 'cellphone' &&
615
+ configs &&
616
+ Object.keys(configs).length > 0 &&
617
+ (configs?.twilio_service_enabled?.value === 'true' ||
618
+ configs?.twilio_service_enabled?.value === '1') && (
619
+ <>
620
+ <OrSeparator>
621
+ <LineSeparator />
622
+ <OText size={18} mRight={20} mLeft={20}>
623
+ {t('OR', 'Or')}
624
+ </OText>
625
+ <LineSeparator />
626
+ </OrSeparator>
627
+
628
+ <ButtonsWrapper mBottom={20}>
629
+ <OButton
630
+ onClick={handleVerifyCodeClick}
631
+ text={t('GET_VERIFY_CODE', 'Get Verify Code')}
632
+ borderColor={theme.colors.primary}
633
+ style={styles.btn}
634
+ imgRightSrc={null}
635
+ isLoading={isLoadingVerifyModal}
636
+ indicatorColor={theme.colors.primary}
637
+ />
638
+ </ButtonsWrapper>
639
+ </>
640
+ )}
641
+
642
+ <OModal open={isModalVisible} onClose={() => setIsModalVisible(false)}>
643
+ <VerifyPhone
644
+ phone={phoneInputData.phone}
645
+ verifyPhoneState={verifyPhoneState}
646
+ checkPhoneCodeState={checkPhoneCodeState}
647
+ handleCheckPhoneCode={handleCheckPhoneCode}
648
+ setCheckPhoneCodeState={setCheckPhoneCodeState}
649
+ handleVerifyCodeClick={handleVerifyCodeClick}
650
+ />
651
+ </OModal>
652
+ </View>
653
+ );
654
+ };
655
+
656
+ export const LoginForm = (props: any) => {
657
+ const loginProps = {
658
+ ...props,
659
+ UIComponent: LoginFormUI,
660
+ };
661
+
662
+ return <LoginFormController {...loginProps} />;
663
+ };
@@ -0,0 +1,48 @@
1
+ import styled, { css } from 'styled-components/native';
2
+
3
+ export const LoginWith = styled.View`
4
+ display: flex;
5
+ width: 100%;
6
+ margin-bottom: 30px;
7
+ `;
8
+
9
+ export const TabsContainer = styled.View`
10
+ min-width: ${({ width }: { width: number }) => `${width}px`};
11
+ width: auto;
12
+ display: flex;
13
+ flex-direction: row;
14
+ `;
15
+
16
+ export const FormInput = styled.View`
17
+ display: flex;
18
+ flex-direction: column;
19
+ width: 100%;
20
+ `;
21
+
22
+ export const ButtonsWrapper = styled.View`
23
+ margin: 10px 0px 0px;
24
+ width: 90%;
25
+ display: flex;
26
+ flex-direction: column;
27
+
28
+ ${(props: any) =>
29
+ props.mBottom &&
30
+ css`
31
+ margin-bottom: ${props.mBottom}px;
32
+ `}
33
+ `;
34
+
35
+ export const OrSeparator = styled.View`
36
+ width: 90%;
37
+ display: flex;
38
+ flex-direction: row;
39
+ justify-content: space-between;
40
+ align-items: center;
41
+ margin-bottom: 20px;
42
+ `;
43
+
44
+ export const LineSeparator = styled.View`
45
+ width: 40%;
46
+ height: 1px;
47
+ background-color: ${(props: any) => props.theme.colors.disabled};
48
+ `;