ordering-ui-react-native 0.15.37 → 0.15.38-test

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 (79) hide show
  1. package/package.json +3 -2
  2. package/src/components/BusinessTypeFilter/index.tsx +4 -1
  3. package/src/components/LanguageSelector/index.tsx +1 -0
  4. package/src/components/OrderDetails/index.tsx +2 -2
  5. package/src/components/PaymentOptions/index.tsx +2 -2
  6. package/src/components/StripeMethodForm/index.tsx +22 -21
  7. package/src/pages/BusinessProductsList.tsx +1 -0
  8. package/src/pages/BusinessesListing.tsx +1 -1
  9. package/themes/business/src/components/Home/index.tsx +128 -55
  10. package/themes/business/src/components/Home/styles.tsx +8 -1
  11. package/themes/business/src/components/NewOrderNotification/index.tsx +59 -98
  12. package/themes/business/src/components/OrderDetails/Delivery.tsx +9 -9
  13. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +152 -91
  14. package/themes/business/src/components/OrderDetails/styles.tsx +7 -0
  15. package/themes/business/src/components/OrdersListManager/index.tsx +51 -48
  16. package/themes/business/src/components/OrdersOption/index.tsx +52 -48
  17. package/themes/business/src/components/PreviousOrders/index.tsx +50 -14
  18. package/themes/kiosk/src/components/Cart/index.tsx +99 -25
  19. package/themes/kiosk/src/components/Cart/styles.tsx +6 -0
  20. package/themes/kiosk/src/components/OrderDetails/index.tsx +134 -39
  21. package/themes/kiosk/src/components/OrderDetails/styles.tsx +5 -0
  22. package/themes/kiosk/src/components/ProductForm/index.tsx +2 -2
  23. package/themes/kiosk/src/types/index.d.ts +2 -0
  24. package/themes/original/index.tsx +165 -0
  25. package/themes/original/src/components/AddressForm/index.tsx +15 -10
  26. package/themes/original/src/components/AddressList/index.tsx +28 -2
  27. package/themes/original/src/components/AppleLogin/index.tsx +118 -77
  28. package/themes/original/src/components/BusinessBasicInformation/index.tsx +96 -45
  29. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +28 -1
  30. package/themes/original/src/components/BusinessController/index.tsx +28 -9
  31. package/themes/original/src/components/BusinessController/styles.tsx +22 -0
  32. package/themes/original/src/components/BusinessFeaturedController/index.tsx +20 -1
  33. package/themes/original/src/components/BusinessFeaturedController/styles.tsx +23 -0
  34. package/themes/original/src/components/BusinessListingSearch/index.tsx +4 -0
  35. package/themes/original/src/components/BusinessMenuList/index.tsx +11 -4
  36. package/themes/original/src/components/BusinessPreorder/index.tsx +141 -121
  37. package/themes/original/src/components/BusinessProductsCategories/index.tsx +7 -5
  38. package/themes/original/src/components/BusinessProductsList/index.tsx +126 -21
  39. package/themes/original/src/components/BusinessProductsList/styles.tsx +32 -2
  40. package/themes/original/src/components/BusinessProductsListing/index.tsx +12 -5
  41. package/themes/original/src/components/BusinessReviews/index.tsx +4 -25
  42. package/themes/original/src/components/BusinessesListing/index.tsx +1 -2
  43. package/themes/original/src/components/Cart/index.tsx +1 -3
  44. package/themes/original/src/components/CartContent/index.tsx +2 -2
  45. package/themes/original/src/components/Checkout/index.tsx +2 -1
  46. package/themes/original/src/components/Home/index.tsx +1 -1
  47. package/themes/original/src/components/LoginForm/index.tsx +73 -2
  48. package/themes/original/src/components/LoginForm/styles.tsx +6 -1
  49. package/themes/original/src/components/LogoutButton/index.tsx +7 -1
  50. package/themes/original/src/components/Messages/index.tsx +5 -0
  51. package/themes/original/src/components/Messages/styles.tsx +1 -3
  52. package/themes/original/src/components/MomentOption/index.tsx +10 -1
  53. package/themes/original/src/components/MomentOption/styles.tsx +1 -1
  54. package/themes/original/src/components/OrderDetails/index.tsx +1 -3
  55. package/themes/original/src/components/OrderProgress/index.tsx +3 -3
  56. package/themes/original/src/components/OrderProgress/styles.tsx +1 -0
  57. package/themes/original/src/components/OrderSummary/index.tsx +2 -2
  58. package/themes/original/src/components/PaymentOptionWallet/index.tsx +6 -2
  59. package/themes/original/src/components/PaymentOptions/index.tsx +3 -1
  60. package/themes/original/src/components/PhoneInputNumber/index.tsx +10 -4
  61. package/themes/original/src/components/PreviousOrders/index.tsx +14 -12
  62. package/themes/original/src/components/ProductForm/index.tsx +4 -4
  63. package/themes/original/src/components/Promotions/index.tsx +232 -0
  64. package/themes/original/src/components/Promotions/styles.tsx +80 -0
  65. package/themes/original/src/components/SignupForm/index.tsx +109 -13
  66. package/themes/original/src/components/SingleProductCard/index.tsx +39 -18
  67. package/themes/original/src/components/SingleProductCard/styles.tsx +28 -1
  68. package/themes/original/src/components/TaxInformation/index.tsx +10 -4
  69. package/themes/original/src/components/UserFormDetails/index.tsx +13 -2
  70. package/themes/original/src/components/UserProfile/index.tsx +53 -8
  71. package/themes/original/src/components/Wallets/index.tsx +57 -3
  72. package/themes/original/src/components/Wallets/styles.tsx +21 -0
  73. package/themes/original/src/components/shared/HeaderTitle.tsx +21 -0
  74. package/themes/original/src/components/shared/index.tsx +2 -0
  75. package/themes/original/src/config/constants.tsx +6 -6
  76. package/themes/original/src/types/index.tsx +21 -1
  77. package/themes/original/src/utils/index.tsx +9 -0
  78. package/themes/single-business/src/components/AddressList/index.tsx +1 -1
  79. package/themes/single-business/src/components/UserProfile/index.tsx +1 -1
