ordering-ui-react-native 0.15.26 → 0.15.27-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 (165) hide show
  1. package/package.json +3 -2
  2. package/src/DeliveryApp.tsx +43 -1
  3. package/src/components/BusinessController/index.tsx +8 -2
  4. package/src/components/BusinessTypeFilter/index.tsx +4 -1
  5. package/src/components/BusinessesListing/index.tsx +1 -1
  6. package/src/components/Checkout/index.tsx +23 -3
  7. package/src/components/DriverTips/index.tsx +11 -6
  8. package/src/components/LanguageSelector/index.tsx +7 -2
  9. package/src/components/OrderDetails/index.tsx +2 -2
  10. package/src/components/PaymentOptions/index.tsx +9 -16
  11. package/src/components/PaymentOptionsWebView/index.tsx +123 -124
  12. package/src/components/SingleProductCard/index.tsx +16 -4
  13. package/src/components/StripeElementsForm/index.tsx +27 -48
  14. package/src/components/UpsellingProducts/index.tsx +1 -1
  15. package/src/components/UserProfileForm/index.tsx +63 -6
  16. package/src/components/UserProfileForm/styles.tsx +8 -0
  17. package/src/components/VerifyPhone/styles.tsx +1 -2
  18. package/src/components/shared/OModal.tsx +1 -1
  19. package/src/config.json +0 -2
  20. package/src/hooks/useCountdownTimer.tsx +26 -0
  21. package/src/navigators/HomeNavigator.tsx +6 -0
  22. package/src/pages/BusinessProductsList.tsx +1 -0
  23. package/src/pages/BusinessesListing.tsx +1 -1
  24. package/src/pages/Checkout.tsx +1 -1
  25. package/src/pages/Sessions.tsx +22 -0
  26. package/src/types/index.tsx +5 -11
  27. package/src/utils/index.tsx +68 -1
  28. package/themes/business/index.tsx +2 -0
  29. package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +103 -15
  30. package/themes/business/src/components/AcceptOrRejectOrder/styles.tsx +6 -0
  31. package/themes/business/src/components/Chat/index.tsx +38 -86
  32. package/themes/business/src/components/Home/index.tsx +128 -55
  33. package/themes/business/src/components/Home/styles.tsx +8 -1
  34. package/themes/business/src/components/LoginForm/index.tsx +89 -2
  35. package/themes/business/src/components/LoginForm/styles.tsx +6 -0
  36. package/themes/business/src/components/LogoutButton/index.tsx +1 -1
  37. package/themes/business/src/components/NewOrderNotification/index.tsx +79 -105
  38. package/themes/business/src/components/OrderDetails/Business.tsx +2 -1
  39. package/themes/business/src/components/OrderDetails/Delivery.tsx +32 -15
  40. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +151 -89
  41. package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +91 -17
  42. package/themes/business/src/components/OrderDetails/styles.tsx +7 -0
  43. package/themes/business/src/components/OrdersListManager/index.tsx +874 -0
  44. package/themes/business/src/components/OrdersListManager/styles.tsx +123 -0
  45. package/themes/business/src/components/OrdersListManager/utils.tsx +216 -0
  46. package/themes/business/src/components/OrdersOption/index.tsx +58 -51
  47. package/themes/business/src/components/PreviousOrders/index.tsx +75 -22
  48. package/themes/business/src/components/shared/OModal.tsx +1 -1
  49. package/themes/business/src/types/index.tsx +5 -1
  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/Cart/index.tsx +98 -24
  54. package/themes/kiosk/src/components/Cart/styles.tsx +6 -0
  55. package/themes/kiosk/src/components/CartBottomSheet/index.tsx +1 -1
  56. package/themes/kiosk/src/components/CartBottomSheet/styles.tsx +1 -1
  57. package/themes/kiosk/src/components/CartContent/index.tsx +13 -3
  58. package/themes/kiosk/src/components/CartItem/index.tsx +20 -8
  59. package/themes/kiosk/src/components/CustomerName/index.tsx +89 -88
  60. package/themes/kiosk/src/components/Intro/index.tsx +13 -13
  61. package/themes/kiosk/src/components/NavBar/index.tsx +14 -14
  62. package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
  63. package/themes/kiosk/src/components/OrderDetails/index.tsx +136 -41
  64. package/themes/kiosk/src/components/OrderDetails/styles.tsx +5 -0
  65. package/themes/kiosk/src/components/OrderSummary/index.tsx +1 -1
  66. package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +10 -12
  67. package/themes/kiosk/src/components/ProductForm/index.tsx +174 -125
  68. package/themes/kiosk/src/components/ProductForm/styles.tsx +1 -1
  69. package/themes/kiosk/src/components/ProductOption/index.tsx +1 -0
  70. package/themes/kiosk/src/components/ProductOption/styles.tsx +1 -0
  71. package/themes/kiosk/src/components/UpsellingProducts/index.tsx +48 -34
  72. package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
  73. package/themes/kiosk/src/types/index.d.ts +2 -0
  74. package/themes/original/index.tsx +178 -1
  75. package/themes/original/src/components/AddressForm/index.tsx +15 -10
  76. package/themes/original/src/components/AddressList/index.tsx +56 -18
  77. package/themes/original/src/components/AppleLogin/index.tsx +117 -78
  78. package/themes/original/src/components/BusinessBasicInformation/index.tsx +96 -45
  79. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +28 -1
  80. package/themes/original/src/components/BusinessController/index.tsx +52 -22
  81. package/themes/original/src/components/BusinessController/styles.tsx +22 -0
  82. package/themes/original/src/components/BusinessFeaturedController/index.tsx +20 -1
  83. package/themes/original/src/components/BusinessFeaturedController/styles.tsx +23 -0
  84. package/themes/original/src/components/BusinessListingSearch/index.tsx +121 -7
  85. package/themes/original/src/components/BusinessListingSearch/styles.tsx +14 -1
  86. package/themes/original/src/components/BusinessMenuList/index.tsx +11 -4
  87. package/themes/original/src/components/BusinessPreorder/index.tsx +142 -122
  88. package/themes/original/src/components/BusinessProductsCategories/index.tsx +9 -7
  89. package/themes/original/src/components/BusinessProductsList/index.tsx +127 -20
  90. package/themes/original/src/components/BusinessProductsList/styles.tsx +29 -2
  91. package/themes/original/src/components/BusinessProductsListing/index.tsx +118 -37
  92. package/themes/original/src/components/BusinessProductsListing/styles.tsx +22 -0
  93. package/themes/original/src/components/BusinessReviews/index.tsx +4 -25
  94. package/themes/original/src/components/BusinessTypeFilter/index.tsx +1 -2
  95. package/themes/original/src/components/BusinessesListing/index.tsx +53 -60
  96. package/themes/original/src/components/Cart/index.tsx +21 -17
  97. package/themes/original/src/components/CartContent/index.tsx +2 -2
  98. package/themes/original/src/components/Checkout/index.tsx +58 -45
  99. package/themes/original/src/components/DriverTips/index.tsx +17 -12
  100. package/themes/original/src/components/ForgotPasswordForm/index.tsx +84 -4
  101. package/themes/original/src/components/GoogleMap/index.tsx +1 -0
  102. package/themes/original/src/components/Help/index.tsx +21 -4
  103. package/themes/original/src/components/HighestRatedBusinesses/index.tsx +97 -89
  104. package/themes/original/src/components/Home/index.tsx +1 -1
  105. package/themes/original/src/components/LastOrders/index.tsx +12 -1
  106. package/themes/original/src/components/LoginForm/Otp/index.tsx +90 -0
  107. package/themes/original/src/components/LoginForm/Otp/styles.tsx +7 -0
  108. package/themes/original/src/components/LoginForm/index.tsx +389 -156
  109. package/themes/original/src/components/LoginForm/styles.tsx +7 -4
  110. package/themes/original/src/components/LogoutButton/index.tsx +7 -1
  111. package/themes/original/src/components/MessageListing/index.tsx +10 -1
  112. package/themes/original/src/components/Messages/index.tsx +34 -25
  113. package/themes/original/src/components/Messages/styles.tsx +1 -3
  114. package/themes/original/src/components/MomentOption/index.tsx +10 -1
  115. package/themes/original/src/components/MomentOption/styles.tsx +1 -1
  116. package/themes/original/src/components/OrderDetails/index.tsx +56 -33
  117. package/themes/original/src/components/OrderDetails/styles.tsx +1 -2
  118. package/themes/original/src/components/OrderProgress/index.tsx +4 -4
  119. package/themes/original/src/components/OrderProgress/styles.tsx +1 -0
  120. package/themes/original/src/components/OrderSummary/index.tsx +3 -3
  121. package/themes/original/src/components/OrderTypeSelector/index.tsx +4 -2
  122. package/themes/original/src/components/OrdersOption/index.tsx +55 -58
  123. package/themes/original/src/components/OrdersOption/styles.tsx +0 -6
  124. package/themes/original/src/components/PaymentOptionCash/index.tsx +2 -2
  125. package/themes/original/src/components/PaymentOptionWallet/index.tsx +22 -24
  126. package/themes/original/src/components/PaymentOptionWallet/styles.tsx +1 -1
  127. package/themes/original/src/components/PaymentOptions/index.tsx +9 -19
  128. package/themes/original/src/components/PhoneInputNumber/index.tsx +1 -1
  129. package/themes/original/src/components/PreviousOrders/index.tsx +16 -14
  130. package/themes/original/src/components/ProductForm/index.tsx +76 -61
  131. package/themes/original/src/components/ProductForm/styles.tsx +2 -2
  132. package/themes/original/src/components/ProductItemAccordion/index.tsx +2 -2
  133. package/themes/original/src/components/ProductOptionSubOption/index.tsx +18 -12
  134. package/themes/original/src/components/Promotions/index.tsx +250 -0
  135. package/themes/original/src/components/Promotions/styles.tsx +60 -0
  136. package/themes/original/src/components/ReviewOrder/index.tsx +10 -9
  137. package/themes/original/src/components/ReviewProducts/index.tsx +1 -1
  138. package/themes/original/src/components/SearchBar/index.tsx +4 -1
  139. package/themes/original/src/components/Sessions/index.tsx +160 -0
  140. package/themes/original/src/components/Sessions/styles.tsx +15 -0
  141. package/themes/original/src/components/SingleProductCard/index.tsx +47 -21
  142. package/themes/original/src/components/SingleProductCard/styles.tsx +28 -1
  143. package/themes/original/src/components/StripeElementsForm/index.tsx +55 -72
  144. package/themes/original/src/components/TaxInformation/index.tsx +10 -4
  145. package/themes/original/src/components/UpsellingProducts/index.tsx +87 -75
  146. package/themes/original/src/components/UserDetails/index.tsx +4 -95
  147. package/themes/original/src/components/UserFormDetails/index.tsx +34 -24
  148. package/themes/original/src/components/UserProfile/index.tsx +62 -14
  149. package/themes/original/src/components/UserProfileForm/index.tsx +20 -18
  150. package/themes/original/src/components/UserVerification/index.tsx +178 -192
  151. package/themes/original/src/components/VerifyPhone/index.tsx +10 -7
  152. package/themes/original/src/components/VerifyPhone/styles.tsx +2 -1
  153. package/themes/original/src/components/Wallets/index.tsx +76 -9
  154. package/themes/original/src/components/Wallets/styles.tsx +21 -0
  155. package/themes/original/src/components/shared/HeaderTitle.tsx +21 -0
  156. package/themes/original/src/components/shared/OModal.tsx +1 -1
  157. package/themes/original/src/components/shared/index.tsx +2 -0
  158. package/themes/original/src/config/constants.tsx +6 -6
  159. package/themes/original/src/types/index.tsx +68 -6
  160. package/themes/original/src/utils/index.tsx +28 -2
  161. package/themes/single-business/src/components/AddressList/index.tsx +1 -1
  162. package/themes/single-business/src/components/OrderTypeSelector/index.tsx +6 -6
  163. package/themes/single-business/src/components/UserProfile/index.tsx +1 -1
  164. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
  165. package/src/components/StripeMethodForm/index.tsx +0 -168
