ordering-ui-react-native 0.15.56 → 0.15.58-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 (186) hide show
  1. package/package.json +5 -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 +7 -21
  13. package/src/components/PaymentOptions/index.tsx +67 -50
  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/LoginForm/index.tsx +89 -2
  38. package/themes/business/src/components/LoginForm/styles.tsx +6 -0
  39. package/themes/business/src/components/LogoutButton/index.tsx +1 -1
  40. package/themes/business/src/components/NewOrderNotification/index.tsx +79 -105
  41. package/themes/business/src/components/OrderDetails/Business.tsx +2 -2
  42. package/themes/business/src/components/OrderDetails/Delivery.tsx +28 -11
  43. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +41 -7
  44. package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +6 -0
  45. package/themes/business/src/components/OrdersListManager/index.tsx +1 -1
  46. package/themes/business/src/components/OrdersOption/index.tsx +5 -2
  47. package/themes/business/src/components/PreviousOrders/index.tsx +2 -2
  48. package/themes/business/src/components/ProductItemAccordion/index.tsx +2 -2
  49. package/themes/business/src/components/UserFormDetails/index.tsx +5 -2
  50. package/themes/business/src/components/UserProfileForm/index.tsx +2 -0
  51. package/themes/business/src/components/shared/OModal.tsx +1 -1
  52. package/themes/business/src/types/index.tsx +6 -1
  53. package/themes/doordash/src/components/BusinessesListing/index.tsx +1 -1
  54. package/themes/doordash/src/components/LoginForm/index.tsx +1 -2
  55. package/themes/instacart/src/components/BusinessesListing/index.tsx +1 -1
  56. package/themes/kiosk/src/components/BusinessMenu/index.tsx +39 -28
  57. package/themes/kiosk/src/components/BusinessesListing/index.tsx +2 -3
  58. package/themes/kiosk/src/components/Cart/index.tsx +11 -12
  59. package/themes/kiosk/src/components/CartBottomSheet/index.tsx +9 -2
  60. package/themes/kiosk/src/components/CartContent/index.tsx +0 -11
  61. package/themes/kiosk/src/components/CartItem/index.tsx +4 -3
  62. package/themes/kiosk/src/components/CategoriesMenu/index.tsx +107 -62
  63. package/themes/kiosk/src/components/Checkout/index.tsx +40 -22
  64. package/themes/kiosk/src/components/CustomerName/index.tsx +0 -6
  65. package/themes/kiosk/src/components/DrawerView/index.tsx +1 -0
  66. package/themes/kiosk/src/components/DrawerView/styles.tsx +2 -2
  67. package/themes/kiosk/src/components/NavBar/index.tsx +29 -20
  68. package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
  69. package/themes/kiosk/src/components/OrderDetails/index.tsx +32 -27
  70. package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +9 -11
  71. package/themes/kiosk/src/components/PaymentOptions/index.tsx +56 -54
  72. package/themes/kiosk/src/components/ProductForm/index.tsx +7 -8
  73. package/themes/kiosk/src/components/ProductItemAccordion/index.tsx +2 -2
  74. package/themes/kiosk/src/components/ProductOption/index.tsx +1 -1
  75. package/themes/kiosk/src/components/ProductOptionSubOption/index.tsx +3 -1
  76. package/themes/kiosk/src/components/UpsellingProducts/index.tsx +16 -5
  77. package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
  78. package/themes/kiosk/src/types/index.d.ts +1 -0
  79. package/themes/original/index.tsx +169 -4
  80. package/themes/original/src/components/ActiveOrders/index.tsx +15 -132
  81. package/themes/original/src/components/ActiveOrders/styles.tsx +0 -54
  82. package/themes/original/src/components/AddressForm/index.tsx +7 -6
  83. package/themes/original/src/components/AddressList/index.tsx +30 -18
  84. package/themes/original/src/components/AppleLogin/index.tsx +9 -13
  85. package/themes/original/src/components/BusinessBasicInformation/index.tsx +136 -45
  86. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +4 -0
  87. package/themes/original/src/components/BusinessController/index.tsx +48 -11
  88. package/themes/original/src/components/BusinessController/styles.tsx +27 -0
  89. package/themes/original/src/components/BusinessFeaturedController/index.tsx +20 -1
  90. package/themes/original/src/components/BusinessFeaturedController/styles.tsx +23 -0
  91. package/themes/original/src/components/BusinessItemAccordion/index.tsx +8 -5
  92. package/themes/original/src/components/BusinessItemAccordion/styles.tsx +3 -1
  93. package/themes/original/src/components/BusinessListingSearch/index.tsx +196 -58
  94. package/themes/original/src/components/BusinessListingSearch/styles.tsx +22 -2
  95. package/themes/original/src/components/BusinessPreorder/index.tsx +1 -1
  96. package/themes/original/src/components/BusinessProductsCategories/index.tsx +2 -2
  97. package/themes/original/src/components/BusinessProductsList/CategoryDescription/index.tsx +44 -0
  98. package/themes/original/src/components/BusinessProductsList/index.tsx +119 -35
  99. package/themes/original/src/components/BusinessProductsList/styles.tsx +12 -4
  100. package/themes/original/src/components/BusinessProductsListing/index.tsx +109 -21
  101. package/themes/original/src/components/BusinessProductsListing/styles.tsx +22 -0
  102. package/themes/original/src/components/BusinessReviews/index.tsx +6 -1
  103. package/themes/original/src/components/BusinessTypeFilter/index.tsx +1 -2
  104. package/themes/original/src/components/BusinessesListing/index.tsx +127 -66
  105. package/themes/original/src/components/BusinessesListing/styles.tsx +11 -3
  106. package/themes/original/src/components/Cart/index.tsx +60 -41
  107. package/themes/original/src/components/Checkout/index.tsx +48 -32
  108. package/themes/original/src/components/DriverTips/index.tsx +17 -12
  109. package/themes/original/src/components/Favorite/index.tsx +92 -0
  110. package/themes/original/src/components/Favorite/styles.tsx +22 -0
  111. package/themes/original/src/components/FavoriteList/index.tsx +298 -0
  112. package/themes/original/src/components/FavoriteList/styles.tsx +5 -0
  113. package/themes/original/src/components/ForgotPasswordForm/index.tsx +84 -4
  114. package/themes/original/src/components/GPSButton/index.tsx +15 -8
  115. package/themes/original/src/components/GoogleMap/index.tsx +11 -11
  116. package/themes/original/src/components/Help/index.tsx +21 -4
  117. package/themes/original/src/components/HighestRatedBusinesses/index.tsx +18 -1
  118. package/themes/original/src/components/Home/index.tsx +1 -1
  119. package/themes/original/src/components/LastOrders/index.tsx +12 -1
  120. package/themes/original/src/components/LoginForm/Otp/index.tsx +91 -0
  121. package/themes/original/src/components/LoginForm/Otp/styles.tsx +7 -0
  122. package/themes/original/src/components/LoginForm/index.tsx +332 -164
  123. package/themes/original/src/components/LoginForm/styles.tsx +1 -3
  124. package/themes/original/src/components/MessageListing/index.tsx +10 -1
  125. package/themes/original/src/components/Messages/index.tsx +1 -1
  126. package/themes/original/src/components/MomentOption/index.tsx +10 -1
  127. package/themes/original/src/components/MomentOption/styles.tsx +1 -1
  128. package/themes/original/src/components/MultiCartsPaymethodsAndWallets/index.tsx +243 -0
  129. package/themes/original/src/components/MultiCartsPaymethodsAndWallets/styles.tsx +46 -0
  130. package/themes/original/src/components/MultiCheckout/index.tsx +298 -0
  131. package/themes/original/src/components/MultiCheckout/styles.tsx +59 -0
  132. package/themes/original/src/components/MultiOrdersDetails/SingleOrderCard.tsx +372 -0
  133. package/themes/original/src/components/MultiOrdersDetails/index.tsx +258 -0
  134. package/themes/original/src/components/MultiOrdersDetails/styles.tsx +50 -0
  135. package/themes/original/src/components/MyOrders/index.tsx +120 -32
  136. package/themes/original/src/components/MyOrders/styles.tsx +8 -1
  137. package/themes/original/src/components/OrderDetails/OrderHistory.tsx +167 -0
  138. package/themes/original/src/components/OrderDetails/index.tsx +135 -49
  139. package/themes/original/src/components/OrderDetails/styles.tsx +1 -2
  140. package/themes/original/src/components/OrderSummary/index.tsx +2 -2
  141. package/themes/original/src/components/OrderTypeSelector/index.tsx +4 -2
  142. package/themes/original/src/components/OrdersOption/PreviousBusinessOrdered/index.tsx +153 -0
  143. package/themes/original/src/components/OrdersOption/PreviousBusinessOrdered/styles.tsx +6 -0
  144. package/themes/original/src/components/OrdersOption/PreviousProductsOrdered/index.tsx +53 -0
  145. package/themes/original/src/components/OrdersOption/PreviousProductsOrdered/styles.tsx +6 -0
  146. package/themes/original/src/components/OrdersOption/index.tsx +130 -38
  147. package/themes/original/src/components/OrdersOption/styles.tsx +4 -1
  148. package/themes/original/src/components/PaymentOptionCash/index.tsx +2 -2
  149. package/themes/original/src/components/PaymentOptionWallet/index.tsx +17 -23
  150. package/themes/original/src/components/PaymentOptionWallet/styles.tsx +1 -1
  151. package/themes/original/src/components/PaymentOptions/index.tsx +57 -36
  152. package/themes/original/src/components/PhoneInputNumber/index.tsx +1 -1
  153. package/themes/original/src/components/PreviousOrders/index.tsx +18 -147
  154. package/themes/original/src/components/ProductForm/index.tsx +70 -62
  155. package/themes/original/src/components/ProductForm/styles.tsx +0 -1
  156. package/themes/original/src/components/ProductItemAccordion/index.tsx +2 -2
  157. package/themes/original/src/components/ProductOptionSubOption/index.tsx +18 -12
  158. package/themes/original/src/components/Promotions/index.tsx +151 -133
  159. package/themes/original/src/components/Promotions/styles.tsx +3 -23
  160. package/themes/original/src/components/SearchBar/index.tsx +10 -4
  161. package/themes/original/src/components/Sessions/index.tsx +160 -0
  162. package/themes/original/src/components/Sessions/styles.tsx +15 -0
  163. package/themes/original/src/components/SignupForm/index.tsx +269 -130
  164. package/themes/original/src/components/SingleOrderCard/index.tsx +282 -0
  165. package/themes/original/src/components/SingleOrderCard/styles.tsx +54 -0
  166. package/themes/original/src/components/SingleProductCard/index.tsx +59 -17
  167. package/themes/original/src/components/StripeElementsForm/index.tsx +16 -8
  168. package/themes/original/src/components/StripeElementsForm/naked.tsx +2 -2
  169. package/themes/original/src/components/UpsellingProducts/index.tsx +86 -74
  170. package/themes/original/src/components/UserDetails/index.tsx +5 -96
  171. package/themes/original/src/components/UserFormDetails/index.tsx +34 -24
  172. package/themes/original/src/components/UserProfile/index.tsx +53 -6
  173. package/themes/original/src/components/UserProfileForm/index.tsx +20 -18
  174. package/themes/original/src/components/UserVerification/index.tsx +178 -192
  175. package/themes/original/src/components/VerifyPhone/index.tsx +10 -7
  176. package/themes/original/src/components/VerifyPhone/styles.tsx +2 -1
  177. package/themes/original/src/components/Wallets/index.tsx +76 -9
  178. package/themes/original/src/components/Wallets/styles.tsx +21 -0
  179. package/themes/original/src/components/shared/OModal.tsx +4 -2
  180. package/themes/original/src/config/constants.tsx +6 -6
  181. package/themes/original/src/types/index.tsx +192 -33
  182. package/themes/original/src/utils/index.tsx +85 -2
  183. package/themes/single-business/src/components/AddressList/index.tsx +1 -1
  184. package/themes/single-business/src/components/OrderTypeSelector/index.tsx +1 -1
  185. package/themes/single-business/src/components/UserProfile/index.tsx +1 -1
  186. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
