ordering-ui-react-native 0.15.48 → 0.15.50-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 (189) hide show
  1. package/package.json +6 -3
  2. package/src/DeliveryApp.tsx +43 -1
  3. package/src/components/AddressForm/index.tsx +18 -2
  4. package/src/components/BusinessController/index.tsx +16 -8
  5. package/src/components/BusinessTypeFilter/index.tsx +3 -1
  6. package/src/components/BusinessesListing/index.tsx +1 -1
  7. package/src/components/Checkout/index.tsx +23 -2
  8. package/src/components/DriverTips/index.tsx +11 -6
  9. package/src/components/LanguageSelector/index.tsx +7 -2
  10. package/src/components/LoginForm/index.tsx +120 -30
  11. package/src/components/LoginForm/styles.tsx +6 -0
  12. package/src/components/OrderDetails/index.tsx +9 -23
  13. package/src/components/PaymentOptions/index.tsx +1 -1
  14. package/src/components/PaymentOptionsWebView/index.tsx +123 -124
  15. package/src/components/SignupForm/index.tsx +145 -61
  16. package/src/components/SingleProductCard/index.tsx +16 -4
  17. package/src/components/StripeMethodForm/index.tsx +1 -2
  18. package/src/components/UpsellingProducts/index.tsx +1 -1
  19. package/src/components/UserProfileForm/index.tsx +63 -6
  20. package/src/components/UserProfileForm/styles.tsx +8 -0
  21. package/src/components/VerifyPhone/styles.tsx +1 -2
  22. package/src/components/shared/OModal.tsx +1 -1
  23. package/src/hooks/useCountdownTimer.tsx +26 -0
  24. package/src/navigators/CheckoutNavigator.tsx +6 -0
  25. package/src/navigators/HomeNavigator.tsx +12 -0
  26. package/src/pages/BusinessesListing.tsx +1 -1
  27. package/src/pages/MultiCheckout.tsx +31 -0
  28. package/src/pages/MultiOrdersDetails.tsx +27 -0
  29. package/src/pages/Sessions.tsx +22 -0
  30. package/src/theme.json +0 -1
  31. package/src/types/index.tsx +18 -11
  32. package/src/utils/index.tsx +68 -1
  33. package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +103 -15
  34. package/themes/business/src/components/AcceptOrRejectOrder/styles.tsx +6 -0
  35. package/themes/business/src/components/Chat/index.tsx +42 -90
  36. package/themes/business/src/components/DriverMap/index.tsx +6 -5
  37. package/themes/business/src/components/Home/index.tsx +128 -55
  38. package/themes/business/src/components/Home/styles.tsx +8 -1
  39. package/themes/business/src/components/LoginForm/index.tsx +89 -2
  40. package/themes/business/src/components/LoginForm/styles.tsx +6 -0
  41. package/themes/business/src/components/LogoutButton/index.tsx +1 -1
  42. package/themes/business/src/components/NewOrderNotification/index.tsx +79 -105
  43. package/themes/business/src/components/OrderDetails/Business.tsx +1 -1
  44. package/themes/business/src/components/OrderDetails/Delivery.tsx +35 -18
  45. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +159 -91
  46. package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +6 -0
  47. package/themes/business/src/components/OrderDetails/styles.tsx +7 -0
  48. package/themes/business/src/components/OrdersListManager/index.tsx +1 -1
  49. package/themes/business/src/components/OrdersOption/index.tsx +5 -2
  50. package/themes/business/src/components/PreviousOrders/index.tsx +7 -5
  51. package/themes/business/src/components/ProductItemAccordion/index.tsx +2 -2
  52. package/themes/business/src/components/shared/OModal.tsx +1 -1
  53. package/themes/business/src/types/index.tsx +5 -1
  54. package/themes/doordash/src/components/BusinessesListing/index.tsx +1 -1
  55. package/themes/doordash/src/components/LoginForm/index.tsx +1 -2
  56. package/themes/instacart/src/components/BusinessesListing/index.tsx +1 -1
  57. package/themes/kiosk/src/components/BusinessMenu/index.tsx +39 -28
  58. package/themes/kiosk/src/components/BusinessesListing/index.tsx +2 -3
  59. package/themes/kiosk/src/components/Cart/index.tsx +99 -26
  60. package/themes/kiosk/src/components/Cart/styles.tsx +6 -0
  61. package/themes/kiosk/src/components/CartBottomSheet/index.tsx +9 -2
  62. package/themes/kiosk/src/components/CartContent/index.tsx +0 -11
  63. package/themes/kiosk/src/components/CartItem/index.tsx +4 -3
  64. package/themes/kiosk/src/components/CategoriesMenu/index.tsx +107 -62
  65. package/themes/kiosk/src/components/Checkout/index.tsx +40 -22
  66. package/themes/kiosk/src/components/CustomerName/index.tsx +0 -6
  67. package/themes/kiosk/src/components/DrawerView/index.tsx +1 -0
  68. package/themes/kiosk/src/components/DrawerView/styles.tsx +2 -2
  69. package/themes/kiosk/src/components/NavBar/index.tsx +29 -20
  70. package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
  71. package/themes/kiosk/src/components/OrderDetails/index.tsx +165 -65
  72. package/themes/kiosk/src/components/OrderDetails/styles.tsx +5 -0
  73. package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +9 -11
  74. package/themes/kiosk/src/components/PaymentOptions/index.tsx +56 -54
  75. package/themes/kiosk/src/components/ProductForm/index.tsx +7 -8
  76. package/themes/kiosk/src/components/ProductItemAccordion/index.tsx +2 -2
  77. package/themes/kiosk/src/components/ProductOption/index.tsx +1 -1
  78. package/themes/kiosk/src/components/ProductOptionSubOption/index.tsx +3 -1
  79. package/themes/kiosk/src/components/UpsellingProducts/index.tsx +16 -5
  80. package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
  81. package/themes/kiosk/src/types/index.d.ts +3 -0
  82. package/themes/original/index.tsx +169 -4
  83. package/themes/original/src/components/ActiveOrders/index.tsx +15 -132
  84. package/themes/original/src/components/ActiveOrders/styles.tsx +0 -54
  85. package/themes/original/src/components/AddressForm/index.tsx +1 -1
  86. package/themes/original/src/components/AddressList/index.tsx +30 -18
  87. package/themes/original/src/components/AppleLogin/index.tsx +117 -78
  88. package/themes/original/src/components/BusinessBasicInformation/index.tsx +136 -45
  89. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +4 -0
  90. package/themes/original/src/components/BusinessController/index.tsx +48 -11
  91. package/themes/original/src/components/BusinessController/styles.tsx +27 -0
  92. package/themes/original/src/components/BusinessFeaturedController/index.tsx +20 -1
  93. package/themes/original/src/components/BusinessFeaturedController/styles.tsx +23 -0
  94. package/themes/original/src/components/BusinessItemAccordion/index.tsx +8 -5
  95. package/themes/original/src/components/BusinessItemAccordion/styles.tsx +3 -1
  96. package/themes/original/src/components/BusinessListingSearch/index.tsx +196 -58
  97. package/themes/original/src/components/BusinessListingSearch/styles.tsx +22 -2
  98. package/themes/original/src/components/BusinessPreorder/index.tsx +1 -1
  99. package/themes/original/src/components/BusinessProductsCategories/index.tsx +2 -2
  100. package/themes/original/src/components/BusinessProductsList/CategoryDescription/index.tsx +44 -0
  101. package/themes/original/src/components/BusinessProductsList/index.tsx +119 -35
  102. package/themes/original/src/components/BusinessProductsList/styles.tsx +12 -4
  103. package/themes/original/src/components/BusinessProductsListing/index.tsx +109 -21
  104. package/themes/original/src/components/BusinessProductsListing/styles.tsx +22 -0
  105. package/themes/original/src/components/BusinessReviews/index.tsx +4 -25
  106. package/themes/original/src/components/BusinessTypeFilter/index.tsx +1 -2
  107. package/themes/original/src/components/BusinessesListing/index.tsx +127 -66
  108. package/themes/original/src/components/BusinessesListing/styles.tsx +11 -3
  109. package/themes/original/src/components/Cart/index.tsx +60 -41
  110. package/themes/original/src/components/Checkout/index.tsx +48 -32
  111. package/themes/original/src/components/DriverTips/index.tsx +17 -12
  112. package/themes/original/src/components/Favorite/index.tsx +92 -0
  113. package/themes/original/src/components/Favorite/styles.tsx +22 -0
  114. package/themes/original/src/components/FavoriteList/index.tsx +298 -0
  115. package/themes/original/src/components/FavoriteList/styles.tsx +5 -0
  116. package/themes/original/src/components/ForgotPasswordForm/index.tsx +84 -4
  117. package/themes/original/src/components/GPSButton/index.tsx +15 -8
  118. package/themes/original/src/components/GoogleMap/index.tsx +1 -0
  119. package/themes/original/src/components/Help/index.tsx +21 -4
  120. package/themes/original/src/components/HighestRatedBusinesses/index.tsx +18 -1
  121. package/themes/original/src/components/Home/index.tsx +1 -1
  122. package/themes/original/src/components/LastOrders/index.tsx +12 -1
  123. package/themes/original/src/components/LoginForm/Otp/index.tsx +91 -0
  124. package/themes/original/src/components/LoginForm/Otp/styles.tsx +7 -0
  125. package/themes/original/src/components/LoginForm/index.tsx +394 -155
  126. package/themes/original/src/components/LoginForm/styles.tsx +7 -4
  127. package/themes/original/src/components/LogoutButton/index.tsx +7 -1
  128. package/themes/original/src/components/MessageListing/index.tsx +10 -1
  129. package/themes/original/src/components/Messages/index.tsx +1 -1
  130. package/themes/original/src/components/MomentOption/index.tsx +10 -1
  131. package/themes/original/src/components/MomentOption/styles.tsx +1 -1
  132. package/themes/original/src/components/MultiCartsPaymethodsAndWallets/index.tsx +243 -0
  133. package/themes/original/src/components/MultiCartsPaymethodsAndWallets/styles.tsx +46 -0
  134. package/themes/original/src/components/MultiCheckout/index.tsx +298 -0
  135. package/themes/original/src/components/MultiCheckout/styles.tsx +59 -0
  136. package/themes/original/src/components/MultiOrdersDetails/SingleOrderCard.tsx +372 -0
  137. package/themes/original/src/components/MultiOrdersDetails/index.tsx +258 -0
  138. package/themes/original/src/components/MultiOrdersDetails/styles.tsx +50 -0
  139. package/themes/original/src/components/MyOrders/index.tsx +120 -32
  140. package/themes/original/src/components/MyOrders/styles.tsx +8 -1
  141. package/themes/original/src/components/OrderDetails/index.tsx +64 -42
  142. package/themes/original/src/components/OrderDetails/styles.tsx +1 -2
  143. package/themes/original/src/components/OrderSummary/index.tsx +3 -3
  144. package/themes/original/src/components/OrderTypeSelector/index.tsx +4 -2
  145. package/themes/original/src/components/OrdersOption/PreviousBusinessOrdered/index.tsx +153 -0
  146. package/themes/original/src/components/OrdersOption/PreviousBusinessOrdered/styles.tsx +6 -0
  147. package/themes/original/src/components/OrdersOption/PreviousProductsOrdered/index.tsx +53 -0
  148. package/themes/original/src/components/OrdersOption/PreviousProductsOrdered/styles.tsx +6 -0
  149. package/themes/original/src/components/OrdersOption/index.tsx +130 -38
  150. package/themes/original/src/components/OrdersOption/styles.tsx +4 -1
  151. package/themes/original/src/components/PaymentOptionCash/index.tsx +2 -2
  152. package/themes/original/src/components/PaymentOptionWallet/index.tsx +17 -23
  153. package/themes/original/src/components/PaymentOptionWallet/styles.tsx +1 -1
  154. package/themes/original/src/components/PaymentOptions/index.tsx +16 -14
  155. package/themes/original/src/components/PhoneInputNumber/index.tsx +1 -1
  156. package/themes/original/src/components/PreviousOrders/index.tsx +18 -147
  157. package/themes/original/src/components/ProductForm/index.tsx +70 -62
  158. package/themes/original/src/components/ProductForm/styles.tsx +0 -1
  159. package/themes/original/src/components/ProductItemAccordion/index.tsx +2 -2
  160. package/themes/original/src/components/ProductOptionSubOption/index.tsx +18 -12
  161. package/themes/original/src/components/Promotions/index.tsx +250 -0
  162. package/themes/original/src/components/Promotions/styles.tsx +60 -0
  163. package/themes/original/src/components/SearchBar/index.tsx +10 -4
  164. package/themes/original/src/components/Sessions/index.tsx +160 -0
  165. package/themes/original/src/components/Sessions/styles.tsx +15 -0
  166. package/themes/original/src/components/SignupForm/index.tsx +333 -128
  167. package/themes/original/src/components/SingleOrderCard/index.tsx +282 -0
  168. package/themes/original/src/components/SingleOrderCard/styles.tsx +54 -0
  169. package/themes/original/src/components/SingleProductCard/index.tsx +59 -17
  170. package/themes/original/src/components/StripeElementsForm/index.tsx +16 -8
  171. package/themes/original/src/components/StripeElementsForm/naked.tsx +2 -2
  172. package/themes/original/src/components/UpsellingProducts/index.tsx +86 -74
  173. package/themes/original/src/components/UserDetails/index.tsx +5 -96
  174. package/themes/original/src/components/UserFormDetails/index.tsx +34 -24
  175. package/themes/original/src/components/UserProfile/index.tsx +59 -5
  176. package/themes/original/src/components/UserProfileForm/index.tsx +20 -18
  177. package/themes/original/src/components/UserVerification/index.tsx +178 -192
  178. package/themes/original/src/components/VerifyPhone/index.tsx +10 -7
  179. package/themes/original/src/components/VerifyPhone/styles.tsx +2 -1
  180. package/themes/original/src/components/Wallets/index.tsx +76 -9
  181. package/themes/original/src/components/Wallets/styles.tsx +21 -0
  182. package/themes/original/src/components/shared/OModal.tsx +4 -2
  183. package/themes/original/src/config/constants.tsx +6 -6
  184. package/themes/original/src/types/index.tsx +144 -9
  185. package/themes/original/src/utils/index.tsx +19 -2
  186. package/themes/single-business/src/components/AddressList/index.tsx +1 -1
  187. package/themes/single-business/src/components/OrderTypeSelector/index.tsx +1 -1
  188. package/themes/single-business/src/components/UserProfile/index.tsx +1 -1
  189. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
