ordering-ui-react-native 0.15.31 → 0.15.33-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 (178) hide show
  1. package/package.json +4 -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/LoginForm/index.tsx +3 -1
  10. package/src/components/OrderDetails/index.tsx +2 -2
  11. package/src/components/PaymentOptions/index.tsx +9 -16
  12. package/src/components/PaymentOptionsWebView/index.tsx +123 -124
  13. package/src/components/SignupForm/index.tsx +3 -1
  14. package/src/components/SingleProductCard/index.tsx +16 -4
  15. package/src/components/StripeElementsForm/index.tsx +27 -48
  16. package/src/components/UpsellingProducts/index.tsx +1 -1
  17. package/src/components/UserProfileForm/index.tsx +63 -6
  18. package/src/components/UserProfileForm/styles.tsx +8 -0
  19. package/src/components/VerifyPhone/styles.tsx +1 -2
  20. package/src/components/shared/OModal.tsx +1 -1
  21. package/src/config.json +0 -2
  22. package/src/hooks/useCountdownTimer.tsx +26 -0
  23. package/src/navigators/HomeNavigator.tsx +6 -0
  24. package/src/pages/BusinessProductsList.tsx +1 -0
  25. package/src/pages/BusinessesListing.tsx +1 -1
  26. package/src/pages/Checkout.tsx +1 -1
  27. package/src/pages/Sessions.tsx +22 -0
  28. package/src/types/index.tsx +5 -11
  29. package/src/utils/index.tsx +68 -1
  30. package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +103 -15
  31. package/themes/business/src/components/AcceptOrRejectOrder/styles.tsx +6 -0
  32. package/themes/business/src/components/Chat/index.tsx +38 -86
  33. package/themes/business/src/components/DriverMap/index.tsx +6 -5
  34. package/themes/business/src/components/Home/index.tsx +128 -55
  35. package/themes/business/src/components/Home/styles.tsx +8 -1
  36. package/themes/business/src/components/LoginForm/index.tsx +89 -2
  37. package/themes/business/src/components/LoginForm/styles.tsx +6 -0
  38. package/themes/business/src/components/LogoutButton/index.tsx +1 -1
  39. package/themes/business/src/components/NewOrderNotification/index.tsx +79 -105
  40. package/themes/business/src/components/OrderDetails/Business.tsx +1 -1
  41. package/themes/business/src/components/OrderDetails/Delivery.tsx +32 -15
  42. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +157 -89
  43. package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +6 -0
  44. package/themes/business/src/components/OrderDetails/styles.tsx +7 -0
  45. package/themes/business/src/components/OrdersListManager/index.tsx +52 -49
  46. package/themes/business/src/components/OrdersOption/index.tsx +57 -50
  47. package/themes/business/src/components/PreviousOrders/index.tsx +50 -14
  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/Checkout/index.tsx +34 -22
  60. package/themes/kiosk/src/components/CustomerName/index.tsx +7 -8
  61. package/themes/kiosk/src/components/Intro/index.tsx +13 -13
  62. package/themes/kiosk/src/components/NavBar/index.tsx +14 -14
  63. package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
  64. package/themes/kiosk/src/components/OrderDetails/index.tsx +167 -67
  65. package/themes/kiosk/src/components/OrderDetails/styles.tsx +5 -0
  66. package/themes/kiosk/src/components/OrderSummary/index.tsx +1 -1
  67. package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +10 -12
  68. package/themes/kiosk/src/components/PaymentOptions/index.tsx +1 -1
  69. package/themes/kiosk/src/components/ProductForm/index.tsx +174 -125
  70. package/themes/kiosk/src/components/ProductForm/styles.tsx +1 -1
  71. package/themes/kiosk/src/components/ProductOption/index.tsx +1 -0
  72. package/themes/kiosk/src/components/ProductOption/styles.tsx +1 -0
  73. package/themes/kiosk/src/components/UpsellingProducts/index.tsx +48 -34
  74. package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
  75. package/themes/kiosk/src/types/index.d.ts +2 -0
  76. package/themes/original/index.tsx +184 -1
  77. package/themes/original/src/components/ActiveOrders/index.tsx +15 -132
  78. package/themes/original/src/components/ActiveOrders/styles.tsx +0 -54
  79. package/themes/original/src/components/AddressForm/index.tsx +15 -10
  80. package/themes/original/src/components/AddressList/index.tsx +56 -18
  81. package/themes/original/src/components/AppleLogin/index.tsx +117 -78
  82. package/themes/original/src/components/BusinessBasicInformation/index.tsx +96 -45
  83. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +28 -1
  84. package/themes/original/src/components/BusinessController/index.tsx +77 -29
  85. package/themes/original/src/components/BusinessController/styles.tsx +27 -0
  86. package/themes/original/src/components/BusinessFeaturedController/index.tsx +20 -1
  87. package/themes/original/src/components/BusinessFeaturedController/styles.tsx +23 -0
  88. package/themes/original/src/components/BusinessListingSearch/index.tsx +125 -7
  89. package/themes/original/src/components/BusinessListingSearch/styles.tsx +14 -1
  90. package/themes/original/src/components/BusinessMenuList/index.tsx +11 -4
  91. package/themes/original/src/components/BusinessPreorder/index.tsx +142 -122
  92. package/themes/original/src/components/BusinessProductsCategories/index.tsx +9 -7
  93. package/themes/original/src/components/BusinessProductsList/CategoryDescription/index.tsx +44 -0
  94. package/themes/original/src/components/BusinessProductsList/index.tsx +140 -37
  95. package/themes/original/src/components/BusinessProductsList/styles.tsx +29 -2
  96. package/themes/original/src/components/BusinessProductsListing/index.tsx +112 -14
  97. package/themes/original/src/components/BusinessProductsListing/styles.tsx +22 -0
  98. package/themes/original/src/components/BusinessReviews/index.tsx +4 -25
  99. package/themes/original/src/components/BusinessTypeFilter/index.tsx +1 -2
  100. package/themes/original/src/components/BusinessesListing/index.tsx +98 -72
  101. package/themes/original/src/components/Cart/index.tsx +21 -17
  102. package/themes/original/src/components/CartContent/index.tsx +2 -2
  103. package/themes/original/src/components/Checkout/index.tsx +59 -48
  104. package/themes/original/src/components/DriverTips/index.tsx +17 -12
  105. package/themes/original/src/components/Favorite/index.tsx +91 -0
  106. package/themes/original/src/components/Favorite/styles.tsx +22 -0
  107. package/themes/original/src/components/FavoriteList/index.tsx +287 -0
  108. package/themes/original/src/components/FavoriteList/styles.tsx +5 -0
  109. package/themes/original/src/components/ForgotPasswordForm/index.tsx +84 -4
  110. package/themes/original/src/components/GPSButton/index.tsx +15 -8
  111. package/themes/original/src/components/GoogleMap/index.tsx +1 -0
  112. package/themes/original/src/components/Help/index.tsx +21 -4
  113. package/themes/original/src/components/HighestRatedBusinesses/index.tsx +115 -90
  114. package/themes/original/src/components/Home/index.tsx +1 -1
  115. package/themes/original/src/components/LastOrders/index.tsx +12 -1
  116. package/themes/original/src/components/LoginForm/Otp/index.tsx +90 -0
  117. package/themes/original/src/components/LoginForm/Otp/styles.tsx +7 -0
  118. package/themes/original/src/components/LoginForm/index.tsx +394 -155
  119. package/themes/original/src/components/LoginForm/styles.tsx +7 -4
  120. package/themes/original/src/components/LogoutButton/index.tsx +7 -1
  121. package/themes/original/src/components/MessageListing/index.tsx +10 -1
  122. package/themes/original/src/components/Messages/index.tsx +34 -25
  123. package/themes/original/src/components/Messages/styles.tsx +1 -3
  124. package/themes/original/src/components/MomentOption/index.tsx +10 -1
  125. package/themes/original/src/components/MomentOption/styles.tsx +1 -1
  126. package/themes/original/src/components/OrderDetails/index.tsx +56 -33
  127. package/themes/original/src/components/OrderDetails/styles.tsx +1 -2
  128. package/themes/original/src/components/OrderProgress/index.tsx +4 -4
  129. package/themes/original/src/components/OrderProgress/styles.tsx +1 -0
  130. package/themes/original/src/components/OrderSummary/index.tsx +3 -3
  131. package/themes/original/src/components/OrderTypeSelector/index.tsx +4 -2
  132. package/themes/original/src/components/OrdersOption/index.tsx +59 -58
  133. package/themes/original/src/components/OrdersOption/styles.tsx +0 -6
  134. package/themes/original/src/components/PaymentOptionCash/index.tsx +2 -2
  135. package/themes/original/src/components/PaymentOptionWallet/index.tsx +22 -24
  136. package/themes/original/src/components/PaymentOptionWallet/styles.tsx +1 -1
  137. package/themes/original/src/components/PaymentOptions/index.tsx +9 -21
  138. package/themes/original/src/components/PhoneInputNumber/index.tsx +1 -1
  139. package/themes/original/src/components/PreviousOrders/index.tsx +18 -145
  140. package/themes/original/src/components/ProductForm/index.tsx +76 -61
  141. package/themes/original/src/components/ProductForm/styles.tsx +2 -2
  142. package/themes/original/src/components/ProductItemAccordion/index.tsx +2 -2
  143. package/themes/original/src/components/ProductOptionSubOption/index.tsx +18 -12
  144. package/themes/original/src/components/Promotions/index.tsx +250 -0
  145. package/themes/original/src/components/Promotions/styles.tsx +60 -0
  146. package/themes/original/src/components/ReviewOrder/index.tsx +10 -9
  147. package/themes/original/src/components/ReviewProducts/index.tsx +1 -1
  148. package/themes/original/src/components/SearchBar/index.tsx +4 -1
  149. package/themes/original/src/components/Sessions/index.tsx +160 -0
  150. package/themes/original/src/components/Sessions/styles.tsx +15 -0
  151. package/themes/original/src/components/SignupForm/index.tsx +9 -4
  152. package/themes/original/src/components/SingleOrderCard/index.tsx +282 -0
  153. package/themes/original/src/components/SingleOrderCard/styles.tsx +54 -0
  154. package/themes/original/src/components/SingleProductCard/index.tsx +82 -30
  155. package/themes/original/src/components/SingleProductCard/styles.tsx +28 -1
  156. package/themes/original/src/components/StripeElementsForm/index.tsx +55 -74
  157. package/themes/original/src/components/TaxInformation/index.tsx +10 -4
  158. package/themes/original/src/components/UpsellingProducts/index.tsx +86 -74
  159. package/themes/original/src/components/UserDetails/index.tsx +4 -95
  160. package/themes/original/src/components/UserFormDetails/index.tsx +34 -24
  161. package/themes/original/src/components/UserProfile/index.tsx +66 -14
  162. package/themes/original/src/components/UserProfileForm/index.tsx +20 -18
  163. package/themes/original/src/components/UserVerification/index.tsx +178 -192
  164. package/themes/original/src/components/VerifyPhone/index.tsx +10 -7
  165. package/themes/original/src/components/VerifyPhone/styles.tsx +2 -1
  166. package/themes/original/src/components/Wallets/index.tsx +76 -9
  167. package/themes/original/src/components/Wallets/styles.tsx +21 -0
  168. package/themes/original/src/components/shared/HeaderTitle.tsx +21 -0
  169. package/themes/original/src/components/shared/OModal.tsx +4 -2
  170. package/themes/original/src/components/shared/index.tsx +2 -0
  171. package/themes/original/src/config/constants.tsx +6 -6
  172. package/themes/original/src/types/index.tsx +115 -9
  173. package/themes/original/src/utils/index.tsx +28 -2
  174. package/themes/single-business/src/components/AddressList/index.tsx +1 -1
  175. package/themes/single-business/src/components/OrderTypeSelector/index.tsx +6 -6
  176. package/themes/single-business/src/components/UserProfile/index.tsx +1 -1
  177. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
  178. package/src/components/StripeMethodForm/index.tsx +0 -174
