ordering-ui-react-native 0.15.2 → 0.15.4-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 (131) hide show
  1. package/package.json +7 -3
  2. package/src/DeliveryApp.tsx +43 -1
  3. package/src/components/BusinessTypeFilter/index.tsx +12 -2
  4. package/src/components/BusinessTypeFilter/styles.tsx +1 -1
  5. package/src/components/BusinessesListing/index.tsx +1 -1
  6. package/src/components/Checkout/index.tsx +0 -1
  7. package/src/components/Home/index.tsx +3 -5
  8. package/src/components/LanguageSelector/index.tsx +66 -97
  9. package/src/components/LanguageSelector/styles.tsx +4 -17
  10. package/src/components/Messages/index.tsx +38 -30
  11. package/src/components/MomentOption/index.tsx +3 -1
  12. package/src/components/OrderDetails/index.tsx +25 -4
  13. package/src/components/PaymentOptions/index.tsx +9 -16
  14. package/src/components/PaymentOptionsWebView/index.tsx +123 -124
  15. package/src/components/ProductForm/index.tsx +1 -1
  16. package/src/components/ProductForm/styles.tsx +1 -0
  17. package/src/components/StripeElementsForm/index.tsx +27 -48
  18. package/src/components/UserProfileForm/index.tsx +35 -1
  19. package/src/components/VerifyPhone/styles.tsx +1 -2
  20. package/src/config.json +0 -2
  21. package/src/pages/Checkout.tsx +1 -1
  22. package/src/types/index.tsx +2 -9
  23. package/src/utils/index.tsx +2 -1
  24. package/themes/business/index.tsx +2 -0
  25. package/themes/business/src/components/Chat/index.tsx +32 -31
  26. package/themes/business/src/components/Home/index.tsx +128 -55
  27. package/themes/business/src/components/Home/styles.tsx +8 -1
  28. package/themes/business/src/components/NewOrderNotification/index.tsx +59 -98
  29. package/themes/business/src/components/OrderDetails/Business.tsx +1 -0
  30. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +27 -0
  31. package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +85 -17
  32. package/themes/business/src/components/OrdersListManager/index.tsx +874 -0
  33. package/themes/business/src/components/OrdersListManager/styles.tsx +123 -0
  34. package/themes/business/src/components/OrdersListManager/utils.tsx +216 -0
  35. package/themes/business/src/components/OrdersOption/index.tsx +70 -116
  36. package/themes/business/src/components/OrdersOption/styles.tsx +2 -5
  37. package/themes/business/src/components/PreviousOrders/index.tsx +82 -23
  38. package/themes/doordash/src/components/BusinessesListing/index.tsx +1 -1
  39. package/themes/doordash/src/components/LoginForm/index.tsx +1 -2
  40. package/themes/instacart/src/components/BusinessesListing/index.tsx +1 -1
  41. package/themes/kiosk/src/components/BusinessController/index.tsx +27 -6
  42. package/themes/kiosk/src/components/BusinessController/styles.tsx +1 -1
  43. package/themes/kiosk/src/components/BusinessProductsListing/index.tsx +51 -24
  44. package/themes/kiosk/src/components/Cart/index.tsx +1 -1
  45. package/themes/kiosk/src/components/CartBottomSheet/index.tsx +1 -1
  46. package/themes/kiosk/src/components/CartBottomSheet/styles.tsx +1 -1
  47. package/themes/kiosk/src/components/CartContent/index.tsx +13 -3
  48. package/themes/kiosk/src/components/CartItem/index.tsx +20 -8
  49. package/themes/kiosk/src/components/CategoriesMenu/index.tsx +7 -5
  50. package/themes/kiosk/src/components/CustomerName/index.tsx +89 -88
  51. package/themes/kiosk/src/components/Intro/index.tsx +13 -13
  52. package/themes/kiosk/src/components/LanguageSelector/index.tsx +12 -8
  53. package/themes/kiosk/src/components/NavBar/index.tsx +14 -14
  54. package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
  55. package/themes/kiosk/src/components/OrderDetails/index.tsx +2 -2
  56. package/themes/kiosk/src/components/OrderSummary/index.tsx +1 -1
  57. package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +10 -12
  58. package/themes/kiosk/src/components/ProductForm/index.tsx +172 -124
  59. package/themes/kiosk/src/components/ProductForm/styles.tsx +1 -1
  60. package/themes/kiosk/src/components/ProductOption/index.tsx +1 -0
  61. package/themes/kiosk/src/components/ProductOption/styles.tsx +1 -0
  62. package/themes/kiosk/src/components/UpsellingProducts/index.tsx +48 -34
  63. package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
  64. package/themes/kiosk/src/components/shared/OCard.tsx +112 -78
  65. package/themes/original/index.tsx +179 -0
  66. package/themes/original/src/components/AddressForm/index.tsx +15 -10
  67. package/themes/original/src/components/AddressList/index.tsx +28 -2
  68. package/themes/original/src/components/AnalyticsSegment/index.tsx +127 -0
  69. package/themes/original/src/components/BusinessBasicInformation/index.tsx +100 -45
  70. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +28 -1
  71. package/themes/original/src/components/BusinessController/index.tsx +32 -21
  72. package/themes/original/src/components/BusinessListingSearch/index.tsx +7 -3
  73. package/themes/original/src/components/BusinessMenuList/index.tsx +11 -4
  74. package/themes/original/src/components/BusinessPreorder/index.tsx +141 -121
  75. package/themes/original/src/components/BusinessProductsCategories/index.tsx +7 -5
  76. package/themes/original/src/components/BusinessProductsList/index.tsx +6 -3
  77. package/themes/original/src/components/BusinessProductsListing/index.tsx +23 -30
  78. package/themes/original/src/components/BusinessReviews/index.tsx +8 -28
  79. package/themes/original/src/components/BusinessesListing/index.tsx +40 -53
  80. package/themes/original/src/components/Cart/index.tsx +40 -9
  81. package/themes/original/src/components/CartContent/index.tsx +2 -2
  82. package/themes/original/src/components/Checkout/index.tsx +58 -33
  83. package/themes/original/src/components/Checkout/styles.tsx +7 -0
  84. package/themes/original/src/components/CouponControl/index.tsx +1 -0
  85. package/themes/original/src/components/DriverTips/index.tsx +1 -1
  86. package/themes/original/src/components/ForgotPasswordForm/index.tsx +8 -12
  87. package/themes/original/src/components/HighestRatedBusinesses/index.tsx +105 -90
  88. package/themes/original/src/components/Home/index.tsx +1 -1
  89. package/themes/original/src/components/LoginForm/index.tsx +156 -70
  90. package/themes/original/src/components/LoginForm/styles.tsx +6 -1
  91. package/themes/original/src/components/Messages/index.tsx +52 -45
  92. package/themes/original/src/components/Messages/styles.tsx +1 -3
  93. package/themes/original/src/components/MomentOption/index.tsx +10 -1
  94. package/themes/original/src/components/MomentOption/styles.tsx +1 -1
  95. package/themes/original/src/components/OrderDetails/index.tsx +102 -125
  96. package/themes/original/src/components/OrderDetails/styles.tsx +3 -1
  97. package/themes/original/src/components/OrderProgress/index.tsx +6 -7
  98. package/themes/original/src/components/OrderProgress/styles.tsx +1 -0
  99. package/themes/original/src/components/OrderSummary/index.tsx +34 -1
  100. package/themes/original/src/components/OrdersOption/index.tsx +15 -46
  101. package/themes/original/src/components/OrdersOption/styles.tsx +0 -6
  102. package/themes/original/src/components/PaymentOptionWallet/index.tsx +6 -2
  103. package/themes/original/src/components/PaymentOptions/index.tsx +24 -25
  104. package/themes/original/src/components/PhoneInputNumber/index.tsx +15 -8
  105. package/themes/original/src/components/PlaceSpot/index.tsx +114 -0
  106. package/themes/original/src/components/PlaceSpot/styles.tsx +11 -0
  107. package/themes/original/src/components/PreviousOrders/index.tsx +19 -13
  108. package/themes/original/src/components/ProductForm/index.tsx +157 -108
  109. package/themes/original/src/components/ProductForm/styles.tsx +5 -3
  110. package/themes/original/src/components/ProductOptionSubOption/index.tsx +6 -1
  111. package/themes/original/src/components/ReviewOrder/index.tsx +10 -9
  112. package/themes/original/src/components/ReviewProducts/index.tsx +1 -1
  113. package/themes/original/src/components/SignupForm/index.tsx +173 -154
  114. package/themes/original/src/components/StripeElementsForm/index.tsx +55 -72
  115. package/themes/original/src/components/TaxInformation/index.tsx +17 -7
  116. package/themes/original/src/components/UpsellingProducts/index.tsx +6 -6
  117. package/themes/original/src/components/UserDetails/index.tsx +4 -95
  118. package/themes/original/src/components/UserFormDetails/index.tsx +2 -14
  119. package/themes/original/src/components/UserProfile/index.tsx +16 -16
  120. package/themes/original/src/components/UserProfileForm/index.tsx +8 -6
  121. package/themes/original/src/components/VerifyPhone/index.tsx +10 -7
  122. package/themes/original/src/components/VerifyPhone/styles.tsx +2 -1
  123. package/themes/original/src/components/shared/HeaderTitle.tsx +21 -0
  124. package/themes/original/src/components/shared/index.tsx +2 -0
  125. package/themes/original/src/config/constants.tsx +6 -6
  126. package/themes/original/src/types/index.tsx +64 -22
  127. package/themes/single-business/src/components/AddressList/index.tsx +1 -1
  128. package/themes/single-business/src/components/OrderTypeSelector/index.tsx +5 -5
  129. package/themes/single-business/src/components/UserProfile/index.tsx +1 -1
  130. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
  131. package/src/components/StripeMethodForm/index.tsx +0 -168