@@ -0,0 +1,232 @@
1
+ import React, { useState } from 'react'
2
+ import { PromotionsController, useLanguage, useUtils, useEvent } from 'ordering-components/native'
3
+ import {
4
+ PromotionsContainer,
5
+ SingleOfferContainer,
6
+ OfferInformation,
7
+ SearchBarContainer,
8
+ SingleBusinessOffer,
9
+ AvailableBusinesses,
10
+ OfferData,
11
+ Code,
12
+ BusinessInfo
13
+ } from './styles'
14
+ import { SearchBar } from '../SearchBar'
15
+ import NavBar from '../NavBar'
16
+ import { useTheme } from 'styled-components/native';
17
+ import { OButton, OIcon, OModal, OText } from '../shared'
18
+ import { Placeholder, PlaceholderLine } from 'rn-placeholder'
19
+ import { NotFoundSource } from '../NotFoundSource'
20
+ import { View, StyleSheet, ScrollView } from 'react-native'
21
+ import FastImage from 'react-native-fast-image'
22
+ import { PromotionParams } from '../../types'
23
+ const PromotionsUI = (props : PromotionParams) => {
24
+ const {
25
+ navigation,
26
+ offersState,
27
+ handleSearchValue,
28
+ searchValue,
29
+ offerSelected,
30
+ setOfferSelected
31
+ } = props
32
+
33
+ const theme = useTheme();
34
+
35
+ const styles = StyleSheet.create({
36
+ productStyle: {
37
+ width: 75,
38
+ height: 75,
39
+ borderRadius: 7.6
40
+ },
41
+ buttonStyle: {
42
+ width: 55,
43
+ height: 25,
44
+ paddingLeft: 0,
45
+ paddingRight: 0
46
+ },
47
+ offerTitle: {
48
+ fontSize: 12
49
+ },
50
+ offerDescription: {
51
+ color: '#909BA9',
52
+ fontSize: 10
53
+ },
54
+ offerExtraInfo: {
55
+ fontSize: 10
56
+ },
57
+ modalButtonStyle: {
58
+ width: 100,
59
+ height: 35,
60
+ paddingLeft: 0,
61
+ paddingRight: 0,
62
+ borderRadius: 7.6
63
+ }
64
+ });
65
+
66
+ const [, t] = useLanguage()
67
+ const [{ parseDate, parsePrice, optimizeImage }] = useUtils()
68
+ const [events] = useEvent()
69
+ const [openModal, setOpenModal] = useState(false)
70
+
71
+ const handleClickOffer = (offer : any) => {
72
+ setOpenModal(true)
73
+ setOfferSelected(offer)
74
+ }
75
+
76
+ const handleBusinessClick = (business : any) => {
77
+ events.emit('go_to_page', { page: 'business', params: { store: business.slug } })
78
+ }
79
+
80
+ const filteredOffers = offersState?.offers?.filter((offer : any) => offer.name.toLowerCase().includes(searchValue.toLowerCase()))
81
+
82
+ const targetString = offerSelected?.target === 1
83
+ ? t('SUBTOTAL', 'Subtotal')
84
+ : offerSelected?.target === 2
85
+ ? t('DELIVERY_FEE', 'Delivery fee')
86
+ : t('SERVICE_FEE', 'Service fee')
87
+
88
+ return (
89
+ <PromotionsContainer>
90
+ <NavBar
91
+ onActionLeft={() => navigation.goBack()}
92
+ btnStyle={{ paddingLeft: 0 }}
93
+ paddingTop={20}
94
+ style={{ paddingBottom: 0, flexDirection: 'column', alignItems: 'flex-start' }}
95
+ title={t('PROMOTIONS', 'Promotions')}
96
+ titleAlign={'center'}
97
+ titleStyle={{ fontSize: 16, marginRight: 0, marginLeft: 0, marginBottom: 10 }}
98
+ titleWrapStyle={{ paddingHorizontal: 0 }}
99
+ />
100
+ <SearchBarContainer>
101
+ <SearchBar
102
+ placeholder={t('SEARCH_OFFERS', 'Search offers')}
103
+ onSearch={handleSearchValue}
104
+ />
105
+ </SearchBarContainer>
106
+
107
+ {offersState?.loading && (
108
+ <>
109
+ {[...Array(5).keys()].map((key, i) => (
110
+ <Placeholder key={i} style={{ flexDirection: 'row', marginBottom: 20 }}>
111
+ <PlaceholderLine height={10} width={45} />
112
+ <PlaceholderLine height={10} width={60} />
113
+ <PlaceholderLine height={10} width={75} />
114
+ </Placeholder>
115
+ ))}
116
+ </>
117
+ )}
118
+ {((!offersState?.loading && filteredOffers?.length === 0) || offersState?.error) && (
119
+ <NotFoundSource
120
+ content={offersState?.error || t('NOT_FOUND_OFFERS', 'Not found offers')}
121
+ />
122
+ )}
123
+ <ScrollView>
124
+ {!offersState?.loading && offersState.offers?.length > 0 && filteredOffers?.map((offer : any) => (
125
+ <SingleOfferContainer key={offer.id}>
126
+ <OfferInformation>
127
+ <OText style={styles.offerTitle}>{offer?.name}</OText>
128
+ {offer?.description && (
129
+ <OText style={styles.offerDescription}>{offer?.description}</OText>
130
+ )}
131
+ <OText style={styles.offerExtraInfo}>
132
+ {t('EXPIRES', 'Expires')} {parseDate(offer?.end, { outputFormat: 'MMM DD, YYYY' })}
133
+ </OText>
134
+ <AvailableBusinesses>
135
+ <OText style={styles.offerExtraInfo}>{t('APPLY_FOR', 'Apply for')}:</OText>
136
+ {offer.businesses.map((business: any, i: number) => (
137
+ <OText style={styles.offerExtraInfo} key={business?.id}>{' '}{business?.name}{i + 1 < offer.businesses?.length ? ',' : ''}</OText>
138
+ ))}
139
+ </AvailableBusinesses>
140
+ </OfferInformation>
141
+ <OButton
142
+ onClick={() => handleClickOffer(offer)}
143
+ text={t('VIEW', 'View')}
144
+ style={styles.buttonStyle}
145
+ textStyle={{ fontSize: 10, color: '#fff', flexWrap: 'nowrap' }}
146
+ />
147
+ </SingleOfferContainer>
148
+ ))}
149
+ </ScrollView>
150
+ <OModal
151
+ open={openModal}
152
+ onClose={() => setOpenModal(false)}
153
+ entireModal
154
+
155
+ title={``}
156
+ >
157
+ <View style={{ padding: 20 }}>
158
+ <OText style={{ alignSelf: 'center', fontWeight: '700' }} mBottom={20}>
159
+ {offerSelected?.name} / {t('VALUE_OF_OFFER', 'Value of offer')}: {offerSelected?.rate_type === 1 ? `${offerSelected?.rate}%` : `${parsePrice(offerSelected?.rate)}`}
160
+ </OText>
161
+ <OfferData>
162
+ {offerSelected?.type === 2 && (
163
+ <Code>
164
+ <OText>{t('YOUR_CODE', 'Your code')}</OText>
165
+ <OText color={theme.colors.primary}>{offerSelected.coupon}</OText>
166
+ </Code>
167
+ )}
168
+ <OText>{t('APPLIES_TO', 'Applies to')}: {targetString}</OText>
169
+ {offerSelected?.auto && (
170
+ <OText>{t('OFFER_AUTOMATIC', 'This offer applies automatic')}</OText>
171
+ )}
172
+ {offerSelected?.minimum && (
173
+ <OText>{t('MINIMUM_PURCHASE_FOR_OFFER', 'Minimum purshase for use this offer')}: {parsePrice(offerSelected?.minimum)}</OText>
174
+ )}
175
+ {offerSelected?.max_discount && (
176
+ <OText>{t('MAX_DISCOUNT_ALLOWED', 'Max discount allowed')}: {parsePrice(offerSelected?.max_discount)}</OText>
177
+ )}
178
+ {offerSelected?.description && (
179
+ <OText>{offerSelected?.description}</OText>
180
+ )}
181
+ </OfferData>
182
+ <OText style={{ marginTop: 10, marginBottom: 10 }}>
183
+ {t('AVAILABLE_BUSINESSES_FOR_OFFER', 'Available businesses for this offer')}:
184
+ </OText>
185
+ <ScrollView style={{height: '75%'}}>
186
+ {offerSelected?.businesses?.map((business : any) => {
187
+ return (
188
+ <SingleBusinessOffer key={business.id}>
189
+ {business?.logo ? (
190
+ <FastImage
191
+ style={styles.productStyle}
192
+ source={{
193
+ uri: optimizeImage(business?.logo, 'h_250,c_limit'),
194
+ priority: FastImage.priority.normal,
195
+ }}
196
+ resizeMode={FastImage.resizeMode.cover}
197
+ />
198
+ ) : (
199
+ <OIcon
200
+ src={theme?.images?.dummies?.product}
201
+ style={styles.productStyle}
202
+ />
203
+ )}
204
+ <BusinessInfo>
205
+ <OText>{business.name}</OText>
206
+ <OButton
207
+ onClick={() => handleBusinessClick(business)}
208
+ text={t('GO_TO_BUSINESSS', 'Go to business')}
209
+ style={styles.modalButtonStyle}
210
+ textStyle={{ fontSize: 10, color: '#fff' }}
211
+ />
212
+ </BusinessInfo>
213
+ </SingleBusinessOffer>
214
+ )
215
+ })}
216
+ </ScrollView>
217
+ </View>
218
+ </OModal>
219
+ </PromotionsContainer>
220
+ )
221
+ }
222
+
223
+ export const Promotions = (props : PromotionParams) => {
224
+ const PromotionsProps = {
225
+ ...props,
226
+ UIComponent: PromotionsUI
227
+ }
228
+
229
+ return (
230
+ <PromotionsController {...PromotionsProps} />
231
+ )
232
+ }
@@ -0,0 +1,80 @@
1
+ import styled, { css } from 'styled-components/native'
2
+
3
+ export const PromotionsContainer = styled.View`
4
+ width: 100%;
5
+ `
6
+
7
+ export const SingleOfferContainer = styled.View`
8
+ flex-direction: row;
9
+ width: 100%;
10
+ height: 80px;
11
+ justify-content: space-between;
12
+ align-items: center;
13
+ margin-bottom: 20px;
14
+
15
+ `
16
+
17
+ export const OfferInformation = styled.View`
18
+ justify-content: space-between;
19
+ max-width: 75%;
20
+ `
21
+
22
+ export const SearchBarContainer = styled.View`
23
+ display: flex;
24
+ width: 100%;
25
+ justify-content: flex-start;
26
+ margin-bottom: 20px;
27
+ .search-bar {
28
+ justify-content: flex-start;
29
+ input {
30
+ width: 100%;
31
+ }
32
+ }
33
+ .clear {
34
+ right: 0;
35
+ }
36
+ `
37
+
38
+ export const SingleBusinessOffer = styled.View`
39
+ flex-direction: row;
40
+ `
41
+
42
+ export const AvailableBusinesses = styled.View`
43
+ flex-direction: row;
44
+ overflow: hidden;
45
+ `
46
+
47
+ export const OfferData = styled.View`
48
+ display: flex;
49
+ align-items: center;
50
+ flex-direction: column;
51
+ p{
52
+ color: #909BA9;
53
+ margin: 3px;
54
+ font-size: 14px;
55
+ }
56
+ `
57
+
58
+ export const Code = styled.View`
59
+ display: flex;
60
+ flex-direction: column;
61
+ align-items: center;
62
+ margin-bottom: 10px;
63
+ `
64
+
65
+ export const ValueOfOffer = styled.View`
66
+ p{
67
+ font-size: 16px;
68
+ }
69
+ span{
70
+ font-size: 20px;
71
+ }
72
+ `
73
+
74
+ export const BusinessInfo = styled.View`
75
+ flex: 1;
76
+ flex-direction: row;
77
+ justify-content: space-between;
78
+ align-items: center;
79
+ margin-left: 10px;
80
+ `
@@ -1,11 +1,12 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
- import { View, Pressable, StyleSheet, Linking, Platform } from 'react-native';
2
+ import { View, Pressable, StyleSheet, Linking, Platform, TouchableOpacity } from 'react-native';
3
3
  import { useForm, Controller } from 'react-hook-form';