@@ -175,6 +175,7 @@ export const ProductOptionsUI = (props: any) => {
175
175
  const [optionLayout, setOptionLayout] = useState<any>({})
176
176
  const [headerRefHeight, setHeaderRefHeight] = useState(0)
177
177
  const [summaryRefHeight, setSummaryRefHeight] = useState(0)
178
+ const [isScrollAvailable, setIsScrollAvailable] = useState(null)
178
179
 
179
180
  const isError = (id: number) => {
180
181
  let bgColor = theme.colors.white;
@@ -278,47 +279,6 @@ export const ProductOptionsUI = (props: any) => {
278
279
  setOptionLayout(_optionLayout)
279
280
  }
280
281
 
281
- useEffect(() => {
282
- const imageList: any = []
283
- const videoList: any = []
284
- product?.images && imageList.push(product.images)
285
- if (product?.gallery && product?.gallery.length > 0) {
286
- for (const img of product?.gallery) {
287
- if (img?.file) {
288
- imageList.push(img?.file)
289
- }
290
- if (img?.video) {
291
- const keys = img?.video.split('/')
292
- let _videoId = keys[keys.length - 1]
293
-
294
- if (_videoId.includes('watch')) {
295
- const __url = _videoId.split('=')[1]
296
- _videoId = __url
297
- } else if (_videoId.includes('?')) {
298
- const __url = _videoId.split('?')[0]
299
- _videoId = __url
300
- }
301
-
302
- if (_videoId.search(/&/i) >= 0) {
303
- _videoId = _videoId.split('&')[0]
304
- } else if (_videoId.search(/\?/i) >= 0) {
305
- _videoId = _videoId.split('?')[0]
306
- }
307
- if ((_videoId.length === 11)) {
308
- videoList.push(_videoId)
309
- }
310
- }
311
- }
312
- }
313
- const gallery = imageList.concat(videoList)
314
- setGallery(gallery)
315
-
316
- if (product?.weight && product?.weight_unit) {
317
- setIsHaveWeight(true)
318
- setPricePerWeightUnit(product?.price / product?.weight)
319
- }
320
- }, [product])
321
-
322
282
  const saveErrors =
323
283
  orderState.loading ||
324
284
  maxProductQuantity === 0 ||
@@ -326,25 +286,6 @@ export const ProductOptionsUI = (props: any) => {
326
286
 
327
287
  const ExtraOptions = ({ eID, options }: any) => (
328
288
  <>
329
- {product?.ingredients.length > 0 && (
330
- <TouchableOpacity
331
- key={`eopt_all_00`}
332
- onPress={() => setSelectedOpt(-1)}
333
- style={[
334
- styles.extraItem,
335
- {
336
- borderBottomColor:
337
- selOpt == -1 ? theme.colors.textNormal : theme.colors.border,
338
- },
339
- ]}>
340
- <OText
341
- color={selOpt == -1 ? theme.colors.textNormal : theme.colors.textSecondary}
342
- size={selOpt == -1 ? 14 : 12}
343
- weight={selOpt == -1 ? '600' : 'normal'}>
344
- {t('INGREDIENTS', 'Ingredients')}
345
- </OText>
346
- </TouchableOpacity>
347
- )}
348
289
  {options.map(({ id, name, respect_to, suboptions }: any) => (
349
290
  <React.Fragment key={`cont_key_${id}`}>
350
291
  {respect_to == null && suboptions?.length > 0 && (
@@ -377,6 +318,54 @@ export const ProductOptionsUI = (props: any) => {
377
318
  ? () => navigation.goBack()
378
319
  : () => navigation.navigate('Business', { store: props.businessSlug })
379
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
+
380
369
  return (
381
370
  <SafeAreaView style={{ flex: 1 }}>
382
371
  <TopHeader>
@@ -665,6 +654,25 @@ export const ProductOptionsUI = (props: any) => {
665
654
  {t('ALL', 'All')}
666
655
  </OText>
667
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
+ )}
668
676
  {product?.extras.map((extra: any) =>
669
677
  <ExtraOptions key={extra.id} options={extra.options} />
670
678
  )}
@@ -694,7 +702,7 @@ export const ProductOptionsUI = (props: any) => {
694
702
  </WrapperIngredients>
695
703
  </View>
696
704
  )}
697
- {product?.extras.map((extra: any) =>
705
+ {product?.extras.sort((a: any, b: any) => a.rank - b.rank).map((extra: any) =>
698
706
  extra.options.sort((a: any, b: any) => a.rank - b.rank).map((option: any) => {
699
707
  const currentState =
700
708
  productCart.options[`id:${option.id}`] || {};
@@ -738,7 +746,7 @@ export const ProductOptionsUI = (props: any) => {
738
746
  isSoldOut ||
739
747
  maxProductQuantity <= 0
740
748
  }
741
- scrollDown={scrollDown}
749
+ setIsScrollAvailable={setIsScrollAvailable}
742
750
  error={errors[`id:${option.id}`]}
743
751
  />
744
752
  );
@@ -49,7 +49,6 @@ export const ProductDescription = styled.View`
49
49
  `
50
50
 
51
51
  export const ProductEditions = styled.View`
52
-
53
52
  `
54
53
 
55
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
+ `
@@ -20,7 +20,12 @@ export const SearchBar = (props: any) => {
20
20
  inputStyle,
21
21
  onPress,
22
22
  isDisabled,
23
- iconCustomRight
23
+ iconCustomRight,
24
+ onSubmitEditing,
25
+ blurOnSubmit,
26
+ inputContainerStyles,
27
+ containerStyles,
28
+ hideIcon
24
29
  } = props
25
30
 
26
31
  const theme = useTheme();
@@ -75,19 +80,20 @@ export const SearchBar = (props: any) => {
75
80
  }
76
81
 
77
82
  return (
78
- <Pressable style={[styles.container, { height: height }]}>
83
+ <Pressable style={[styles.container, containerStyles, { height: height }]}>
79
84
  <OInput
80
85
  value={searchValue}
81
86
  onChange={onChangeSearch}
82
- style={styles.inputStyle}
87
+ style={{...styles.inputStyle, ...inputContainerStyles}}
83
88
  placeholder={placeholder}
84
- icon={theme.images.general.search}
89
+ icon={!hideIcon && theme.images.general.search}
85
90
  isDisabled={isDisabled}
86
91
  iconStyle={{ width: 12 }}
87
92
  returnKeyType='done'
88
93
  inputStyle={{padding: 0, paddingTop: Platform.OS == 'android' ? 2 : 0, ...inputStyle}}
89
94
  onPress={() => onPress && onPress()}
90
95
  iconCustomRight={iconCustomRight}
96
+ onSubmitEditing={() => onSubmitEditing && onSubmitEditing()}
91
97
  />
92
98
  {isCancelButtonShow && (
93
99
  <OButton