@@ -1,8 +1,8 @@
1
- import React from 'react';
1
+ import React, { useEffect } from 'react';
2
2
  import {
3
- BusinessList as BusinessesListingController,
3
+ BusinessList as BusinessesListingController,
4
4
  useLanguage,
5
- useOrder
5
+ useOrder
6
6
  } from 'ordering-components/native';
7
7
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
8
8
  import { View, ScrollView, Platform, Dimensions } from 'react-native';
@@ -18,116 +18,131 @@ const HighestRatedBusinessesUI = (props: HighestRatedBusinessesParams) => {
18
18
  const {
19
19
  businessesList,
20
20
  onBusinessClick,
21
- navigation
21
+ navigation,
22
+ isLoading,
23
+ getBusinesses
22
24
  } = props;
23
25
 
24
26
  const [, t] = useLanguage()
25
- const [orderState] = useOrder();
27
+ const [orderState] = useOrder()
26
28
 
27
29
  const windowWidth = Dimensions.get('window').width;
28
30
 
31
+ useEffect(() => {
32
+ if (businessesList?.loading || !isLoading) return
33
+ getBusinesses(true)
34
+ }, [isLoading])
35
+
29
36
  return (
30
37
  <>
31
- <ListWrapper>
32
- <OText size={16} mBottom={5} weight={Platform.OS === 'ios' ? '600' : 'bold'}>{t('HIGHEST_RATED', 'Highest rated')}</OText>
33
- <OText size={12}>{t('TOP_RATINGS_AND_GREAT_SERVICE', 'Top ratings and great service')}</OText>
34
- <ScrollView
35
- showsHorizontalScrollIndicator={false}
36
- nestedScrollEnabled
37
- horizontal
38
- style={{ height: 300 }}
39
- >
40
- {businessesList.loading ? (
41
- <>
42
- {[
43
- ...Array(10).keys()
44
- ].map((item, i) => (
45
- <Placeholder
46
- Animation={Fade}
47
- key={i}
48
- style={{
49
- marginTop: 20,
50
- width: windowWidth - 100,
51
- paddingHorizontal: 5,
52
- height: '100%'
53
- }}>
54
- <View style={{ width: '100%' }}>
55
- <PlaceholderLine
56
- height={150}
57
- style={{ marginBottom: 20, borderRadius: 8 }}
58
- />
59
- <View style={{ paddingHorizontal: 10 }}>
60
- <View
61
- style={{
62
- flexDirection: 'row',
63
- justifyContent: 'space-between',
64
- }}>
65
- <PlaceholderLine
66
- height={15}
67
- width={40}
68
- style={{ marginBottom: 15 }}
69
- />
70
- <PlaceholderLine
71
- height={15}
72
- width={20}
73
- style={{ marginBottom: 15 }}
74
- />
75
- </View>
38
+
39
+ {businessesList.loading ? (
40
+ <>
41
+ <ScrollView
42
+ showsHorizontalScrollIndicator={false}
43
+ nestedScrollEnabled
44
+ horizontal
45
+ style={{ height: 300, paddingHorizontal: 40 }}
46
+ >
47
+ {[
48
+ ...Array(10).keys()
49
+ ].map((item, i) => (
50
+ <Placeholder
51
+ Animation={Fade}
52
+ key={i}
53
+ style={{
54
+ marginTop: 20,
55
+ width: windowWidth - 100,
56
+ paddingHorizontal: 5,
57
+ height: '100%'
58
+ }}>
59
+ <View style={{ width: '100%' }}>
60
+ <PlaceholderLine
61
+ height={150}
62
+ style={{ marginBottom: 20, borderRadius: 8 }}
63
+ />
64
+ <View style={{ paddingHorizontal: 10 }}>
65
+ <View
66
+ style={{
67
+ flexDirection: 'row',
68
+ justifyContent: 'space-between',
69
+ }}>
76
70
  <PlaceholderLine
77
71
  height={15}
78
- width={30}
79
- style={{ marginBottom: 10 }}
72
+ width={40}
73
+ style={{ marginBottom: 15 }}
80
74
  />
81
75
  <PlaceholderLine
82
76
  height={15}
83
- width={80}
84
- style={{ marginBottom: 10 }}
77
+ width={20}
78
+ style={{ marginBottom: 15 }}
85
79
  />
86
80
  </View>
81
+ <PlaceholderLine
82
+ height={15}
83
+ width={30}
84
+ style={{ marginBottom: 10 }}
85
+ />
86
+ <PlaceholderLine
87
+ height={15}
88
+ width={80}
89
+ style={{ marginBottom: 10 }}
90
+ />
87
91
  </View>
88
- </Placeholder>
89
- ))}
90
- </>
91
- ) : (
92
- <>
93
- {businessesList.businesses.length > 0 ? (
94
- businessesList.businesses?.map(
95
- (business: any) => (
96
- <View
97
- key={business.id}
98
- style={{
99
- width: windowWidth - 100,
100
- paddingHorizontal: 5,
101
- height: '100%'
102
- }}
103
- >
104
- <BusinessController
105
- business={business}
106
- isBusinessOpen={business?.open}
107
- handleCustomClick={onBusinessClick}
108
- orderType={orderState?.options?.type}
109
- navigation={navigation}
110
- />
111
- </View>
92
+ </View>
93
+ </Placeholder>
94
+ ))}
95
+ </ScrollView>
96
+ </>
97
+ ) : (
98
+ <>
99
+ {businessesList.businesses.length > 0 && (
100
+ <ListWrapper>
101
+ <OText size={16} mBottom={5} weight={Platform.OS === 'ios' ? '600' : 'bold'}>{t('HIGHEST_RATED', 'Highest rated')}</OText>
102
+ <OText size={12}>{t('TOP_RATINGS_AND_GREAT_SERVICE', 'Top ratings and great service')}</OText>
103
+ <ScrollView
104
+ showsHorizontalScrollIndicator={false}
105
+ nestedScrollEnabled
106
+ horizontal
107
+ style={{ height: 300 }}
108
+ >
109
+ {
110
+ businessesList.businesses?.map(
111
+ (business: any) => (
112
+ <View
113
+ key={business.id}
114
+ style={{
115
+ width: windowWidth - 100,
116
+ paddingHorizontal: 5,
117
+ height: '100%'
118
+ }}
119
+ >
120
+ <BusinessController
121
+ business={business}
122
+ isBusinessOpen={business?.open}
123
+ handleCustomClick={onBusinessClick}
124
+ orderType={orderState?.options?.type}
125
+ navigation={navigation}
126
+ />
127
+ </View>
128
+ )
112
129
  )
113
- )
114
- ) : (
115
- <NotFoundSource />
116
- )}
117
- </>
130
+ }
131
+ </ScrollView>
132
+ </ListWrapper>
118
133
  )}
119
- </ScrollView>
120
- </ListWrapper>
134
+ </>
135
+ )}
121
136
  </>
122
137
  )
123
138
  }
124
139
 
125
140
  export const HighestRatedBusinesses = (props: any) => {
126
- const highestRatedBusinessesProps = {
127
- ...props,
128
- UIComponent: HighestRatedBusinessesUI,
141
+ const highestRatedBusinessesProps = {
142
+ ...props,
143
+ UIComponent: HighestRatedBusinessesUI,
129
144
  initialOrderByValue: 'rating'
130
- };
145
+ };
131
146
 
132
- return <BusinessesListingController {...highestRatedBusinessesProps} />;
147
+ return <BusinessesListingController {...highestRatedBusinessesProps} />;
133
148
  };
@@ -36,7 +36,7 @@ export const Home = (props: any) => {
36
36
  {t('WELCOME', 'Welcome!')}
37
37
  </OText>
38
38
  <OText color={theme.colors.white} size={14} style={{ marginBottom: 46 }}>
39
- {t('LETS_START_ORDER', "Let's start to order now")}
39
+ {t('SUBTITLE_HOME', "Let's start to order now")}
40
40
  </OText>
41
41
  <OButton
42
42
  text={t('LOGIN_NOW', 'Login now')}
@@ -4,6 +4,7 @@ import Spinner from 'react-native-loading-spinner-overlay';
4
4
  import { useForm, Controller } from 'react-hook-form';
5
5
  import { PhoneInputNumber } from '../PhoneInputNumber';
6
6
  import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
7
+ import Recaptcha from 'react-native-recaptcha-that-works'
7
8
 
8
9
  import {
9
10
  LoginForm as LoginFormController,
@@ -18,7 +19,6 @@ import { FacebookLogin } from '../FacebookLogin';
18
19
  import { VerifyPhone } from '../../../../../src/components/VerifyPhone';
19
20
  import { OModal } from '../../../../../src/components/shared';
20
21
 
21
-
22
22
  import {
23
23
  Container,
24
24
  ButtonsWrapper,
@@ -32,6 +32,7 @@ import {
32
32
  LineSeparator,
33
33
  SkeletonWrapper,
34
34
  TabBtn,
35
+ RecaptchaButton
35
36
  } from './styles';
36
37
 
37
38
  import NavBar from '../NavBar';
@@ -60,14 +61,16 @@ const LoginFormUI = (props: LoginParams) => {
60
61
  handleSendVerifyCode,
61
62
  handleCheckPhoneCode,
62
63
  onNavigationRedirect,
63
- notificationState
64
+ notificationState,
65
+ handleReCaptcha,
66
+ enableReCaptcha
64
67
  } = props;
65
68
 
66
69
  const [, { showToast }] = useToast();
67
70
  const [, t] = useLanguage();
68
71
  const [{ configs }] = useConfig();
69
72
  const [, { login }] = useSession();
70
- const { control, handleSubmit, errors } = useForm();
73
+ const { control, handleSubmit, errors, reset, register, setValue } = useForm();
71
74
  const [passwordSee, setPasswordSee] = useState(false);
72
75
  const [isLoadingVerifyModal, setIsLoadingVerifyModal] = useState(false);
73
76
  const [isModalVisible, setIsModalVisible] = useState(false);
@@ -79,6 +82,8 @@ const LoginFormUI = (props: LoginParams) => {
79
82
  cellphone: null,
80
83
  },
81
84
  });
85
+ const [recaptchaConfig, setRecaptchaConfig] = useState<any>({})
86
+ const [recaptchaVerified, setRecaptchaVerified] = useState(false)
82
87
 
83
88
  const theme = useTheme();
84
89
 
@@ -91,7 +96,7 @@ const LoginFormUI = (props: LoginParams) => {
91
96
  inputStyle: {
92
97
  marginBottom: 28,
93
98
  borderWidth: 1,
94
- borderColor: theme.colors.border,
99
+ // borderColor: theme.colors.border,
95
100
  borderRadius: 7.6,
96
101
  },
97
102
  line: {
@@ -100,10 +105,15 @@ const LoginFormUI = (props: LoginParams) => {
100
105
  flexGrow: 1,
101
106
  marginBottom: 7,
102
107
  },
108
+ recaptchaIcon: {
109
+ width: 100,
110
+ height: 100,
111
+ }
103
112
  });
104
113
 
105
114
  const emailRef = useRef<any>({});
106
115
  const passwordRef = useRef<any>({});
116
+ const recaptchaRef = useRef<any>({});
107
117
 
108
118
  const handleChangeTab = (val: string) => {
109
119
  props.handleChangeTab(val);
@@ -156,6 +166,33 @@ const LoginFormUI = (props: LoginParams) => {
156
166
  onChange(value.toLowerCase().replace(/[&,()%";:ç?<>{}\\[\]\s]/g, ''));
157
167
  };
158
168
 
169
+ const handleOpenRecaptcha = () => {
170
+ setRecaptchaVerified(false)
171
+ if (!recaptchaConfig?.siteKey) {
172
+ showToast(ToastType.Error, t('NO_RECAPTCHA_SITE_KEY', 'The config doesn\'t have recaptcha site key'));
173
+ return
174
+ }
175
+ if (!recaptchaConfig?.baseUrl) {
176
+ showToast(ToastType.Error, t('NO_RECAPTCHA_BASE_URL', 'The config doesn\'t have recaptcha base url'));
177
+ return
178
+ }
179
+ recaptchaRef.current.open()
180
+ }
181
+
182
+ const onRecaptchaVerify = (token: any) => {
183
+ setRecaptchaVerified(true)
184
+ handleReCaptcha(token)
185
+ }
186
+
187
+ useEffect(() => {
188
+ if (configs && Object.keys(configs).length > 0 && enableReCaptcha) {
189
+ setRecaptchaConfig({
190
+ siteKey: configs?.security_recaptcha_site_key?.value || null,
191
+ baseUrl: configs?.security_recaptcha_base_url?.value || null
192
+ })
193
+ }
194
+ }, [configs, enableReCaptcha])
195
+
159
196
  useEffect(() => {
160
197
  if (!formState.loading && formState.result?.error) {
161
198
  formState.result?.result &&
@@ -189,33 +226,21 @@ const LoginFormUI = (props: LoginParams) => {
189
226
  }, [verifyPhoneState]);
190
227
 
191
228
  useEffect(() => {
192
- if (Object.keys(errors).length > 0) {
193
- // Convert all errors in one string to show in toast provider
194
- const list = Object.values(errors);
195
- let stringError = '';
196
- if (phoneInputData.error) {
197
- list.unshift({ message: phoneInputData.error });
198
- }
199
- if (
200
- loginTab === 'cellphone' &&
201
- !phoneInputData.error &&
202
- !phoneInputData.phone.country_phone_code &&
203
- !phoneInputData.phone.cellphone
204
- ) {
205
- list.unshift({
206
- message: t(
207
- 'VALIDATION_ERROR_MOBILE_PHONE_REQUIRED',
208
- 'The field Mobile phone is required.',
209
- ),
210
- });
211
- }
212
- list.map((item: any, i: number) => {
213
- stringError +=
214
- i + 1 === list.length ? `- ${item.message}` : `- ${item.message}\n`;
215
- });
216
- showToast(ToastType.Error, stringError);
217
- }
218
- }, [errors]);
229
+ if (phoneInputData?.phone?.cellphone) setValue('cellphone', phoneInputData?.phone?.cellphone, '')
230
+ else setValue('cellphone', '')
231
+ }, [phoneInputData?.phone?.cellphone])
232
+
233
+ useEffect(() => {
234
+ register('cellphone', {
235
+ required: loginTab === 'cellphone'
236
+ ? t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Mobile phone is required').replace('_attribute_', t('CELLPHONE', 'Cellphone'))
237
+ : null
238
+ })
239
+ }, [register])
240
+
241
+ useEffect(() => {
242
+ reset()
243
+ }, [loginTab])
219
244
 
220
245
  return (
221
246
  <Container>
@@ -284,43 +309,58 @@ const LoginFormUI = (props: LoginParams) => {
284
309
  {(useLoginByCellphone || useLoginByEmail) && (
285
310
  <FormInput>
286
311
  {useLoginByEmail && loginTab === 'email' && (
287
- <Controller
288
- control={control}
289
- render={({ onChange, value }: any) => (
290
- <OInput
291
- placeholder={t('EMAIL', 'Email')}
292
- style={loginStyle.inputStyle}
293
- icon={theme.images.general.email}
294
- onChange={(e: any) => {
295
- handleChangeInputEmail(e, onChange);
296
- }}
297
- value={value}
298
- autoCapitalize="none"
299
- autoCorrect={false}
300
- type="email-address"
301
- autoCompleteType="email"
302
- returnKeyType="next"
303
- onSubmitEditing={() => passwordRef.current?.focus()}
304
- blurOnSubmit={false}
305
- forwardRef={emailRef}
306
- />
312
+ <>
313
+ {errors?.email && (
314
+ <OText
315
+ size={14}
316
+ color={theme.colors.danger5}
317
+ weight={'normal'}>
318
+ {errors?.email?.message}{errors?.email?.type === 'required' && '*'}
319
+ </OText>
307
320
  )}
308
- name="email"
309
- rules={{
310
- required: t(
311
- 'VALIDATION_ERROR_EMAIL_REQUIRED',
312
- 'The field Email is required',
313
- ).replace('_attribute_', t('EMAIL', 'Email')),
314
- pattern: {
315
- value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
316
- message: t(
317
- 'INVALID_ERROR_EMAIL',
318
- 'Invalid email address',
319
- ).replace('_attribute_', t('EMAIL', 'Email')),
320
- },
321
- }}
322
- defaultValue=""
323
- />
321
+ <Controller
322
+ control={control}
323
+ render={({ onChange, value }: any) => (
324
+ <OInput
325
+ placeholder={t('EMAIL', 'Email')}
326
+ style={loginStyle.inputStyle}
327
+ icon={theme.images.general.email}
328
+ onChange={(e: any) => {
329
+ handleChangeInputEmail(e, onChange);
330
+ }}
331
+ value={value}
332
+ autoCapitalize="none"
333
+ autoCorrect={false}
334
+ type="email-address"
335
+ autoCompleteType="email"
336
+ returnKeyType="next"
337
+ onSubmitEditing={() => passwordRef.current?.focus()}
338
+ blurOnSubmit={false}
339
+ forwardRef={emailRef}
340
+ borderColor={errors?.email ? theme.colors.danger5 : theme.colors.border}
341
+ />
342
+ )}
343
+ name="email"
344
+ rules={{
345
+ required: {
346
+ value: true,
347
+ message: t(
348
+ 'VALIDATION_ERROR_EMAIL_REQUIRED',
349
+ 'The field Email is required',
350
+ ).replace('_attribute_', t('EMAIL', 'Email'))
351
+ },
352
+ pattern: {
353
+ value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
354
+ message: t(
355
+ 'INVALID_ERROR_EMAIL',
356
+ 'Invalid email address',
357
+ ).replace('_attribute_', t('EMAIL', 'Email')),
358
+ }
359
+ }}
360
+ defaultValue=""
361
+ />
362
+ </>
363
+
324
364
  )}
325
365
  {useLoginByCellphone && loginTab === 'cellphone' && (
326
366
  <View style={{ marginBottom: 28 }}>
@@ -331,10 +371,18 @@ const LoginFormUI = (props: LoginParams) => {
331
371
  returnKeyType: 'next',
332
372
  onSubmitEditing: () => passwordRef?.current?.focus?.(),
333
373
  }}
374
+ isStartValidation={errors?.cellphone}
334
375
  />
335
376
  </View>
336
377
  )}
337
-
378
+ {errors?.password && (
379
+ <OText
380
+ size={14}
381
+ color={theme.colors.danger5}
382
+ weight={'normal'}>
383
+ {errors?.password?.message}{errors?.password?.type === 'required' && '*'}
384
+ </OText>
385
+ )}
338
386
  <Controller
339
387
  control={control}
340
388
  render={({ onChange, value }: any) => (
@@ -366,14 +414,18 @@ const LoginFormUI = (props: LoginParams) => {
366
414
  returnKeyType="done"
367
415
  onSubmitEditing={handleSubmit(onSubmit)}
368
416
  blurOnSubmit
417
+ borderColor={errors?.password ? theme.colors.danger5 : theme.colors.border}
369
418
  />
370
419
  )}
371
420
  name="password"
372
421
  rules={{
373
- required: t(
422
+ required: {
423
+ value: true,
424
+ message: t(
374
425
  'VALIDATION_ERROR_PASSWORD_REQUIRED',
375
426
  'The field Password is required',
376
- ).replace('_attribute_', t('PASSWORD', 'Password')),
427
+ ).replace('_attribute_', t('PASSWORD', 'Password'))
428
+ }
377
429
  }}
378
430
  defaultValue=""
379
431
  />
@@ -384,6 +436,39 @@ const LoginFormUI = (props: LoginParams) => {
384
436
  </OText>
385
437
  </TouchableOpacity>
386
438
  )}
439
+
440
+ {enableReCaptcha && (
441
+ <>
442
+ <TouchableOpacity
443
+ onPress={handleOpenRecaptcha}
444
+ >
445
+ <RecaptchaButton>
446
+ {recaptchaVerified ? (
447
+ <MaterialCommunityIcons
448
+ name="checkbox-marked"
449
+ size={26}
450
+ color={theme.colors.primary}
451
+ />
452
+ ) : (
453
+ <MaterialCommunityIcons
454
+ name="checkbox-blank-outline"
455
+ size={26}
456
+ color={theme.colors.mediumGray}
457
+ />
458
+ )}
459
+ <OText size={14} mLeft={8}>{t('VERIFY_ReCAPTCHA', 'Verify reCAPTCHA')}</OText>
460
+ </RecaptchaButton>
461
+ </TouchableOpacity>
462
+ <Recaptcha
463
+ ref={recaptchaRef}
464
+ siteKey={recaptchaConfig?.siteKey}
465
+ baseUrl={recaptchaConfig?.baseUrl}
466
+ onVerify={onRecaptchaVerify}
467
+ onExpire={() => setRecaptchaVerified(false)}
468
+ />
469
+ </>
470
+ )}
471
+
387
472
  <OButton
388
473
  onClick={handleSubmit(onSubmit)}
389
474
  text={loginButtonText}
@@ -544,6 +629,7 @@ const LoginFormUI = (props: LoginParams) => {
544
629
  export const LoginForm = (props: any) => {
545
630
  const loginProps = {
546
631
  ...props,
632
+ isRecaptchaEnable: true,
547
633
  UIComponent: LoginFormUI,
548
634
  };
549
635
  return <LoginFormController {...loginProps} />;
@@ -36,7 +36,7 @@ export const LoginWith = styled.View`
36
36
  width: 100%;
37
37
  align-items: flex-start;
38
38
  border-bottom-width: 1px;
39
- border-bottom-color: ${(props: any) => props.theme.colors.border}
39
+ border-bottom-color: ${(props: any) => props.theme.colors.border};
40
40
  `;
41
41
 
42
42
  export const FormInput = styled.View`
@@ -80,3 +80,8 @@ export const LineSeparator = styled.View`
80
80
  export const SkeletonWrapper = styled.View`
81
81
  width: 90%;
82
82
  `
83
+ export const RecaptchaButton = styled.View`
84
+ flex-direction: row;
85
+ align-items: center;
86
+ margin-bottom: 10px;
87
+ `