4
4
  import Spinner from 'react-native-loading-spinner-overlay';
5
5
  import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
6
6
  import CheckBox from '@react-native-community/checkbox';
7
7
  import { PhoneInputNumber } from '../PhoneInputNumber';
8
8
  import { FacebookLogin } from '../FacebookLogin';
9
+ import Recaptcha from 'react-native-recaptcha-that-works'
9
10
 
10
11
  import {
11
12
  SignupForm as SignUpController,
@@ -23,6 +24,7 @@ import {
23
24
  LoginWith as SignupWith,
24
25
  OTab,
25
26
  OTabs,
27
+ RecaptchaButton
26
28
  } from '../LoginForm/styles';
27
29
 
28
30
  import NavBar from '../NavBar';
@@ -63,7 +65,9 @@ const SignupFormUI = (props: SignupParams) => {
63
65
  handleSendVerifyCode,
64
66
  handleCheckPhoneCode,
65
67
  notificationState,
66
- handleChangePromotions
68
+ handleChangePromotions,
69
+ enableReCaptcha,
70
+ handleReCaptcha
67
71
  } = props;
68
72
 
69
73
  const theme = useTheme();
@@ -115,8 +119,11 @@ const SignupFormUI = (props: SignupParams) => {
115
119
  phone: {
116
120
  country_phone_code: null,
117
121
  cellphone: null,
122
+ country_code: null
118
123
  },
119
124
  });