@@ -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,
@@ -17,8 +18,6 @@ import { useTheme } from 'styled-components/native';
17
18
  import { FacebookLogin } from '../FacebookLogin';
18
19
  import { VerifyPhone } from '../../../../../src/components/VerifyPhone';
19
20
  import { OModal } from '../../../../../src/components/shared';
20
-
21
-
22
21
  import {
23
22
  Container,
24
23
  ButtonsWrapper,
@@ -32,16 +31,19 @@ import {
32
31
  LineSeparator,
33
32
  SkeletonWrapper,
34
33
  TabBtn,
34
+ RecaptchaButton
35
35
  } from './styles';
36
36
 
37
37
  import NavBar from '../NavBar';
38
38
 
39
- import { OText, OButton, OInput, OIcon } from '../shared';
39
+ import { OText, OButton, OInput } from '../shared';
40
40
  import { LoginParams } from '../../types';
41
41
  import { Placeholder, PlaceholderLine, Fade } from 'rn-placeholder';
42
42
  import { GoogleLogin } from '../GoogleLogin';
43
43
  import { AppleLogin } from '../AppleLogin';
44
+ import { Otp } from './Otp'
44
45
  import { TouchableOpacity } from 'react-native-gesture-handler';
46
+ import Alert from '../../../../../src/providers/AlertProvider'
45
47
 
46
48
  const LoginFormUI = (props: LoginParams) => {
47
49
  const {
@@ -50,6 +52,7 @@ const LoginFormUI = (props: LoginParams) => {
50
52
  navigation,
51
53
  useLoginByEmail,
52
54
  useLoginByCellphone,
55
+ useLoginOtp,
53
56
  loginButtonText,
54
57
  forgotButtonText,
55
58
  verifyPhoneState,
@@ -60,7 +63,14 @@ const LoginFormUI = (props: LoginParams) => {
60
63
  handleSendVerifyCode,
61
64
  handleCheckPhoneCode,
62
65
  onNavigationRedirect,
63
- notificationState
66
+ notificationState,
67
+ handleReCaptcha,
68
+ enableReCaptcha,
69
+ otpType,
70
+ setOtpType,
71
+ generateOtpCode,
72
+ useLoginOtpEmail,
73
+ useLoginOtpCellphone,
64
74
  } = props;
65
75
 
66
76
  const [, { showToast }] = useToast();
@@ -72,6 +82,7 @@ const LoginFormUI = (props: LoginParams) => {
72
82
  const [isLoadingVerifyModal, setIsLoadingVerifyModal] = useState(false);
73
83
  const [isModalVisible, setIsModalVisible] = useState(false);
74
84
  const [isFBLoading, setIsFBLoading] = useState(false);
85
+ const [willVerifyOtpState, setWillVerifyOtpState] = useState(false)
75
86
  const [phoneInputData, setPhoneInputData] = useState({
76
87
  error: '',
77
88
  phone: {
@@ -79,9 +90,15 @@ const LoginFormUI = (props: LoginParams) => {
79
90
  cellphone: null,
80
91
  },
81
92
  });
93
+ const [recaptchaConfig, setRecaptchaConfig] = useState<any>({})
94
+ const [recaptchaVerified, setRecaptchaVerified] = useState(false)
95
+ const [alertState, setAlertState] = useState({ open: false, title: '', content: [] })
96
+ const [tabLayouts, setTabLayouts] = useState<any>({})
97
+ const tabsRef = useRef<any>(null)
82
98
 
83
99
  const theme = useTheme();
84
-
100
+ const isOtpEmail = loginTab === 'otp' && otpType === 'email'
101
+ const isOtpCellphone = loginTab === 'otp' && otpType === 'cellphone'
85
102
  const loginStyle = StyleSheet.create({
86
103
  btnOutline: {
87
104
  backgroundColor: '#FFF',
@@ -100,28 +117,69 @@ const LoginFormUI = (props: LoginParams) => {
100
117
  flexGrow: 1,
101
118
  marginBottom: 7,
102
119
  },
120
+ recaptchaIcon: {
121
+ width: 100,
122
+ height: 100,
123
+ },
124
+ borderStyleBase: {
125
+ width: 30,
126
+ height: 45
127
+ },
128
+
129
+ borderStyleHighLighted: {
130
+ borderColor: "#03DAC6",
131
+ },
132
+
133
+ underlineStyleBase: {
134
+ width: 45,
135
+ height: 60,
136
+ borderWidth: 1,
137
+ fontSize: 16
138
+ },
139
+
140
+ underlineStyleHighLighted: {
141
+ borderColor: theme.colors.primary,
142
+ color: theme.colors.primary,
143
+ fontSize: 16
144
+ },
103
145
  });
104
146
 
105
147
  const emailRef = useRef<any>({});
106
148
  const passwordRef = useRef<any>({});
149
+ const recaptchaRef = useRef<any>({});
107
150
 
108
- const handleChangeTab = (val: string) => {
151
+ const handleChangeTab = (val: string, otpType?: string) => {
109
152
  props.handleChangeTab(val);
110
153
  setPasswordSee(false);
154
+ handleCategoryScroll(otpType ? `${val}_${otpType}` : val)
111
155
  };
112
156
 
113
- const onSubmit = (values: any) => {
157
+ const onSubmit = (values?: any) => {
114
158
  Keyboard.dismiss();
115
- if (phoneInputData.error) {
116
- showToast(ToastType.Error, phoneInputData.error);
117
- return;
159
+ if (loginTab === 'otp') {
160
+ if (phoneInputData.error && (loginTab !== 'otp' || (otpType === 'cellphone' && loginTab === 'otp'))) {
161
+ showToast(ToastType.Error, t('INVALID_PHONE_NUMBER', 'Invalid phone number'));
162
+ return
163
+ }
164
+ if (loginTab === 'otp') {
165
+ generateOtpCode({
166
+ ...values,
167
+ ...phoneInputData.phone
168
+ })
169
+ }
170
+ setWillVerifyOtpState(true)
171
+ } else {
172
+ if (phoneInputData.error) {
173
+ showToast(ToastType.Error, phoneInputData.error);
174
+ return;
175
+ }
176
+ handleButtonLoginClick({
177
+ ...values,
178
+ ...phoneInputData.phone,
179
+ });
118
180
  }
119
- handleButtonLoginClick({
120
- ...values,
121
- ...phoneInputData.phone,
122
- });
123
- };
124
181
 
182
+ };
125
183
  const handleVerifyCodeClick = () => {
126
184
  if (phoneInputData.error) {
127
185
  showToast(ToastType.Error, phoneInputData.error);
@@ -156,6 +214,66 @@ const LoginFormUI = (props: LoginParams) => {
156
214
  onChange(value.toLowerCase().replace(/[&,()%";:ç?<>{}\\[\]\s]/g, ''));
157
215
  };
158
216
 
217
+ const handleOpenRecaptcha = () => {
218
+ setRecaptchaVerified(false)
219
+ if (!recaptchaConfig?.siteKey) {
220
+ showToast(ToastType.Error, t('NO_RECAPTCHA_SITE_KEY', 'The config doesn\'t have recaptcha site key'));
221
+ return
222
+ }
223
+ if (!recaptchaConfig?.baseUrl) {
224
+ showToast(ToastType.Error, t('NO_RECAPTCHA_BASE_URL', 'The config doesn\'t have recaptcha base url'));
225
+ return
226
+ }
227
+
228
+ recaptchaRef.current.open()
229
+ }
230
+
231
+ const onRecaptchaVerify = (token: any) => {
232
+ setRecaptchaVerified(true)
233
+ handleReCaptcha(token)
234
+ }
235
+
236
+ const handleChangeOtpType = (type: string) => {
237
+ handleChangeTab('otp', type)
238
+ setOtpType(type)
239
+ }
240
+
241
+ const handleLoginOtp = (code: string) => {
242
+ handleButtonLoginClick({ code })
243
+ setWillVerifyOtpState(false)
244
+ }
245
+
246
+ const closeAlert = () => {
247
+ setAlertState({
248
+ open: false,
249
+ title: '',
250
+ content: []
251
+ })
252
+ }
253
+
254
+ const handleCategoryScroll = (opc : string) => {
255
+ tabsRef.current.scrollTo({
256
+ x: tabLayouts?.[opc]?.x - 40,
257
+ animated: true
258
+ })
259
+ }
260
+
261
+ const handleOnLayout = (event: any, opc: string) => {
262
+ const _tabLayouts = { ...tabLayouts }
263
+ const categoryKey = opc
264
+ _tabLayouts[categoryKey] = event.nativeEvent.layout
265
+ setTabLayouts(_tabLayouts)
266
+ }
267
+
268
+ useEffect(() => {
269
+ if (configs && Object.keys(configs).length > 0 && enableReCaptcha) {
270
+ setRecaptchaConfig({
271
+ siteKey: configs?.security_recaptcha_site_key?.value || null,
272
+ baseUrl: configs?.security_recaptcha_base_url?.value || null
273
+ })
274
+ }
275
+ }, [configs, enableReCaptcha])
276
+
159
277
  useEffect(() => {
160
278
  if (!formState.loading && formState.result?.error) {
161
279
  formState.result?.result &&
@@ -194,16 +312,26 @@ const LoginFormUI = (props: LoginParams) => {
194
312
  }, [phoneInputData?.phone?.cellphone])
195
313
 
196
314
  useEffect(() => {
197
- register('cellphone', {
198
- required: loginTab === 'cellphone'
199
- ? t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Mobile phone is required').replace('_attribute_', t('CELLPHONE', 'Cellphone'))
200
- : null
201
- })
202
- }, [register])
315
+ register('cellphone', {
316
+ required: loginTab === 'cellphone'
317
+ ? t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Mobile phone is required').replace('_attribute_', t('CELLPHONE', 'Cellphone'))
318
+ : null
319
+ })
320
+ }, [register])
321
+
322
+ useEffect(() => {
323
+ reset()
324
+ }, [loginTab])
203
325
 
204
326
  useEffect(() => {
205
- reset()
206
- }, [loginTab])
327
+ if (checkPhoneCodeState?.result?.error) {
328
+ setAlertState({
329
+ open: true,
330
+ content: t(checkPhoneCodeState?.result?.error, checkPhoneCodeState?.result?.error),
331
+ title: ''
332
+ })
333
+ }
334
+ }, [checkPhoneCodeState])
207
335
 
208
336
  return (
209
337
  <Container>
@@ -218,11 +346,18 @@ const LoginFormUI = (props: LoginParams) => {
218
346
  titleStyle={{ marginRight: 0, marginLeft: 0 }}
219
347
  />
220
348
  <FormSide>
221
- {useLoginByEmail && useLoginByCellphone && (
349
+ {((useLoginByEmail && useLoginByCellphone) || useLoginOtp) && (
222
350
  <LoginWith>
223
- <OTabs>
351
+ <OTabs
352
+ horizontal
353
+ showsHorizontalScrollIndicator={false}
354
+ ref={tabsRef}
355
+ >
224
356
  {useLoginByEmail && (
225
- <TabBtn onPress={() => handleChangeTab('email')}>
357
+ <TabBtn
358
+ onPress={() => handleChangeTab('email')}
359
+ onLayout={(event: any) => handleOnLayout(event, 'email')}
360
+ >
226
361
  <OTab
227
362
  style={{
228
363
  borderBottomColor:
@@ -244,7 +379,10 @@ const LoginFormUI = (props: LoginParams) => {
244
379
  </TabBtn>
245
380
  )}
246
381
  {useLoginByCellphone && (
247
- <TabBtn onPress={() => handleChangeTab('cellphone')}>
382
+ <TabBtn
383
+ onPress={() => handleChangeTab('cellphone')}
384
+ onLayout={(event: any) => handleOnLayout(event, 'cellphone')}
385
+ >
248
386
  <OTab
249
387
  style={{
250
388
  borderBottomColor:
@@ -265,13 +403,63 @@ const LoginFormUI = (props: LoginParams) => {
265
403
  </OTab>
266
404
  </TabBtn>
267
405
  )}
406
+ {useLoginOtpEmail && (
407
+ <TabBtn
408
+ onPress={() => handleChangeOtpType('email')}
409
+ onLayout={(event: any) => handleOnLayout(event, 'otp_email')}
410
+ >
411
+ <OTab
412
+ style={{
413
+ borderBottomColor:
414
+ isOtpEmail
415
+ ? theme.colors.textNormal
416
+ : theme.colors.border,
417
+ }}>
418
+ <OText
419
+ size={14}
420
+ color={
421
+ isOtpEmail
422
+ ? theme.colors.textNormal
423
+ : theme.colors.disabled
424
+ }
425
+ weight={isOtpEmail ? 'bold' : 'normal'}>
426
+ {t('BY_OTP_EMAIL', 'By Otp Email')}
427
+ </OText>
428
+ </OTab>
429
+ </TabBtn>
430
+ )}
431
+ {useLoginOtpCellphone && (
432
+ <TabBtn
433
+ onPress={() => handleChangeOtpType('cellphone')}
434
+ onLayout={(event: any) => handleOnLayout(event, 'otp_cellphone')}
435
+ >
436
+ <OTab
437
+ style={{
438
+ borderBottomColor:
439
+ isOtpCellphone
440
+ ? theme.colors.textNormal
441
+ : theme.colors.border,
442
+ }}>
443
+ <OText
444
+ size={14}
445
+ color={
446
+ isOtpCellphone
447
+ ? theme.colors.textNormal
448
+ : theme.colors.disabled
449
+ }
450
+ weight={isOtpCellphone ? 'bold' : 'normal'}>
451
+ {t('BY_OTP_PHONE', 'By Otp Phone')}
452
+ </OText>
453
+ </OTab>
454
+ </TabBtn>
455
+ )}
268
456
  </OTabs>
269
457
  </LoginWith>
270
458
  )}
271
459
 
272
- {(useLoginByCellphone || useLoginByEmail) && (
460
+ {(useLoginByCellphone || useLoginByEmail || useLoginOtp) && (
273
461
  <FormInput>
274
- {useLoginByEmail && loginTab === 'email' && (
462
+ {((useLoginByEmail && loginTab === 'email') || (loginTab === 'otp' && otpType === 'email')) && (
275
463
  <>
276
464
  {errors?.email && (
277
465
  <OText
@@ -307,10 +495,10 @@ const LoginFormUI = (props: LoginParams) => {
307
495
  rules={{
308
496
  required: {
309
497
  value: true,
310
- message: t(
311
- 'VALIDATION_ERROR_EMAIL_REQUIRED',
312
- 'The field Email is required',
313
- ).replace('_attribute_', t('EMAIL', 'Email'))
498
+ message: t(
499
+ 'VALIDATION_ERROR_EMAIL_REQUIRED',
500
+ 'The field Email is required',
501
+ ).replace('_attribute_', t('EMAIL', 'Email'))
314
502
  },
315
503
  pattern: {
316
504
  value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
@@ -325,7 +513,7 @@ const LoginFormUI = (props: LoginParams) => {
325
513
  </>
326
514
 
327
515
  )}
328
- {useLoginByCellphone && loginTab === 'cellphone' && (
516
+ {((useLoginByCellphone && loginTab === 'cellphone') || (loginTab === 'otp' && otpType === 'cellphone')) && (
329
517
  <View style={{ marginBottom: 28 }}>
330
518
  <PhoneInputNumber
331
519
  data={phoneInputData}
@@ -346,62 +534,97 @@ const LoginFormUI = (props: LoginParams) => {
346
534
  {errors?.password?.message}{errors?.password?.type === 'required' && '*'}
347
535
  </OText>
348
536
  )}
349
- <Controller
350
- control={control}
351
- render={({ onChange, value }: any) => (
352
- <OInput
353
- isSecured={!passwordSee ? true : false}
354
- placeholder={t('PASSWORD', 'Password')}
355
- style={{...loginStyle.inputStyle, marginBottom: 14}}
356
- icon={theme.images.general.lock}
357
- iconCustomRight={
358
- !passwordSee ? (
359
- <MaterialCommunityIcons
360
- name="eye-outline"
361
- size={24}
362
- onPress={() => setPasswordSee(!passwordSee)}
363
- color={theme.colors.disabled}
364
- />
365
- ) : (
366
- <MaterialCommunityIcons
367
- name="eye-off-outline"
368
- size={24}
369
- onPress={() => setPasswordSee(!passwordSee)}
370
- color={theme.colors.disabled}
371
- />
372
- )
537
+ {loginTab !== 'otp' && (
538
+
539
+ <Controller
540
+ control={control}
541
+ render={({ onChange, value }: any) => (
542
+ <OInput
543
+ isSecured={!passwordSee ? true : false}
544
+ placeholder={t('PASSWORD', 'Password')}
545
+ style={{ ...loginStyle.inputStyle, marginBottom: 14 }}
546
+ icon={theme.images.general.lock}
547
+ iconCustomRight={
548
+ !passwordSee ? (
549
+ <MaterialCommunityIcons
550
+ name="eye-outline"
551
+ size={24}
552
+ onPress={() => setPasswordSee(!passwordSee)}
553
+ color={theme.colors.disabled}
554
+ />
555
+ ) : (
556
+ <MaterialCommunityIcons
557
+ name="eye-off-outline"
558
+ size={24}
559
+ onPress={() => setPasswordSee(!passwordSee)}
560
+ color={theme.colors.disabled}
561
+ />
562
+ )
563
+ }
564
+ value={value}
565
+ forwardRef={passwordRef}
566
+ onChange={(val: any) => onChange(val)}
567
+ returnKeyType="done"
568
+ onSubmitEditing={handleSubmit(onSubmit)}
569
+ blurOnSubmit
570
+ borderColor={errors?.password ? theme.colors.danger5 : theme.colors.border}
571
+ />
572
+ )}
573
+ name="password"
574
+ rules={{
575
+ required: {
576
+ value: true,
577
+ message: t(
578
+ 'VALIDATION_ERROR_PASSWORD_REQUIRED',
579
+ 'The field Password is required',
580
+ ).replace('_attribute_', t('PASSWORD', 'Password'))
373
581
  }
374
- value={value}
375
- forwardRef={passwordRef}
376
- onChange={(val: any) => onChange(val)}
377
- returnKeyType="done"
378
- onSubmitEditing={handleSubmit(onSubmit)}
379
- blurOnSubmit
380
- borderColor={errors?.password ? theme.colors.danger5 : theme.colors.border}
381
- />
382
- )}
383
- name="password"
384
- rules={{
385
- required: {
386
- value: true,
387
- message: t(
388
- 'VALIDATION_ERROR_PASSWORD_REQUIRED',
389
- 'The field Password is required',
390
- ).replace('_attribute_', t('PASSWORD', 'Password'))
391
- }
392
- }}
393
- defaultValue=""
394
- />
395
- {onNavigationRedirect && forgotButtonText && (
582
+ }}
583
+ defaultValue=""
584
+ />
585
+ )}
586
+ {onNavigationRedirect && forgotButtonText && loginTab !== 'otp' && (
396
587
  <TouchableOpacity onPress={() => onNavigationRedirect('Forgot')}>
397
588
  <OText size={14} mBottom={18}>
398
589
  {forgotButtonText}
399
590
  </OText>
400
591
  </TouchableOpacity>
401
592
  )}
593
+
594
+ {enableReCaptcha && (
595
+ <>
596
+ <TouchableOpacity
597
+ onPress={handleOpenRecaptcha}
598
+ >
599
+ <RecaptchaButton>
600
+ {recaptchaVerified ? (
601
+ <MaterialCommunityIcons
602
+ name="checkbox-marked"
603
+ size={26}
604
+ color={theme.colors.primary}
605
+ />
606
+ ) : (
607
+ <MaterialCommunityIcons
608
+ name="checkbox-blank-outline"
609
+ size={26}
610
+ color={theme.colors.mediumGray}
611
+ />
612
+ )}
613
+ <OText size={14} mLeft={8}>{t('VERIFY_ReCAPTCHA', 'Verify reCAPTCHA')}</OText>
614
+ </RecaptchaButton>
615
+ </TouchableOpacity>
616
+ <Recaptcha
617
+ ref={recaptchaRef}
618
+ siteKey={recaptchaConfig?.siteKey}
619
+ baseUrl={recaptchaConfig?.baseUrl}
620
+ onVerify={onRecaptchaVerify}
621
+ onExpire={() => setRecaptchaVerified(false)}
622
+ />
623
+ </>
624
+ )}
402
625
  <OButton
403
626
  onClick={handleSubmit(onSubmit)}
404
- text={loginButtonText}
627
+ text={loginTab !== 'otp' ? loginButtonText : t('GET_VERIFY_CODE', 'Get verify code')}
405
628
  bgColor={theme.colors.primary}
406
629
  borderColor={theme.colors.primary}
407
630
  textStyle={{ color: 'white' }}
@@ -410,11 +633,11 @@ const LoginFormUI = (props: LoginParams) => {
410
633
  style={{ borderRadius: 7.6, marginTop: 10, marginBottom: 25 }}
411
634
  />
412
635
  {onNavigationRedirect && registerButtonText && (
413
- <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center'}}>
636
+ <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center' }}>
414
637
  <OText size={14}>
415
638
  {t('NEW_ON_PLATFORM', 'New on Ordering?')}
416
639
  </OText>
417
- <TouchableOpacity onPress={() => onNavigationRedirect('Signup')}>
640
+ <TouchableOpacity onPress={() => onNavigationRedirect('Signup')}>
418
641
  <OText size={14} mLeft={5} color={theme.colors.skyBlue}>
419
642
  {t('CREATE_ACCOUNT', 'Create account')}
420
643
  </OText>
@@ -425,11 +648,11 @@ const LoginFormUI = (props: LoginParams) => {
425
648
  )}
426
649
 
427
650
  {useLoginByCellphone &&
428
- loginTab === 'cellphone' &&
429
- configs && Object.keys(configs).length > 0 &&
430
- (configs?.twilio_service_enabled?.value === 'true' ||
431
- configs?.twilio_service_enabled?.value === '1') &&
432
- configs?.twilio_module?.value && (
651
+ loginTab === 'cellphone' &&
652
+ configs && Object.keys(configs).length > 0 &&
653
+ (configs?.twilio_service_enabled?.value === 'true' ||
654
+ configs?.twilio_service_enabled?.value === '1') &&
655
+ configs?.twilio_module?.value && (
433
656
  <>
434
657
  <OrSeparator>
435
658
  <LineSeparator />
@@ -454,59 +677,59 @@ const LoginFormUI = (props: LoginParams) => {
454
677
  )}
455
678
 
456
679
  {configs && Object.keys(configs).length > 0 ? (
457
- (((configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') && configs?.facebook_id?.value) ||
458
- (configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null)) &&
459
- (
460
- <>
461
- <View
462
- style={{
463
- flexDirection: 'row',
464
- width: '100%',
465
- justifyContent: 'space-between',
466
- alignItems: 'center',
467
- marginVertical: 15
468
- }}>
469
- <View style={loginStyle.line} />
470
- <OText
471
- size={14}
472
- mBottom={10}
473
- style={{ paddingHorizontal: 19 }}
474
- color={theme.colors.disabled}>
475
- {t('OR', 'or')}
476
- </OText>
477
- <View style={loginStyle.line} />
478
- </View>
479
- <ButtonsWrapper>
480
- <SocialButtons>
481
- {(configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') &&
482
- configs?.facebook_id?.value && (
483
- <FacebookLogin
484
- notificationState={notificationState}
485
- handleErrors={(err: any) => showToast(ToastType.Error, err)}
486
- handleLoading={(val: boolean) => setIsFBLoading(val)}
487
- handleSuccessFacebookLogin={handleSuccessFacebook}
488
- />
489
- )}
490
- {(configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && (
491
- <GoogleLogin
492
- notificationState={notificationState}
493
- webClientId={configs?.google_login_client_id?.value}
494
- handleErrors={(err: any) => showToast(ToastType.Error, err)}
495
- handleLoading={(val: boolean) => setIsFBLoading(val)}
496
- handleSuccessGoogleLogin={handleSuccessFacebook}
497
- />
498
- )}
499
- {(configs?.apple_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && (
500
- <AppleLogin
501
- notificationState={notificationState}
502
- handleErrors={(err: any) => showToast(ToastType.Error, err)}
503
- handleLoading={(val: boolean) => setIsFBLoading(val)}
504
- handleSuccessAppleLogin={handleSuccessFacebook}
505
- />
506
- )}
507
- </SocialButtons>
508
- </ButtonsWrapper>
509
- </>
680
+ (((configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') && configs?.facebook_id?.value) ||
681
+ (configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null)) &&
682
+ (
683
+ <>
684
+ <View
685
+ style={{
686
+ flexDirection: 'row',
687
+ width: '100%',
688
+ justifyContent: 'space-between',
689
+ alignItems: 'center',
690
+ marginVertical: 15
691
+ }}>
692
+ <View style={loginStyle.line} />
693
+ <OText
694
+ size={14}
695
+ mBottom={10}
696
+ style={{ paddingHorizontal: 19 }}
697
+ color={theme.colors.disabled}>
698
+ {t('OR', 'or')}
699
+ </OText>
700
+ <View style={loginStyle.line} />
701
+ </View>
702
+ <ButtonsWrapper>
703
+ <SocialButtons>
704
+ {(configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') &&
705
+ configs?.facebook_id?.value && (
706
+ <FacebookLogin
707
+ notificationState={notificationState}
708
+ handleErrors={(err: any) => showToast(ToastType.Error, err)}
709
+ handleLoading={(val: boolean) => setIsFBLoading(val)}
710
+ handleSuccessFacebookLogin={handleSuccessFacebook}
711
+ />
712
+ )}
713
+ {(configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && (
714
+ <GoogleLogin
715
+ notificationState={notificationState}
716
+ webClientId={configs?.google_login_client_id?.value}
717
+ handleErrors={(err: any) => showToast(ToastType.Error, err)}
718
+ handleLoading={(val: boolean) => setIsFBLoading(val)}
719
+ handleSuccessGoogleLogin={handleSuccessFacebook}
720
+ />
721
+ )}
722
+ {(configs?.apple_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && (
723
+ <AppleLogin
724
+ notificationState={notificationState}
725
+ handleErrors={(err: any) => showToast(ToastType.Error, err)}
726
+ handleLoading={(val: boolean) => setIsFBLoading(val)}
727
+ handleSuccessAppleLogin={handleSuccessFacebook}
728
+ />
729
+ )}
730
+ </SocialButtons>
731
+ </ButtonsWrapper>
732
+ </>
510
733
  )
511
734
  ) : (
512
735
  <SkeletonWrapper>
@@ -522,24 +745,12 @@ const LoginFormUI = (props: LoginParams) => {
522
745
  </Placeholder>
523
746
  </SkeletonWrapper>
524
747
  )}
525
-
526
- {/* {onNavigationRedirect && registerButtonText && (
527
- <ButtonsWrapper>
528
- <OButton
529
- onClick={() => onNavigationRedirect('Signup')}
530
- text={registerButtonText}
531
- style={loginStyle.btnOutline}
532
- borderColor={theme.colors.primary}
533
- imgRightSrc={null}
534
- />
535
- </ButtonsWrapper>
536
- )} */}
537
748
  </FormSide>
538
749
  <OModal
539
750
  open={isModalVisible}
540
751
  onClose={() => setIsModalVisible(false)}
541
- entireModal
542
- title={t('VERIFY_PHONE', 'Verify Phone')}
752
+ entireModal
753
+ title={t('VERIFY_PHONE', 'Verify Phone')}
543
754
  >
544
755
  <VerifyPhone
545
756
  phone={phoneInputData.phone}
@@ -548,9 +759,30 @@ const LoginFormUI = (props: LoginParams) => {
548
759
  handleCheckPhoneCode={handleCheckPhoneCode}
549
760
  setCheckPhoneCodeState={setCheckPhoneCodeState}
550
761
  handleVerifyCodeClick={handleVerifyCodeClick}
551
- onClose={() => setIsModalVisible(false)}
762
+ onClose={() => setIsModalVisible(false)}
552
763
  />
553
764
  </OModal>
765
+ <OModal
766
+ open={willVerifyOtpState}
767
+ onClose={() => setWillVerifyOtpState(false)}
768
+ entireModal
769
+ title={t('ENTER_VERIFICATION_CODE', 'Enter verification code')}
770
+ >
771
+ <Otp
772
+ willVerifyOtpState={willVerifyOtpState}
773
+ setWillVerifyOtpState={setWillVerifyOtpState}
774
+ handleLoginOtp={handleLoginOtp}
775
+ onSubmit={onSubmit}
776
+ setAlertState={setAlertState}
777
+ />
778
+ </OModal>
779
+ <Alert
780
+ open={alertState.open}
781
+ content={alertState.content}
782
+ title={alertState.title || ''}
783
+ onAccept={closeAlert}
784
+ onClose={closeAlert}
785
+ />
554
786
  <Spinner visible={isFBLoading} />
555
787
  </Container>
556
788
  );
@@ -559,6 +791,7 @@ const LoginFormUI = (props: LoginParams) => {
559
791
  export const LoginForm = (props: any) => {
560
792
  const loginProps = {
561
793
  ...props,
794
+ isRecaptchaEnable: true,
562
795
  UIComponent: LoginFormUI,
563
796
  };
564
797
  return <LoginFormController {...loginProps} />;