@@ -46,7 +46,6 @@ import { ProductOptionSubOption } from '../ProductOptionSubOption';
46
46
  import { NotFoundSource } from '../NotFoundSource';
47
47
  import { Placeholder, PlaceholderLine, Fade } from 'rn-placeholder';
48
48
  import { useState } from 'react';
49
-
50
49
  const windowHeight = Dimensions.get('window').height;
51
50
  const windowWidth = Dimensions.get('window').width;
52
51
 
@@ -176,6 +175,7 @@ export const ProductOptionsUI = (props: any) => {
176
175
  const [optionLayout, setOptionLayout] = useState<any>({})
177
176
  const [headerRefHeight, setHeaderRefHeight] = useState(0)
178
177
  const [summaryRefHeight, setSummaryRefHeight] = useState(0)
178
+ const [isScrollAvailable, setIsScrollAvailable] = useState(null)
179
179
 
180
180
  const isError = (id: number) => {
181
181
  let bgColor = theme.colors.white;
@@ -279,39 +279,6 @@ export const ProductOptionsUI = (props: any) => {
279
279
  setOptionLayout(_optionLayout)
280
280
  }
281
281
 
282
- useEffect(() => {
283
- const imageList: any = []
284
- const videoList: any = []
285
- product?.images && imageList.push(product.images)
286
- if (product?.gallery && product?.gallery.length > 0) {
287
- for (const img of product?.gallery) {
288
- if (img?.file) {
289
- imageList.push(img?.file)
290
- }
291
- if (img?.video) {
292
- const keys = img?.video.split('/')
293
- let _videoId = keys[keys.length - 1]
294
- if (_videoId.includes('watch')) {
295
- const __url = _videoId.split('=')[1]
296
- _videoId = __url
297
- }
298
- if (_videoId.includes('?')) {
299
- const __url = _videoId.split('?')[0]
300
- _videoId = __url
301
- }
302
- videoList.push(_videoId)
303
- }
304
- }
305
- }
306
- const gallery = imageList.concat(videoList)
307
- setGallery(gallery)
308
-
309
- if (product?.weight && product?.weight_unit) {
310
- setIsHaveWeight(true)
311
- setPricePerWeightUnit(product?.price / product?.weight)
312
- }
313
- }, [product])
314
-
315
282
  const saveErrors =
316
283
  orderState.loading ||
317
284
  maxProductQuantity === 0 ||
@@ -319,28 +286,9 @@ export const ProductOptionsUI = (props: any) => {
319
286
 
320
287
  const ExtraOptions = ({ eID, options }: any) => (
321
288
  <>
322
- {product?.ingredients.length > 0 && (
323
- <TouchableOpacity
324
- key={`eopt_all_00`}
325
- onPress={() => setSelectedOpt(-1)}
326
- style={[
327
- styles.extraItem,
328
- {
329
- borderBottomColor:
330
- selOpt == -1 ? theme.colors.textNormal : theme.colors.border,
331
- },
332
- ]}>
333
- <OText
334
- color={selOpt == -1 ? theme.colors.textNormal : theme.colors.textSecondary}
335
- size={selOpt == -1 ? 14 : 12}
336
- weight={selOpt == -1 ? '600' : 'normal'}>
337
- {t('INGREDIENTS', 'Ingredients')}
338
- </OText>
339
- </TouchableOpacity>
340
- )}
341
- {options.map(({ id, name, respect_to }: any) => (
289
+ {options.map(({ id, name, respect_to, suboptions }: any) => (
342
290
  <React.Fragment key={`cont_key_${id}`}>
343
- {respect_to == null && (
291
+ {respect_to == null && suboptions?.length > 0 && (
344
292
  <TouchableOpacity
345
293
  key={`eopt_key_${id}`}
346
294
  onPress={() => setSelectedOpt(id)}
@@ -370,6 +318,54 @@ export const ProductOptionsUI = (props: any) => {
370
318
  ? () => navigation.goBack()
371
319
  : () => navigation.navigate('Business', { store: props.businessSlug })
372
320
 
321
+ useEffect(() => {
322
+ if (isScrollAvailable) {
323
+ setIsScrollAvailable(null)
324
+ scrollDown(isScrollAvailable)
325
+ }
326
+ }, [errors])
327
+
328
+ useEffect(() => {
329
+ const imageList: any = []
330
+ const videoList: any = []
331
+ product?.images && imageList.push(product.images)
332
+ if (product?.gallery && product?.gallery.length > 0) {
333
+ for (const img of product?.gallery) {
334
+ if (img?.file) {
335
+ imageList.push(img?.file)
336
+ }
337
+ if (img?.video) {
338
+ const keys = img?.video.split('/')
339
+ let _videoId = keys[keys.length - 1]
340
+
341
+ if (_videoId.includes('watch')) {
342
+ const __url = _videoId.split('=')[1]
343
+ _videoId = __url
344
+ } else if (_videoId.includes('?')) {
345
+ const __url = _videoId.split('?')[0]
346
+ _videoId = __url
347
+ }
348
+
349
+ if (_videoId.search(/&/i) >= 0) {
350
+ _videoId = _videoId.split('&')[0]
351
+ } else if (_videoId.search(/\?/i) >= 0) {
352
+ _videoId = _videoId.split('?')[0]
353
+ }
354
+ if ((_videoId.length === 11)) {
355
+ videoList.push(_videoId)
356
+ }
357
+ }
358
+ }
359
+ }
360
+ const gallery = imageList.concat(videoList)
361
+ setGallery(gallery)
362
+
363
+ if (product?.weight && product?.weight_unit) {
364
+ setIsHaveWeight(true)
365
+ setPricePerWeightUnit(product?.price / product?.weight)
366
+ }
367
+ }, [product])
368
+
373
369
  return (
374
370
  <SafeAreaView style={{ flex: 1 }}>
375
371
  <TopHeader>
@@ -658,6 +654,25 @@ export const ProductOptionsUI = (props: any) => {
658
654
  {t('ALL', 'All')}
659
655
  </OText>
660
656
  </TouchableOpacity>
657
+ {product?.ingredients.length > 0 && (
658
+ <TouchableOpacity
659
+ key={`eopt_all_00`}
660
+ onPress={() => setSelectedOpt(-1)}
661
+ style={[
662
+ styles.extraItem,
663
+ {
664
+ borderBottomColor:
665
+ selOpt == -1 ? theme.colors.textNormal : theme.colors.border,
666
+ },
667
+ ]}>
668
+ <OText
669
+ color={selOpt == -1 ? theme.colors.textNormal : theme.colors.textSecondary}
670
+ size={selOpt == -1 ? 14 : 12}
671
+ weight={selOpt == -1 ? '600' : 'normal'}>
672
+ {t('INGREDIENTS', 'Ingredients')}
673
+ </OText>
674
+ </TouchableOpacity>
675
+ )}
661
676
  {product?.extras.map((extra: any) =>
662
677
  <ExtraOptions key={extra.id} options={extra.options} />
663
678
  )}
@@ -687,8 +702,8 @@ export const ProductOptionsUI = (props: any) => {
687
702
  </WrapperIngredients>
688
703
  </View>
689
704
  )}
690
- {product?.extras.map((extra: any) =>
691
- extra.options.map((option: any) => {
705
+ {product?.extras.sort((a: any, b: any) => a.rank - b.rank).map((extra: any) =>
706
+ extra.options.sort((a: any, b: any) => a.rank - b.rank).map((option: any) => {
692
707
  const currentState =
693
708
  productCart.options[`id:${option.id}`] || {};
694
709
  return (
@@ -704,7 +719,7 @@ export const ProductOptionsUI = (props: any) => {
704
719
  backgroundColor: isError(option.id),
705
720
  borderRadius: 7.6
706
721
  }}>
707
- {option.suboptions.map(
722
+ {option.suboptions.sort((a: any, b: any) => a.rank - b.rank).map(
708
723
  (suboption: any) => {
709
724
  const currentState =
710
725
  productCart.options[
@@ -731,7 +746,7 @@ export const ProductOptionsUI = (props: any) => {
731
746
  isSoldOut ||
732
747
  maxProductQuantity <= 0
733
748
  }
734
- scrollDown={scrollDown}
749
+ setIsScrollAvailable={setIsScrollAvailable}
735
750
  error={errors[`id:${option.id}`]}
736
751
  />
737
752
  );
@@ -772,7 +787,7 @@ export const ProductOptionsUI = (props: any) => {
772
787
  ) : (
773
788
  <>
774
789
  {product?.extras.map((extra: any) =>
775
- extra.options.map((option: any) => {
790
+ extra.options.sort((a: any, b: any) => a.rank - b.rank).map((option: any) => {
776
791
  if (
777
792
  option.id == selOpt ||
778
793
  (hasRespected(
@@ -797,7 +812,7 @@ export const ProductOptionsUI = (props: any) => {
797
812
  option.id,
798
813
  ),
799
814
  }}>
800
- {option.suboptions.map(
815
+ {option.suboptions.sort((a: any, b: any) => a.rank - b.rank).map(
801
816
  (suboption: any) => {
802
817
  const currentState =
803
818
  productCart.options[
@@ -6,9 +6,10 @@ export const WrapHeader = styled.View`
6
6
  `
7
7
 
8
8
  export const TopActions = styled.TouchableOpacity`
9
- height: 44px;
9
+ height: 60px;
10
10
  justify-content: center;
11
11
  padding-horizontal: 30px;
12
+ width: 80px;
12
13
  `;
13
14
 
14
15
  export const TopHeader = styled.View`
@@ -48,7 +49,6 @@ export const ProductDescription = styled.View`
48
49
  `
49
50
 
50
51
  export const ProductEditions = styled.View`
51
-
52
52
  `
53
53
 
54
54
  export const SectionTitle = styled.View`
@@ -40,7 +40,7 @@ export const ProductItemAccordion = (props: ProductItemAccordionParams) => {
40
40
 
41
41
  const pickerStyle = StyleSheet.create({
42
42
  inputAndroid: {
43
- width: 27,
43
+ width: 34,
44
44
  textAlign: 'center',
45
45
  overflow: 'visible',
46
46
  fontSize: 12,
@@ -49,7 +49,7 @@ export const ProductItemAccordion = (props: ProductItemAccordionParams) => {
49
49
  color: theme.colors.textNormal
50
50
  },
51
51
  inputIOS: {
52
- width: 27,
52
+ width: 34,
53
53
  textAlign: 'center',
54
54
  overflow: 'visible',
55
55
  fontSize: 12,
@@ -28,36 +28,40 @@ export const ProductOptionSubOptionUI = (props: any) => {
28
28
  toggleSelect,
29
29
  changePosition,
30
30
  disabled,
31
- error,
32
- scrollDown
31
+ setIsScrollAvailable
33
32
  } = props
34
33
 
34
+ const disableIncrement = option?.limit_suboptions_by_max ? balance === option?.max : state.quantity === suboption?.max || (!state.selected && balance === option?.max)
35
+ const price = option?.with_half_option && suboption?.half_price && state.position !== 'whole' ? suboption?.half_price : suboption?.price
36
+
35
37
  const theme = useTheme();
36
-
37
38
  const [, t] = useLanguage()
38
39
  const [{ parsePrice }] = useUtils()
39
40
  const [showMessage, setShowMessage] = useState(false)
41
+ const [isDirty, setIsDirty] = useState(false)
40
42
 
41
43
  const handleSuboptionClick = () => {
42
44
  toggleSelect()
43
-
44
- if (balance === option?.max - 1 && !state.selected) {
45
- scrollDown(option?.id)
46
- }
45
+ setIsDirty(true)
47
46
 
48
47
  if (balance === option?.max && option?.suboptions?.length > balance && !(option?.min === 1 && option?.max === 1)) {
49
48
  setShowMessage(true)
50
49
  }
51
50
  }
52
51
 
52
+ useEffect(() => {
53
+ if (balance === option?.max && state?.selected && isDirty) {
54
+ setIsDirty(false)
55
+ setIsScrollAvailable(option?.id)
56
+ }
57
+ }, [state?.selected])
58
+
53
59
  useEffect(() => {
54
60
  if (!(balance === option?.max && option?.suboptions?.length > balance && !(option?.min === 1 && option?.max === 1))) {
55
61
  setShowMessage(false)
56
62
  }
57
63
  }, [balance])
58
64
 
59
- const disableIncrement = option?.limit_suboptions_by_max ? balance === option?.max : state.quantity === suboption?.max || (!state.selected && balance === option?.max)
60
- const price = option?.with_half_option && suboption?.half_price && state.position !== 'whole' ? suboption?.half_price : suboption?.price
61
65
  return (
62
66
  <View>
63
67
  <Container onPress={() => handleSuboptionClick()}>
@@ -130,9 +134,11 @@ export const ProductOptionSubOptionUI = (props: any) => {
130
134
  </>
131
135
  )}
132
136
  </PositionControl>
133
- <OText size={12} lineHeight={18} color={theme.colors.textSecondary}>
134
- + {parsePrice(price)}
135
- </OText>
137
+ {price > 0 && (
138
+ <OText size={12} lineHeight={18} color={theme.colors.textSecondary}>
139
+ + {parsePrice(price)}
140
+ </OText>
141
+ )}
136
142
  </Container>
137
143
  {showMessage && <OText size={10} mLeft={4} mRight={4} style={{ flex: 1, textAlign: 'center' }} color={theme.colors.primary}>{`${t('OPTIONS_MAX_LIMIT', 'Maximum options to choose')}: ${option?.max}`}</OText>}
138
144
  </View>
@@ -0,0 +1,250 @@
1
+ import React, { useState } from 'react'
2
+ import { PromotionsController, useLanguage, useUtils } 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, Platform, RefreshControl } from 'react-native'
21
+ import FastImage from 'react-native-fast-image'
22
+ import { PromotionParams } from '../../types'
23
+ import { Container } from '../../layouts/Container'
24
+
25
+ const PromotionsUI = (props: PromotionParams) => {
26
+ const {
27
+ navigation,
28
+ offersState,
29
+ handleSearchValue,
30
+ searchValue,
31
+ loadOffers,
32
+ offerSelected,
33
+ setOfferSelected
34
+ } = props
35
+
36
+ const theme = useTheme();
37
+
38
+ const styles = StyleSheet.create({
39
+ productStyle: {
40
+ width: 75,
41
+ height: 75,
42
+ borderRadius: 7.6
43
+ },
44
+ buttonStyle: {
45
+ width: 55,
46
+ height: 25,
47
+ paddingLeft: 0,
48
+ paddingRight: 0
49
+ },
50
+ offerTitle: {
51
+ fontSize: 12
52
+ },
53
+ offerDescription: {
54
+ color: '#909BA9',
55
+ fontSize: 10
56
+ },
57
+ offerExtraInfo: {
58
+ fontSize: 10
59
+ },
60
+ modalButtonStyle: {
61
+ width: 100,
62
+ height: 35,
63
+ paddingLeft: 0,
64
+ paddingRight: 0,
65
+ borderRadius: 7.6
66
+ }
67
+ });
68
+
69
+ const [, t] = useLanguage()
70
+ const [{ parseDate, parsePrice, optimizeImage }] = useUtils()
71
+ const [openModal, setOpenModal] = useState(false)
72
+ const [refreshing] = useState(false);
73
+
74
+ const handleClickOffer = (offer: any) => {
75
+ setOpenModal(true)
76
+ setOfferSelected(offer)
77
+ }
78
+
79
+ const handleBusinessClick = (store: any) => {
80
+ setOpenModal(false)
81
+ navigation.navigate('Business', { store: store.slug })
82
+ }
83
+
84
+ const handleOnRefresh = () => {
85
+ if (!offersState.loading) {
86
+ loadOffers();
87
+ }
88
+ }
89
+
90
+ const filteredOffers = offersState?.offers?.filter((offer: any) => offer.name.toLowerCase().includes(searchValue.toLowerCase()))
91
+ const targetString = offerSelected?.target === 1
92
+ ? t('SUBTOTAL', 'Subtotal')
93
+ : offerSelected?.target === 2
94
+ ? t('DELIVERY_FEE', 'Delivery fee')
95
+ : t('SERVICE_FEE', 'Service fee')
96
+
97
+ return (
98
+ <Container
99
+ noPadding
100
+ refreshControl={
101
+ <RefreshControl
102
+ refreshing={refreshing}
103
+ onRefresh={() => handleOnRefresh()}
104
+ />
105
+ }
106
+ >
107
+ <NavBar
108
+ title={t('PROMOTIONS', 'Promotions')}
109
+ titleAlign={'center'}
110
+ onActionLeft={() => navigation.goBack()}
111
+ showCall={false}
112
+ style={{ paddingVertical: Platform.OS === 'ios' ? 0 : 20, marginLeft: 20 }}
113
+ />
114
+ <PromotionsContainer>
115
+ <SearchBarContainer>
116
+ <SearchBar
117
+ placeholder={t('SEARCH_OFFERS', 'Search offers')}
118
+ onSearch={handleSearchValue}
119
+ />
120
+ </SearchBarContainer>
121
+
122
+ {offersState?.loading && (
123
+ <>
124
+ {[...Array(5).keys()].map((key, i) => (
125
+ <Placeholder key={i} style={{ flexDirection: 'row', marginBottom: 20 }}>
126
+ <PlaceholderLine height={10} width={45} />
127
+ <PlaceholderLine height={10} width={60} />
128
+ <PlaceholderLine height={10} width={75} />
129
+ </Placeholder>
130
+ ))}
131
+ </>
132
+ )}
133
+ {((!offersState?.loading && filteredOffers?.length === 0) || offersState?.error) && (
134
+ <NotFoundSource
135
+ content={offersState?.error || t('NOT_FOUND_OFFERS', 'Not found offers')}
136
+ />
137
+ )}
138
+ <ScrollView>
139
+ {!offersState?.loading && offersState.offers?.length > 0 && filteredOffers?.map((offer: any) => (
140
+ <SingleOfferContainer key={offer.id}>
141
+ <OfferInformation>
142
+ <OText style={styles.offerTitle} numberOfLines={2}>{offer?.name}</OText>
143
+ {!!offer?.description && (
144
+ <OText style={styles.offerDescription} numberOfLines={2}>{offer?.description}</OText>
145
+ )}
146
+ <OText style={styles.offerExtraInfo}>
147
+ {t('EXPIRES', 'Expires')} {parseDate(offer?.end, { outputFormat: 'MMM DD, YYYY' })}
148
+ </OText>
149
+ <AvailableBusinesses>
150
+ <OText style={styles.offerExtraInfo} numberOfLines={1}>
151
+ {t('APPLY_FOR', 'Apply for')}:
152
+ {offer.businesses.map((business: any, i: number) => (
153
+ <React.Fragment key={i}>{' '}{business?.name}{i + 1 < offer.businesses?.length ? ',' : ''}</React.Fragment>
154
+ ))}
155
+ </OText>
156
+ </AvailableBusinesses>
157
+ </OfferInformation>
158
+ <OButton
159
+ onClick={() => handleClickOffer(offer)}
160
+ text={t('VIEW', 'View')}
161
+ style={styles.buttonStyle}
162
+ textStyle={{ fontSize: 10, color: '#fff', flexWrap: 'nowrap' }}
163
+ />
164
+ </SingleOfferContainer>
165
+ ))}
166
+ </ScrollView>
167
+ <OModal
168
+ open={openModal}
169
+ onClose={() => setOpenModal(false)}
170
+ entireModal
171
+
172
+ title={``}
173
+ >
174
+ <View style={{ padding: 20 }}>
175
+ <OText style={{ alignSelf: 'center', fontWeight: '700' }} mBottom={20}>
176
+ {offerSelected?.name} / {t('VALUE_OF_OFFER', 'Value of offer')}: {offerSelected?.rate_type === 1 ? `${offerSelected?.rate}%` : `${parsePrice(offerSelected?.rate)}`}
177
+ </OText>
178
+ <OfferData>
179
+ {offerSelected?.type === 2 && (
180
+ <Code>
181
+ <OText>{t('YOUR_CODE', 'Your code')}</OText>
182
+ <OText color={theme.colors.primary}>{offerSelected.coupon}</OText>
183
+ </Code>
184
+ )}
185
+ <OText>{t('APPLIES_TO', 'Applies to')}: {targetString}</OText>
186
+ {offerSelected?.auto && (
187
+ <OText>{t('OFFER_AUTOMATIC', 'This offer applies automatic')}</OText>
188
+ )}
189
+ {!!offerSelected?.minimum && (
190
+ <OText>{t('MINIMUM_PURCHASE_FOR_OFFER', 'Minimum purchase for use this offer')}: {parsePrice(offerSelected?.minimum)}</OText>
191
+ )}
192
+ {!!offerSelected?.max_discount && (
193
+ <OText>{t('MAX_DISCOUNT_ALLOWED', 'Max discount allowed')}: {parsePrice(offerSelected?.max_discount)}</OText>
194
+ )}
195
+ {!!offerSelected?.description && (
196
+ <OText>{offerSelected?.description}</OText>
197
+ )}
198
+ </OfferData>
199
+ <OText style={{ marginTop: 10, marginBottom: 10 }}>
200
+ {t('AVAILABLE_BUSINESSES_FOR_OFFER', 'Available businesses for this offer')}:
201
+ </OText>
202
+ <ScrollView style={{ height: '75%' }}>
203
+ {offerSelected?.businesses?.map((business: any) => {
204
+ return (
205
+ <SingleBusinessOffer key={business.id}>
206
+ {business?.logo ? (
207
+ <FastImage
208
+ style={styles.productStyle}
209
+ source={{
210
+ uri: optimizeImage(business?.logo, 'h_250,c_limit'),
211
+ priority: FastImage.priority.normal,
212
+ }}
213
+ resizeMode={FastImage.resizeMode.cover}
214
+ />
215
+ ) : (
216
+ <OIcon
217
+ src={theme?.images?.dummies?.product}
218
+ style={styles.productStyle}
219
+ />
220
+ )}
221
+ <BusinessInfo>
222
+ <OText style={{ maxWidth: '60%' }}>{business.name}</OText>
223
+ <OButton
224
+ onClick={() => handleBusinessClick(business)}
225
+ text={t('GO_TO_BUSINESSS', 'Go to business')}
226
+ style={styles.modalButtonStyle}
227
+ textStyle={{ fontSize: 10, color: '#fff' }}
228
+ />
229
+ </BusinessInfo>
230
+ </SingleBusinessOffer>
231
+ )
232
+ })}
233
+ </ScrollView>
234
+ </View>
235
+ </OModal>
236
+ </PromotionsContainer>
237
+ </Container>
238
+ )
239
+ }
240
+
241
+ export const Promotions = (props: PromotionParams) => {
242
+ const PromotionsProps = {
243
+ ...props,
244
+ UIComponent: PromotionsUI
245
+ }
246
+
247
+ return (
248
+ <PromotionsController {...PromotionsProps} />
249
+ )
250
+ }
@@ -0,0 +1,60 @@
1
+ import styled, { css } from 'styled-components/native'
2
+
3
+ export const PromotionsContainer = styled.View`
4
+ width: 100%;
5
+ padding-left: 40px;
6
+ padding-right: 40px;
7
+ `
8
+
9
+ export const SingleOfferContainer = styled.View`
10
+ flex-direction: row;
11
+ width: 100%;
12
+ justify-content: space-between;
13
+ align-items: center;
14
+ margin-bottom: 20px;
15
+
16
+ `
17
+
18
+ export const OfferInformation = styled.View`
19
+ justify-content: space-between;
20
+ max-width: 75%;
21
+ `
22
+
23
+ export const SearchBarContainer = styled.View`
24
+ display: flex;
25
+ width: 100%;
26
+ justify-content: flex-start;
27
+ margin-bottom: 20px;
28
+ `
29
+
30
+ export const SingleBusinessOffer = styled.View`
31
+ flex-direction: row;
32
+ `
33
+
34
+ export const AvailableBusinesses = styled.View`
35
+ flex-direction: row;
36
+ overflow: hidden;
37
+ `
38
+
39
+ export const OfferData = styled.View`
40
+ display: flex;
41
+ align-items: center;
42
+ flex-direction: column;
43
+ `
44
+
45
+ export const Code = styled.View`
46
+ display: flex;
47
+ flex-direction: column;
48
+ align-items: center;
49
+ margin-bottom: 10px;
50
+ `
51
+
52
+ export const ValueOfOffer = styled.View``
53
+
54
+ export const BusinessInfo = styled.View`
55
+ flex: 1;
56
+ flex-direction: row;
57
+ justify-content: space-between;
58
+ align-items: center;
59
+ margin-left: 10px;
60
+ `