125
+ const [recaptchaConfig, setRecaptchaConfig] = useState<any>({})
126
+ const [recaptchaVerified, setRecaptchaVerified] = useState(false)
120
127
 
121
128
  const nameRef = useRef<any>(null);
122
129
  const lastnameRef = useRef<any>(null);
@@ -125,8 +132,9 @@ const SignupFormUI = (props: SignupParams) => {
125
132
  const emailRef = useRef<any>(null);
126
133
  const phoneRef = useRef<any>(null);
127
134
  const passwordRef = useRef<any>(null);
135
+ const recaptchaRef = useRef<any>({});
128
136
 
129
- const showInputPhoneNumber = (validationFields?.fields?.checkout?.cellphone?.enabled ?? false) || configs?.verification_phone_required?.value === '1'
137
+ const showInputPhoneNumber = (validationFields?.fields?.checkout?.cellphone?.enabled ?? false) || configs?.verification_phone_required?.value === '1'
130
138
 
131
139
  const handleRefs = (ref: any, code: string) => {
132
140
  switch (code) {
@@ -209,8 +217,8 @@ const SignupFormUI = (props: SignupParams) => {
209
217
  !phoneInputData.phone.country_phone_code &&
210
218
  !phoneInputData.phone.cellphone &&
211
219
  ((validationFields?.fields?.checkout?.cellphone?.enabled &&
212
- validationFields?.fields?.checkout?.cellphone?.required) ||
213
- configs?.verification_phone_required?.value === '1')
220
+ validationFields?.fields?.checkout?.cellphone?.required) ||
221
+ configs?.verification_phone_required?.value === '1')
214
222
  ) {
215
223
  showToast(
216
224
  ToastType.Error,
@@ -225,7 +233,8 @@ const SignupFormUI = (props: SignupParams) => {
225
233
  handleButtonSignupClick &&
226
234
  handleButtonSignupClick({
227
235
  ...values,
228
- ...((phoneInputData.phone.cellphone !== null && phoneInputData.phone.country_phone_code !== null) && {...phoneInputData.phone}),
236
+ ...((phoneInputData.phone.cellphone !== null && phoneInputData.phone.country_phone_code !== null) && { ...phoneInputData.phone }),
237
+ country_code: phoneInputData.phone.country_code
229
238
  });
230
239
  if (
231
240
  !formState.loading &&
@@ -286,6 +295,33 @@ const SignupFormUI = (props: SignupParams) => {
286
295
  }
287
296
  }
288
297
 
298
+ const handleOpenRecaptcha = () => {
299
+ setRecaptchaVerified(false)
300
+ if (!recaptchaConfig?.siteKey) {
301
+ showToast(ToastType.Error, t('NO_RECAPTCHA_SITE_KEY', 'The config doesn\'t have recaptcha site key'));
302
+ return
303
+ }
304
+ if (!recaptchaConfig?.baseUrl) {
305
+ showToast(ToastType.Error, t('NO_RECAPTCHA_BASE_URL', 'The config doesn\'t have recaptcha base url'));
306
+ return
307
+ }
308
+ recaptchaRef.current.open()
309
+ }
310
+
311
+ const onRecaptchaVerify = (token: any) => {
312
+ setRecaptchaVerified(true)
313
+ handleReCaptcha(token)
314
+ }
315
+
316
+ useEffect(() => {
317
+ if (configs && Object.keys(configs).length > 0 && enableReCaptcha) {
318
+ setRecaptchaConfig({
319
+ siteKey: configs?.security_recaptcha_site_key?.value || null,
320
+ baseUrl: configs?.security_recaptcha_base_url?.value || null
321
+ })
322
+ }
323
+ }, [configs, enableReCaptcha])
324
+
289
325
  useEffect(() => {
290
326
  if (!formState.loading && formState.result?.error) {
291
327
  formState.result?.result &&
@@ -301,12 +337,12 @@ const SignupFormUI = (props: SignupParams) => {
301
337
  }, [errors]);
302
338
 
303
339
  useEffect(() => {
304
- register('cellphone', {
305
- required: isRequiredField('cellphone')
306
- ? t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Mobile phone is required').replace('_attribute_', t('CELLPHONE', 'Cellphone'))
307
- : null
308
- })
309
- }, [register])
340
+ register('cellphone', {
341
+ required: isRequiredField('cellphone')
342
+ ? t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Mobile phone is required').replace('_attribute_', t('CELLPHONE', 'Cellphone'))
343
+ : null
344
+ })
345
+ }, [register])
310
346
 
311
347
  useEffect(() => {
312
348
  if (phoneInputData?.phone?.cellphone) setValue('cellphone', phoneInputData?.phone?.cellphone, '')
@@ -333,6 +369,16 @@ const SignupFormUI = (props: SignupParams) => {
333
369
  }
334
370
  }, [verifyPhoneState]);
335
371
 
372
+ useEffect(() => {
373
+ setPhoneInputData({
374
+ ...phoneInputData,
375
+ phone: {
376
+ ...phoneInputData.phone,
377
+ country_code: configs?.default_country_code?.value
378
+ }
379
+ })
380
+ }, [configs])
381
+
336
382
  return (
337
383
  <View>
338
384
  <NavBar
@@ -456,8 +502,24 @@ const SignupFormUI = (props: SignupParams) => {
456
502
  <View style={{ marginBottom: 25 }}>
457
503
  <PhoneInputNumber
458
504
  data={phoneInputData}
459
- handleData={(val: any) => setPhoneInputData(val)}
505
+ handleData={(val: any) => setPhoneInputData({
506
+ ...phoneInputData,
507
+ ...val,
508
+ phone: {
509
+ ...phoneInputData.phone,
510
+ ...val.phone,
511
+ country_code: phoneInputData.phone.country_code
512
+ }
513
+ })}
460
514
  forwardRef={phoneRef}
515
+ defaultCode={formState?.country_code ?? formState?.country_phone_code ?? null}
516
+ changeCountry={(val: any) => setPhoneInputData({
517
+ ...phoneInputData,
518
+ phone: {
519
+ ...phoneInputData.phone,
520
+ country_code: val.cca2
521
+ }
522
+ })}
461
523
  textInputProps={{
462
524
  returnKeyType: 'next',
463
525
  onSubmitEditing: () => passwordRef?.current?.focus?.(),
@@ -467,6 +529,39 @@ const SignupFormUI = (props: SignupParams) => {
467
529
  </View>
468
530
  )}
469
531
 
532
+ {enableReCaptcha && (
533
+ <>
534
+ <TouchableOpacity
535
+ onPress={handleOpenRecaptcha}
536
+ style={{ marginHorizontal: 4, marginBottom: 10 }}
537
+ >
538
+ <RecaptchaButton>
539
+ {recaptchaVerified ? (
540
+ <MaterialCommunityIcons
541
+ name="checkbox-marked"
542
+ size={23}
543
+ color={theme.colors.primary}
544
+ />
545
+ ) : (
546
+ <MaterialCommunityIcons
547
+ name="checkbox-blank-outline"
548
+ size={23}
549
+ color={theme.colors.disabled}
550
+ />
551
+ )}
552
+ <OText size={14} mLeft={8}>{t('VERIFY_ReCAPTCHA', 'Verify reCAPTCHA')}</OText>
553
+ </RecaptchaButton>
554
+ </TouchableOpacity>
555
+ <Recaptcha
556
+ ref={recaptchaRef}
557
+ siteKey={recaptchaConfig?.siteKey}
558
+ baseUrl={recaptchaConfig?.baseUrl}
559
+ onVerify={onRecaptchaVerify}
560
+ onExpire={() => setRecaptchaVerified(false)}
561
+ />
562
+ </>
563
+ )}
564
+
470
565
  <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
471
566
  <Controller
472
567
  control={control}
@@ -736,6 +831,7 @@ const SignupFormUI = (props: SignupParams) => {
736
831
  export const SignupForm = (props: any) => {
737
832
  const signupProps = {
738
833
  ...props,
834
+ isRecaptchaEnable: true,
739
835
  UIComponent: SignupFormUI,
740
836
  };
741
837
  return <SignUpController {...signupProps} />;
@@ -7,10 +7,11 @@ import {
7
7
  } from 'ordering-components/native';
8
8
  import { useTheme } from 'styled-components/native';
9
9
  import { SingleProductCardParams } from '../../types';
10
- import { CardContainer, CardInfo, SoldOut, QuantityContainer, PricesContainer } from './styles';
10
+ import { CardContainer, CardInfo, SoldOut, QuantityContainer, PricesContainer, RibbonBox, LogoWrapper } from './styles';
11
11
  import { StyleSheet } from 'react-native';
12
12
  import { OText, OIcon } from '../shared';
13
13
  import FastImage from 'react-native-fast-image'
14
+ import { shape } from '../../utils';
14
15
 
15
16
  export const SingleProductCard = (props: SingleProductCardParams) => {
16
17
  const {
@@ -46,8 +47,7 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
46
47
  productStyle: {
47
48
  width: 75,
48
49
  height: 75,
49
- borderRadius: 7.6,
50
- marginStart: 12
50
+ borderRadius: 7.6
51
51
  },
52
52
  quantityContainer: {
53
53
  position: 'absolute',
@@ -136,21 +136,42 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
136
136
  {product?.description}
137
137
  </OText>
138
138
  </CardInfo>
139
- {product?.images ? (
140
- <FastImage
141
- style={styles.productStyle}
142
- source={{
143
- uri: optimizeImage(product?.images, 'h_250,c_limit'),
144
- priority: FastImage.priority.normal,
145
- }}
146
- resizeMode={FastImage.resizeMode.cover}
147
- />
148
- ) : (
149
- <OIcon
150
- src={theme?.images?.dummies?.product}
151
- style={styles.productStyle}
152
- />
153
- )}
139
+ <LogoWrapper>
140
+ {product?.ribbon?.enabled && (
141
+ <RibbonBox
142
+ bgColor={product?.ribbon?.color}
143
+ isRoundRect={product?.ribbon?.shape === shape?.rectangleRound}
144
+ isCapsule={product?.ribbon?.shape === shape?.capsuleShape}
145
+ >
146
+ <OText
147
+ size={10}
148
+ weight={'400'}
149
+ color={theme.colors.white}
150
+ numberOfLines={2}
151
+ ellipsizeMode='tail'
152
+ lineHeight={13}
153
+ >
154
+ {product?.ribbon?.text}
155
+ </OText>
156
+ </RibbonBox>
157
+ )}
158
+ {product?.images ? (
159
+ <FastImage
160
+ style={styles.productStyle}
161
+ source={{
162
+ uri: optimizeImage(product?.images, 'h_250,c_limit'),
163
+ priority: FastImage.priority.normal,
164
+ }}
165
+ resizeMode={FastImage.resizeMode.cover}
166
+ />
167
+ ) : (
168
+ <OIcon
169
+ src={theme?.images?.dummies?.product}
170
+ style={styles.productStyle}
171
+ />
172
+ )}
173
+ </LogoWrapper>
174
+
154
175
  {(isSoldOut || maxProductQuantity <= 0) && (
155
176
  <SoldOut>
156
177
  <OText size={12} weight="bold" color={theme.colors.textSecondary} style={styles.soldOutTextStyle}>
@@ -1,4 +1,4 @@
1
- import styled from 'styled-components/native'
1
+ import styled, { css } from 'styled-components/native'
2
2
 
3
3
  export const CardContainer = styled.TouchableOpacity`
4
4
  flex: 1;
@@ -31,3 +31,30 @@ export const PricesContainer = styled.View`
31
31
  flex-direction: row;
32
32
  align-items: center;
33
33
  `
34
+
35
+ export const LogoWrapper = styled.View`
36
+ position: relative;
37
+ margin-left: 12px;
38
+ `
39
+
40
+ export const RibbonBox = styled.View`
41
+ position: absolute;
42
+ z-index: 1;
43
+ top: -4px;
44
+ right: -4px;
45
+ background-color: ${(props: any) => props.theme.colors.primary};
46
+ padding: 1px 8px;
47
+ max-width: 60px;
48
+
49
+ ${(props: any) => props.bgColor && css`
50
+ background-color: ${props.bgColor};
51
+ `}
52
+
53
+ ${(props: any) => props.isRoundRect && css`
54
+ border-radius: 7.6px;
55
+ `}
56
+
57
+ ${(props: any) => props.isCapsule && css`
58
+ border-radius: 50px;
59
+ `}
60
+ `
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { useLanguage } from 'ordering-components/native'
2
+ import { useLanguage, useUtils } from 'ordering-components/native'
3
3
  import { SingleProductCard } from '../SingleProductCard'
4
4
  import { TaxInformationContainer, ProductContainer } from './styles'
5
5
  import { OText } from '../shared'
@@ -13,8 +13,9 @@ interface taxInformationParams {
13
13
  fixed?: number,
14
14
  percentage?: number,
15
15
  id: number,
16
- discounts?: any
17
- } | null,
16
+ discounts?: any,
17
+ rate_type?: number
18
+ },
18
19
  products: Array<any>,
19
20
  type: string
20
21
  }
@@ -27,6 +28,7 @@ export const TaxInformation = (props: taxInformationParams) => {
27
28
  } = props
28
29
 
29
30
  const [, t] = useLanguage()
31
+ const [{ parsePrice }] = useUtils()
30
32
 
31
33
  const includedOnPriceString = data?.type === 1 ? `(${t('INCLUDED_ON_PRICE', 'Included on price')})` : `(${t('NOT_INCLUDED_ON_PRICE', 'Not included on price')})`
32
34
  const offersHideArray = ['offer_target_2', 'offer_target_3']
@@ -56,8 +58,12 @@ export const TaxInformation = (props: taxInformationParams) => {
56
58
 
57
59
  return (
58
60
  <TaxInformationContainer>
61
+ <OText size={24} style={{ alignSelf: 'center', textAlign: 'center' }} mBottom={10}>
62
+ {`${data?.name ||
63
+ t('INHERIT_FROM_BUSINESS', 'Inherit from business')} ${data?.rate_type !== 2 ? `(${typeof data?.rate === 'number' ? `${data?.rate}%` : `${parsePrice(data?.fixed ?? 0)} + ${data?.percentage}%`})` : ''} `}
64
+ </OText>
59
65
  {!!data?.description ? (
60
- <OText size={24} style={{ alignSelf: 'center', textAlign: 'center' }} mBottom={10}>
66
+ <OText size={20} style={{ alignSelf: 'center', textAlign: 'center' }} mBottom={10}>
61
67
  {t('DESCRIPTION', 'Description')}: {data?.description} {data?.type && !type?.includes('offer') && includedOnPriceString}
62
68
  </OText>
63
69
  ) : (