@@ -144,7 +144,7 @@ const BusinessPreorderUI = (props: BusinessPreorderParams) => {
144
144
 
145
145
  const validateSelectedDate = (curdate: any, menu: any) => {
146
146
  const day = moment(curdate).format('d')
147
- setIsEnabled(menu?.schedule[day]?.enabled || false)
147
+ setIsEnabled(menu?.schedule?.[day]?.enabled || false)
148
148
  }
149
149
 
150
150
  const getTimes = (curdate: any, menu: any) => {
@@ -57,12 +57,12 @@ const BusinessProductsCategoriesUI = (props: any) => {
57
57
 
58
58
  if (!lazyLoadProductsRecommended) {
59
59
  if (category?.id) {
60
- scrollViewRef.current.scrollTo({
60
+ scrollViewRef?.current?.scrollTo && scrollViewRef.current.scrollTo({
61
61
  y: categoriesLayout[`cat_${category?.id}`]?.y + productListLayout?.y - 70,
62
62
  animated: true
63
63
  })
64
64
  } else {
65
- scrollViewRef.current.scrollTo({
65
+ scrollViewRef?.current?.scrollTo && scrollViewRef.current.scrollTo({
66
66
  y: productListLayout?.y - 70,
67
67
  animated: true
68
68
  })
@@ -0,0 +1,44 @@
1
+ import React from 'react'
2
+ import { OModal, OText, OIcon } from '../../shared'
3
+ import { ScrollView } from 'react-native'
4
+ import { useUtils } from 'ordering-components/native'
5
+
6
+ interface CategoryDescriptionParams {
7
+ openDescription?: {name: string, image: string, description: string} | null,
8
+ setOpenDescription: any;
9
+ }
10
+
11
+ function categoryDescriptionPropsAreEqual(prev : any, next : any) {
12
+ return prev.openDescription === next.openDescription
13
+ }
14
+
15
+ const CategoryDescription = (props : CategoryDescriptionParams) => {
16
+ const [{ optimizeImage }] = useUtils()
17
+ return (
18
+ <OModal
19
+ open={!!props.openDescription}
20
+ onClose={() => props.setOpenDescription(null)}
21
+ styleContainerCloseButton={{
22
+ marginLeft: -37,
23
+ width: 55,
24
+ height: 55,
25
+ marginTop: 2
26
+ }}
27
+ >
28
+ <OText size={20} style={{ paddingLeft: 70, paddingRight: 20, bottom: 25 }}>{props.openDescription?.name}</OText>
29
+ <ScrollView style={{ padding: 20 }}>
30
+ {!!props.openDescription?.image && (
31
+ <OIcon
32
+ url={optimizeImage(props.openDescription?.image, 'h_100,c_limit')}
33
+ width={240}
34
+ height={240}
35
+ style={{ borderRadius: 7.6 }}
36
+ />
37
+ )}
38
+ <OText mBottom={60}>{props.openDescription?.description}</OText>
39
+ </ScrollView>
40
+ </OModal>
41
+ )
42
+ }
43
+
44
+ export const CategoryDescriptionMemoized = React.memo(CategoryDescription,categoryDescriptionPropsAreEqual)
@@ -4,12 +4,13 @@ import { SingleProductCard } from '../SingleProductCard';
4
4
  import { NotFoundSource } from '../NotFoundSource';
5
5
  import { BusinessProductsListParams } from '../../types';
6
6
  import { OButton, OIcon, OModal, OText } from '../shared';
7
- import { ProductsContainer, ErrorMessage, WrapperNotFound, RibbonBox } from './styles';
7
+ import { ProductsContainer, ErrorMessage, WrapperNotFound, RibbonBox, SubCategoriesContainer, ContainerButton, HeaderWrapper } from './styles';
8
8
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
9
9
  import { View, ScrollView } from 'react-native';
10
10
  import { StyleSheet } from 'react-native';
11
11
  import { useTheme } from 'styled-components/native';
12
12
  import { shape } from '../../utils'
13
+ import { CategoryDescriptionMemoized } from './CategoryDescription';
13
14
 
14
15
  const BusinessProductsListUI = (props: BusinessProductsListParams) => {
15
16
  const {
@@ -28,7 +29,13 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
28
29
  handleCancelSearch,
29
30
  categoriesLayout,
30
31
  setCategoriesLayout,
31
- currentCart
32
+ currentCart,
33
+ setSubcategoriesSelected,
34
+ subcategoriesSelected,
35
+ onClickCategory,
36
+ lazyLoadProductsRecommended,
37
+ handleUpdateProducts,
38
+ isFiltMode
32
39
  } = props;
33
40
 
34
41
  const [, t] = useLanguage();
@@ -44,20 +51,86 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
44
51
  setCategoriesLayout(_categoriesLayout)
45
52
  }
46
53
 
54
+ const onClickSubcategory = (subCategory: any, parentCategory: any) => {
55
+ if (parentCategory && lazyLoadProductsRecommended) {
56
+ onClickCategory(parentCategory)
57
+ }
58
+ if (!subCategory) {
59
+ setSubcategoriesSelected?.(subcategoriesSelected.filter((_subcategory: any) => _subcategory?.parent_category_id !== parentCategory?.id))
60
+ return
61
+ }
62
+ const categoryFounded = subcategoriesSelected.find((_subcategory: any) => subCategory?.id === _subcategory?.id)
63
+ if (categoryFounded) {
64
+ setSubcategoriesSelected?.(subcategoriesSelected.filter((_subcategory: any) => subCategory?.id !== _subcategory?.id))
65
+ } else {
66
+ setSubcategoriesSelected?.([...subcategoriesSelected, subCategory])
67
+ }
68
+ }
69
+
70
+ const SubcategoriesComponent = ({ category }: any) => {
71
+ const allsubcategorySelected = !subcategoriesSelected?.some((subcategory: any) => category?.id === subcategory?.parent_category_id)
72
+
73
+ return (
74
+ <SubCategoriesContainer>
75
+ <ContainerButton
76
+ isSelected={allsubcategorySelected}
77
+ >
78
+ <OButton
79
+ onClick={() => onClickSubcategory(null, category)}
80
+ bgColor={allsubcategorySelected ? theme.colors.primary : theme.colors.backgroundGray}
81
+ text={`${t('ALL', 'All')} ${allsubcategorySelected ? 'X' : ''}`}
82
+ style={bpStyles.categoryButtonStyle}
83
+ textStyle={{ color: allsubcategorySelected ? theme.colors.white : theme.colors.textNormal, fontSize: 12 }}
84
+ />
85
+ </ContainerButton>
86
+ {category?.subcategories?.map((subcategory: any) => {
87
+ const isSubcategorySelected = subcategoriesSelected?.find((_subcategory: any) => _subcategory?.id === subcategory?.id)
88
+ return (
89
+ <ContainerButton
90
+ key={subcategory?.id}
91
+ isSelected={isSubcategorySelected}
92
+ >
93
+ <OButton
94
+ onClick={() => onClickSubcategory(subcategory, category)}
95
+ bgColor={isSubcategorySelected ? theme.colors.primary : theme.colors.backgroundGray}
96
+ text={`${subcategory?.name} ${isSubcategorySelected ? 'X' : ''}`}
97
+ style={bpStyles.categoryButtonStyle}
98
+ textStyle={{ color: isSubcategorySelected ? theme.colors.white : theme.colors.textNormal, fontSize: 12 }}
99
+ />
100
+ </ContainerButton>
101
+ )
102
+ }
103
+ )}
104
+ </SubCategoriesContainer>
105
+ )
106
+ }
107
+
47
108
  return (
48
109
  <ProductsContainer renderToHardwareTextureAndroid={categoryState.loading || isBusinessLoading}>
110
+ <HeaderWrapper>
111
+ {category?.subcategories?.length > 0 && (
112
+ <SubcategoriesComponent category={category} />
113
+ )}
114
+ </HeaderWrapper>
49
115
  {category.id &&
50
- categoryState.products?.sort((a: any, b: any) => a.rank - b.rank).map((product: any) => (
51
- <SingleProductCard
52
- key={'prod_' + product.id}
53
- isSoldOut={product.inventoried && !product.quantity}
54
- product={product}
55
- businessId={businessId}
56
- onProductClick={() => onProductClick(product)}
57
- productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
58
- />
59
- ))}
60
-
116
+ categoryState.products
117
+ ?.filter((product: any) =>
118
+ !subcategoriesSelected.find((subcategory: any) => subcategory?.parent_category_id === category?.id) ||
119
+ subcategoriesSelected?.some((subcategory: any) => subcategory.id === product?.category_id))
120
+ ?.sort((a: any, b: any) => a.rank - b.rank)
121
+ ?.map((product: any, i: number) => (
122
+ <SingleProductCard
123
+ key={'prod_' + product.id + `_${i}`}
124
+ isSoldOut={product.inventoried && !product.quantity}
125
+ product={product}
126
+ businessId={businessId}
127
+ categoryState={categoryState}
128
+ onProductClick={() => onProductClick(product)}
129
+ productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
130
+ handleUpdateProducts={handleUpdateProducts}
131
+ />
132
+ ))
133
+ }
61
134
  {!category.id &&
62
135
  featured &&
63
136
  categoryState?.products?.find((product: any) => product.featured) && (
@@ -72,11 +145,13 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
72
145
  (product: any, i: any) =>
73
146
  product.featured && (
74
147
  <SingleProductCard
75
- key={i}
148
+ key={'feat_' + product.id + `_${i}`}
76
149
  isSoldOut={product.inventoried && !product.quantity}
77
150
  product={product}
78
151
  businessId={businessId}
152
+ categoryState={categoryState}
79
153
  onProductClick={onProductClick}
154
+ handleUpdateProducts={handleUpdateProducts}
80
155
  productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
81
156
  />
82
157
  ),
@@ -86,9 +161,14 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
86
161
  )}
87
162
 
88
163
  {!category?.id && categories.filter(category => category?.id !== null).map((category, i, _categories) => {
89
- const products = !isUseParentCategory
164
+ const _products = !isUseParentCategory
90
165
  ? categoryState?.products?.filter((product: any) => product?.category_id === category?.id) ?? []
91
166
  : categoryState?.products?.filter((product: any) => category?.children?.some((cat: any) => cat.category_id === product?.category_id)) ?? []
167
+ const products = subcategoriesSelected?.length > 0
168
+ ? _products?.filter((product: any) =>
169
+ !subcategoriesSelected.find((subcategory: any) => subcategory?.parent_category_id === category?.id) ||
170
+ subcategoriesSelected?.some((subcategory: any) => subcategory.id === product?.category_id))
171
+ : _products
92
172
 
93
173
  const shortCategoryDescription = category?.description?.length > 80 ? `${category?.description?.substring(0, 80)}...` : category?.description
94
174
 
@@ -132,12 +212,12 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
132
212
  </View>
133
213
  {!!category?.description && (
134
214
  <View style={{ position: 'relative' }}>
135
- <OText size={12} weight={'500'} mBottom={5}>
215
+ <OText size={12} weight={'500'} mBottom={10} color='#909BA9'>
136
216
  {shortCategoryDescription}
137
217
  {category?.description?.length > 80 && (
138
218
  <OButton
139
219
  style={{ height: 15, paddingRight: 0, paddingLeft: 0, borderWidth: 0 }}
140
- text={t('SEE_MORE', 'See more')}
220
+ text={t('VIEW_MORE', 'View more')}
141
221
  parentStyle={{ padding: 0 }}
142
222
  onClick={() => setOpenDescription(category)}
143
223
  bgColor='transparent'
@@ -152,14 +232,19 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
152
232
  </OText>
153
233
  </View>
154
234
  )}
235
+ {category?.subcategories?.length > 0 && !isFiltMode && (
236
+ <SubcategoriesComponent category={category} />
237
+ )}
155
238
  <>
156
239
  {products.sort((a: any, b: any) => a.rank - b.rank).map((product: any, i: any) => (
157
240
  <SingleProductCard
158
- key={i}
241
+ key={`${product?.id}_${i}`}
159
242
  isSoldOut={product.inventoried && !product.quantity}
160
243
  businessId={businessId}
161
244
  product={product}
245
+ categoryState={categoryState}
162
246
  onProductClick={onProductClick}
247
+ handleUpdateProducts={handleUpdateProducts}
163
248
  productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
164
249
  />
165
250
  ))}
@@ -195,6 +280,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
195
280
  !isBusinessLoading &&
196
281
  categoryState.products.length === 0 &&
197
282
  !errors &&
283
+ !isFiltMode &&
198
284
  !(
199
285
  (searchValue && errorQuantityProducts) ||
200
286
  (!searchValue && !errorQuantityProducts)
@@ -234,23 +320,12 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
234
320
  <OText>{e}</OText>
235
321
  </ErrorMessage>
236
322
  ))}
237
- <OModal
238
- open={!!openDescription}
239
- title={openDescription?.name}
240
- onClose={() => setOpenDescription(null)}
241
- >
242
- <ScrollView style={{ padding: 20 }}>
243
- {!!openDescription?.image && (
244
- <OIcon
245
- url={optimizeImage(openDescription?.image, 'h_100,c_limit')}
246
- width={240}
247
- height={240}
248
- style={{ borderRadius: 7.6 }}
249
- />
250
- )}
251
- <OText mBottom={40}>{openDescription?.description}</OText>
252
- </ScrollView>
253
- </OModal>
323
+ {!!openDescription && (
324
+ <CategoryDescriptionMemoized
325
+ openDescription={openDescription}
326
+ setOpenDescription={setOpenDescription}
327
+ />
328
+ )}
254
329
  </ProductsContainer>
255
330
  );
256
331
  };
@@ -265,6 +340,15 @@ const bpStyles = StyleSheet.create({
265
340
  shadowRadius: 1,
266
341
  marginEnd: 13,
267
342
  },
343
+ categoryButtonStyle: {
344
+ borderWidth: 0,
345
+ marginLeft: 5,
346
+ marginRight: 5,
347
+ marginBottom: 10,
348
+ height: 35,
349
+ paddingLeft: 3,
350
+ paddingRight: 3,
351
+ }
268
352
  });
269
353
 
270
354
  export const BusinessProductsList = (props: BusinessProductsListParams) => {
@@ -18,16 +18,24 @@ export const RibbonBox = styled.View`
18
18
  background-color: ${(props: any) => props.theme.colors.primary};
19
19
  padding: 2px 8px;
20
20
  max-width: 180px;
21
-
22
21
  ${(props: any) => props.bgColor && css`
23
22
  background-color: ${props.bgColor};
24
23
  `}
25
-
26
24
  ${(props: any) => props.isRoundRect && css`
27
25
  border-radius: 7.6px;
28
26
  `}
29
-
30
27
  ${(props: any) => props.isCapsule && css`
31
28
  border-radius: 50px;
32
29
  `}
33
- `
30
+ `
31
+
32
+ export const SubCategoriesContainer = styled.View`
33
+ flex-direction: row;
34
+ flex-wrap: wrap;
35
+ margin-bottom: 10px;
36
+ `
37
+
38
+ export const ContainerButton = styled.View`
39
+ `
40
+
41
+ export const HeaderWrapper = styled.View``
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from 'react'
2
- import { View, TouchableOpacity, StyleSheet, SafeAreaView } from 'react-native'
2
+ import { View, TouchableOpacity, StyleSheet, SafeAreaView, Dimensions, Platform, KeyboardAvoidingViewBase, KeyboardAvoidingView } from 'react-native'
3
3
  import { useTheme } from 'styled-components/native';
4
4
  import {
5
5
  BusinessAndProductList,
@@ -12,6 +12,7 @@ import {
12
12
  useConfig
13
13
  } from 'ordering-components/native'
14
14
  import { OButton, OIcon, OModal, OText } from '../shared'
15
+ import Alert from '../../providers/AlertProvider'
15
16
  import { BusinessBasicInformation } from '../BusinessBasicInformation'
16
17
  import { SearchBar } from '../SearchBar'
17
18
  import { BusinessProductsCategories } from '../BusinessProductsCategories'
@@ -22,13 +23,16 @@ import {
22
23
  TopHeader,
23
24
  WrapSearchBar,
24
25
  WrapContent,
25
- BusinessProductsListingContainer
26
+ BusinessProductsListingContainer,
27
+ FiltProductsContainer,
28
+ ContainerSafeAreaView,
29
+ BackgroundGray
26
30
  } from './styles'
27
31
  import { FloatingButton } from '../FloatingButton'
28
32
  import { UpsellingRedirect } from './UpsellingRedirect'
29
33
  import Animated from 'react-native-reanimated'
30
34
 
31
- const PIXELS_TO_SCROLL = 1000
35
+ const PIXELS_TO_SCROLL = 2000
32
36
 
33
37
  const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
34
38
  const {
@@ -45,7 +49,11 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
45
49
  errorQuantityProducts,
46
50
  header,
47
51
  logo,
52
+ alertState,
53
+ setAlertState,
54
+ multiRemoveProducts,
48
55
  getNextProducts,
56
+ handleUpdateProducts
49
57
  } = props
50
58
 
51
59
  const theme = useTheme();
@@ -92,9 +100,12 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
92
100
  const [categoriesLayout, setCategoriesLayout] = useState<any>({})
93
101
  const [productListLayout, setProductListLayout] = useState<any>(null)
94
102
  const [isCategoryClicked, setCategoryClicked] = useState(false)
103
+ const [subcategoriesSelected, setSubcategoriesSelected] = useState([])
95
104
 
105
+ const isCheckoutMultiBusinessEnabled: Boolean = configs?.checkout_multi_business_enabled?.value === '1'
96
106
  const currentCart: any = Object.values(orderState.carts).find((cart: any) => cart?.business?.slug === business?.slug) ?? {}
97
-
107
+ const isOpenFiltProducts = isOpenSearchBar && !!searchValue
108
+ const filtProductsHeight = Platform.OS === 'ios' ? 0 : 35
98
109
  const onRedirect = (route: string, params?: any) => {
99
110
  navigation.navigate(route, params)
100
111
  }
@@ -113,13 +124,19 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
113
124
  }
114
125
 
115
126
  const handleUpsellingPage = () => {
116
- onRedirect('CheckoutNavigator', {
117
- screen: 'CheckoutPage',
118
- cartUuid: currentCart?.uuid,
119
- businessLogo: logo,
120
- businessName: business?.name,
121
- cartTotal: currentCart?.total
122
- })
127
+ if (isCheckoutMultiBusinessEnabled) {
128
+ onRedirect('CheckoutNavigator', {
129
+ screen: 'MultiCheckout'
130
+ })
131
+ } else {
132
+ onRedirect('CheckoutNavigator', {
133
+ screen: 'CheckoutPage',
134
+ cartUuid: currentCart?.uuid,
135
+ businessLogo: logo,
136
+ businessName: business?.name,
137
+ cartTotal: currentCart?.total
138
+ })
139
+ }
123
140
  setOpenUpselling(false)
124
141
  }
125
142
 
@@ -164,25 +181,41 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
164
181
  navigation?.canGoBack() ? navigation.goBack() : navigation.navigate('BottomTab')
165
182
  }
166
183
 
184
+ const adjustBusiness = async (adjustBusinessId: number) => {
185
+ const _carts = orderState?.carts?.[adjustBusinessId]
186
+ const products = _carts?.products
187
+ const unavailableProducts = products.filter((product: any) => product.valid !== true)
188
+ const alreadyRemoved = await _retrieveStoreData('already-removed')
189
+ _removeStoreData('already-removed')
190
+ if (unavailableProducts.length > 0) {
191
+ multiRemoveProducts && await multiRemoveProducts(unavailableProducts, _carts)
192
+ return
193
+ }
194
+
195
+ if (alreadyRemoved === 'removed') {
196
+ setAlertState({ open: true, content: [t('NOT_AVAILABLE_PRODUCT', 'This product is not available.')] })
197
+ }
198
+ }
199
+
167
200
  const removeCartByReOrder = async () => {
168
- const removeCardId = await _retrieveStoreData('remove-cartId')
169
- if (currentCart && removeCardId) {
170
- clearCart(removeCardId)
171
- _removeStoreData('remove-cartId')
172
- showToast(ToastType.Info, t('PRODUCT_REMOVED', 'Products removed from cart'))
201
+ const adjustBusinessId = await _retrieveStoreData('adjust-cart-products')
202
+ if (currentCart && adjustBusinessId) {
203
+ _removeStoreData('adjust-cart-products')
204
+ adjustBusiness(adjustBusinessId)
173
205
  }
174
206
  }
175
207
 
176
208
  useEffect(() => {
177
209
  removeCartByReOrder()
178
- }, [])
210
+ }, [currentCart])
179
211
 
180
212
  return (
181
- <SafeAreaView
213
+ <ContainerSafeAreaView
182
214
  style={{ flex: 1 }}
215
+ isOpenFiltProducts={isOpenFiltProducts}
183
216
  >
184
217
  <Animated.View style={{ position: 'relative' }}>
185
- <TopHeader>
218
+ <TopHeader isIos={Platform.OS === 'ios'}>
186
219
  {!isOpenSearchBar && (
187
220
  <>
188
221
  <View style={{ ...styles.headerItem, flex: 1 }}>
@@ -220,6 +253,47 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
220
253
  )}
221
254
  </TopHeader>
222
255
  </Animated.View>
256
+
257
+ {business?.categories?.length > 0 && isOpenFiltProducts && (
258
+ <FiltProductsContainer
259
+ style={{
260
+ height: Dimensions.get('window').height - filtProductsHeight
261
+ }}
262
+ >
263
+ <View style={{ padding: 20, backgroundColor: theme.colors.white }}>
264
+ <BusinessProductsList
265
+ categories={[
266
+ { id: null, name: t('ALL', 'All') },
267
+ { id: 'featured', name: t('FEATURED', 'Featured') },
268
+ ...business?.categories.sort((a: any, b: any) => a.rank - b.rank)
269
+ ]}
270
+ category={categorySelected}
271
+ categoryState={categoryState}
272
+ businessId={business.id}
273
+ errors={errors}
274
+ onProductClick={onProductClick}
275
+ handleSearchRedirect={handleSearchRedirect}
276
+ featured={featuredProducts}
277
+ searchValue={searchValue}
278
+ handleClearSearch={handleChangeSearch}
279
+ errorQuantityProducts={errorQuantityProducts}
280
+ handleCancelSearch={handleCancel}
281
+ categoriesLayout={categoriesLayout}
282
+ subcategoriesSelected={subcategoriesSelected}
283
+ lazyLoadProductsRecommended={business?.lazy_load_products_recommended}
284
+ setCategoriesLayout={setCategoriesLayout}
285
+ currentCart={currentCart}
286
+ setSubcategoriesSelected={setSubcategoriesSelected}
287
+ onClickCategory={handleChangeCategory}
288
+ handleUpdateProducts={handleUpdateProducts}
289
+ isFiltMode
290
+ />
291
+ </View>
292
+ </FiltProductsContainer>
293
+ )}
294
+ {isOpenFiltProducts && (
295
+ <BackgroundGray />
296
+ )}
223
297
  <BusinessProductsListingContainer
224
298
  stickyHeaderIndices={[2]}
225
299
  style={styles.mainContainer}
@@ -254,6 +328,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
254
328
  lazyLoadProductsRecommended={business?.lazy_load_products_recommended}
255
329
  setSelectedCategoryId={setSelectedCategoryId}
256
330
  setCategoryClicked={setCategoryClicked}
331
+
257
332
  />
258
333
  )}
259
334
  </>
@@ -281,8 +356,13 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
281
356
  errorQuantityProducts={errorQuantityProducts}
282
357
  handleCancelSearch={handleCancel}
283
358
  categoriesLayout={categoriesLayout}
359
+ subcategoriesSelected={subcategoriesSelected}
360
+ lazyLoadProductsRecommended={business?.lazy_load_products_recommended}
284
361
  setCategoriesLayout={setCategoriesLayout}
285
362
  currentCart={currentCart}
363
+ setSubcategoriesSelected={setSubcategoriesSelected}
364
+ onClickCategory={handleChangeCategory}
365
+ handleUpdateProducts={handleUpdateProducts}
286
366
  />
287
367
  </WrapContent>
288
368
  </>
@@ -304,6 +384,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
304
384
  categoryState={categoryState}
305
385
  isBusinessLoading={loading}
306
386
  errorQuantityProducts={errorQuantityProducts}
387
+ handleUpdateProducts={handleUpdateProducts}
307
388
  />
308
389
  </WrapContent>
309
390
  </>
@@ -321,7 +402,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
321
402
  isSecondaryBtn={currentCart?.subtotal < currentCart?.minimum || openUpselling}
322
403
  btnLeftValueShow={currentCart?.subtotal >= currentCart?.minimum && currentCart?.products?.length > 0}
323
404
  btnRightValueShow={currentCart?.subtotal >= currentCart?.minimum && currentCart?.products?.length > 0}
324
- btnLeftValue={currentCart?.products?.length}
405
+ btnLeftValue={currentCart?.products.reduce((prev: number, product: any) => prev + product.quantity, 0)}
325
406
  btnRightValue={parsePrice(currentCart?.total)}
326
407
  disabled={currentCart?.subtotal < currentCart?.minimum || openUpselling}
327
408
  handleClick={() => setOpenUpselling(true)}
@@ -342,7 +423,14 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
342
423
  onRedirect={onRedirect}
343
424
  />
344
425
  )}
345
- </SafeAreaView>
426
+ <Alert
427
+ open={alertState?.open || false}
428
+ title=''
429
+ content={[t('NOT_AVAILABLE_PRODUCTS', 'These products are not available.')]}
430
+ onAccept={() => setAlertState({ open: false, content: [] })}
431
+ onClose={() => setAlertState({ open: false, content: [] })}
432
+ />
433
+ </ContainerSafeAreaView>
346
434
  )
347
435
  }
348
436
 
@@ -1,5 +1,8 @@
1
1
  import styled, { css } from 'styled-components/native'
2
2
 
3
+ export const ContainerSafeAreaView = styled.SafeAreaView`
4
+ `
5
+
3
6
  export const WrapHeader = styled.View`
4
7
  position: relative;
5
8
  `
@@ -11,6 +14,7 @@ export const TopHeader = styled.View`
11
14
  z-index: 1;
12
15
  height: 60px;
13
16
  min-height: 60px;
17
+ margin-top: ${(props : any) => props.isIos ? '0' : '40px'};
14
18
  `
15
19
  export const AddressInput = styled.TouchableOpacity`
16
20
  flex: 1;
@@ -33,3 +37,21 @@ export const BusinessProductsListingContainer = styled.ScrollView`
33
37
  margin-bottom: 50px;
34
38
  `}
35
39
  `
40
+
41
+ export const FiltProductsContainer = styled.ScrollView`
42
+ position: absolute;
43
+ width: 100%;
44
+ z-index: 2000;
45
+ top: ${(props : any) => props.isIos ? '40px': '80px'};
46
+ margin-top: 20px;
47
+ `
48
+
49
+ export const BackgroundGray = styled.View`
50
+ flex: 1;
51
+ height: 100%;
52
+ background-color: rgba(0,0,0,0.5);
53
+ position: absolute;
54
+ margin-top: 100px;
55
+ z-index: 100;
56
+ width: 100%;
57
+ `
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import {
3
3
  BusinessReviews as BusinessReviewController,
4
4
  useLanguage,
@@ -22,6 +22,7 @@ import {
22
22
  import { BusinessReviewsParams } from '../../types';
23
23
  import { ProgressBar, TouchableRipple } from 'react-native-paper';
24
24
  import moment from 'moment';
25
+ import { setLocalMoment } from '../../utils';
25
26
 
26
27
  const BusinessReviewsUI = (props: BusinessReviewsParams) => {
27
28
  const { businessState, reviewsList } = props;
@@ -99,6 +100,10 @@ const BusinessReviewsUI = (props: BusinessReviewsParams) => {
99
100
  </View>
100
101
  );
101
102
 
103
+ useEffect(() => {
104
+ setLocalMoment(moment, t)
105
+ }, [])
106
+
102
107
  return (
103
108
  <BusinessReviewsContainer>
104
109
  <BusinessReviewContent
@@ -45,7 +45,6 @@ export const BusinessTypeFilterUI = (props: BusinessTypeFilterParams) => {
45
45
  const renderTypes = ({ item }: any) => {
46
46
  return (
47
47
  <TouchableOpacity
48
- key={item.id}
49
48
  onPress={() => handleChangeBusinessType(item.id)}
50
49
  style={{
51
50
  height: 34,
@@ -103,7 +102,7 @@ export const BusinessTypeFilterUI = (props: BusinessTypeFilterParams) => {
103
102
  showsHorizontalScrollIndicator={false}
104
103
  data={typesState?.types}
105
104
  renderItem={renderTypes}
106
- keyExtractor={(type) => type.name}
105
+ keyExtractor={(type, index) => `${type.name}_${index}`}
107
106
  />
108
107
  <TouchableOpacity
109
108
  style={{ marginLeft: 15 }}