ordering-ui-react-native 0.15.52 → 0.15.54-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 (188) 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 +9 -23
  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/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 +2 -2
  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/ProductItemAccordion/index.tsx +2 -2
  51. package/themes/business/src/components/shared/OModal.tsx +1 -1
  52. package/themes/business/src/types/index.tsx +5 -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 +99 -26
  59. package/themes/kiosk/src/components/Cart/styles.tsx +6 -0
  60. package/themes/kiosk/src/components/CartBottomSheet/index.tsx +9 -2
  61. package/themes/kiosk/src/components/CartContent/index.tsx +0 -11
  62. package/themes/kiosk/src/components/CartItem/index.tsx +4 -3
  63. package/themes/kiosk/src/components/CategoriesMenu/index.tsx +107 -62
  64. package/themes/kiosk/src/components/Checkout/index.tsx +40 -22
  65. package/themes/kiosk/src/components/CustomerName/index.tsx +0 -6
  66. package/themes/kiosk/src/components/DrawerView/index.tsx +1 -0
  67. package/themes/kiosk/src/components/DrawerView/styles.tsx +2 -2
  68. package/themes/kiosk/src/components/NavBar/index.tsx +29 -20
  69. package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
  70. package/themes/kiosk/src/components/OrderDetails/index.tsx +165 -65
  71. package/themes/kiosk/src/components/OrderDetails/styles.tsx +5 -0
  72. package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +9 -11
  73. package/themes/kiosk/src/components/PaymentOptions/index.tsx +56 -54
  74. package/themes/kiosk/src/components/ProductForm/index.tsx +7 -8
  75. package/themes/kiosk/src/components/ProductItemAccordion/index.tsx +2 -2
  76. package/themes/kiosk/src/components/ProductOption/index.tsx +1 -1
  77. package/themes/kiosk/src/components/ProductOptionSubOption/index.tsx +3 -1
  78. package/themes/kiosk/src/components/UpsellingProducts/index.tsx +16 -5
  79. package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
  80. package/themes/kiosk/src/types/index.d.ts +3 -0
  81. package/themes/original/index.tsx +169 -4
  82. package/themes/original/src/components/ActiveOrders/index.tsx +15 -132
  83. package/themes/original/src/components/ActiveOrders/styles.tsx +0 -54
  84. package/themes/original/src/components/AddressForm/index.tsx +1 -1
  85. package/themes/original/src/components/AddressList/index.tsx +30 -18
  86. package/themes/original/src/components/AppleLogin/index.tsx +54 -21
  87. package/themes/original/src/components/BusinessBasicInformation/index.tsx +136 -45
  88. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +4 -0
  89. package/themes/original/src/components/BusinessController/index.tsx +48 -11
  90. package/themes/original/src/components/BusinessController/styles.tsx +27 -0
  91. package/themes/original/src/components/BusinessFeaturedController/index.tsx +20 -1
  92. package/themes/original/src/components/BusinessFeaturedController/styles.tsx +23 -0
  93. package/themes/original/src/components/BusinessItemAccordion/index.tsx +8 -5
  94. package/themes/original/src/components/BusinessItemAccordion/styles.tsx +3 -1
  95. package/themes/original/src/components/BusinessListingSearch/index.tsx +196 -58
  96. package/themes/original/src/components/BusinessListingSearch/styles.tsx +22 -2
  97. package/themes/original/src/components/BusinessPreorder/index.tsx +1 -1
  98. package/themes/original/src/components/BusinessProductsCategories/index.tsx +2 -2
  99. package/themes/original/src/components/BusinessProductsList/CategoryDescription/index.tsx +44 -0
  100. package/themes/original/src/components/BusinessProductsList/index.tsx +119 -35
  101. package/themes/original/src/components/BusinessProductsList/styles.tsx +12 -4
  102. package/themes/original/src/components/BusinessProductsListing/index.tsx +109 -21
  103. package/themes/original/src/components/BusinessProductsListing/styles.tsx +22 -0
  104. package/themes/original/src/components/BusinessReviews/index.tsx +10 -26
  105. package/themes/original/src/components/BusinessTypeFilter/index.tsx +1 -2
  106. package/themes/original/src/components/BusinessesListing/index.tsx +127 -66
  107. package/themes/original/src/components/BusinessesListing/styles.tsx +11 -3
  108. package/themes/original/src/components/Cart/index.tsx +60 -41
  109. package/themes/original/src/components/Checkout/index.tsx +48 -32
  110. package/themes/original/src/components/DriverTips/index.tsx +17 -12
  111. package/themes/original/src/components/Favorite/index.tsx +92 -0
  112. package/themes/original/src/components/Favorite/styles.tsx +22 -0
  113. package/themes/original/src/components/FavoriteList/index.tsx +298 -0
  114. package/themes/original/src/components/FavoriteList/styles.tsx +5 -0
  115. package/themes/original/src/components/ForgotPasswordForm/index.tsx +84 -4
  116. package/themes/original/src/components/GPSButton/index.tsx +15 -8
  117. package/themes/original/src/components/GoogleMap/index.tsx +1 -0
  118. package/themes/original/src/components/Help/index.tsx +21 -4
  119. package/themes/original/src/components/HighestRatedBusinesses/index.tsx +18 -1
  120. package/themes/original/src/components/Home/index.tsx +1 -1
  121. package/themes/original/src/components/LastOrders/index.tsx +12 -1
  122. package/themes/original/src/components/LoginForm/Otp/index.tsx +91 -0
  123. package/themes/original/src/components/LoginForm/Otp/styles.tsx +7 -0
  124. package/themes/original/src/components/LoginForm/index.tsx +332 -164
  125. package/themes/original/src/components/LoginForm/styles.tsx +1 -3
  126. package/themes/original/src/components/MessageListing/index.tsx +10 -1
  127. package/themes/original/src/components/Messages/index.tsx +1 -1
  128. package/themes/original/src/components/MomentOption/index.tsx +10 -1
  129. package/themes/original/src/components/MomentOption/styles.tsx +1 -1
  130. package/themes/original/src/components/MultiCartsPaymethodsAndWallets/index.tsx +243 -0
  131. package/themes/original/src/components/MultiCartsPaymethodsAndWallets/styles.tsx +46 -0
  132. package/themes/original/src/components/MultiCheckout/index.tsx +298 -0
  133. package/themes/original/src/components/MultiCheckout/styles.tsx +59 -0
  134. package/themes/original/src/components/MultiOrdersDetails/SingleOrderCard.tsx +372 -0
  135. package/themes/original/src/components/MultiOrdersDetails/index.tsx +258 -0
  136. package/themes/original/src/components/MultiOrdersDetails/styles.tsx +50 -0
  137. package/themes/original/src/components/MyOrders/index.tsx +120 -32
  138. package/themes/original/src/components/MyOrders/styles.tsx +8 -1
  139. package/themes/original/src/components/OrderDetails/OrderHistory.tsx +167 -0
  140. package/themes/original/src/components/OrderDetails/index.tsx +117 -46
  141. package/themes/original/src/components/OrderDetails/styles.tsx +1 -2
  142. package/themes/original/src/components/OrderSummary/index.tsx +3 -3
  143. package/themes/original/src/components/OrderTypeSelector/index.tsx +4 -2
  144. package/themes/original/src/components/OrdersOption/PreviousBusinessOrdered/index.tsx +153 -0
  145. package/themes/original/src/components/OrdersOption/PreviousBusinessOrdered/styles.tsx +6 -0
  146. package/themes/original/src/components/OrdersOption/PreviousProductsOrdered/index.tsx +53 -0
  147. package/themes/original/src/components/OrdersOption/PreviousProductsOrdered/styles.tsx +6 -0
  148. package/themes/original/src/components/OrdersOption/index.tsx +130 -38
  149. package/themes/original/src/components/OrdersOption/styles.tsx +4 -1
  150. package/themes/original/src/components/PaymentOptionCash/index.tsx +2 -2
  151. package/themes/original/src/components/PaymentOptionWallet/index.tsx +17 -23
  152. package/themes/original/src/components/PaymentOptionWallet/styles.tsx +1 -1
  153. package/themes/original/src/components/PaymentOptions/index.tsx +57 -36
  154. package/themes/original/src/components/PhoneInputNumber/index.tsx +1 -1
  155. package/themes/original/src/components/PreviousOrders/index.tsx +18 -147
  156. package/themes/original/src/components/ProductForm/index.tsx +70 -62
  157. package/themes/original/src/components/ProductForm/styles.tsx +0 -1
  158. package/themes/original/src/components/ProductItemAccordion/index.tsx +2 -2
  159. package/themes/original/src/components/ProductOptionSubOption/index.tsx +18 -12
  160. package/themes/original/src/components/Promotions/index.tsx +151 -133
  161. package/themes/original/src/components/Promotions/styles.tsx +3 -23
  162. package/themes/original/src/components/SearchBar/index.tsx +10 -4
  163. package/themes/original/src/components/Sessions/index.tsx +160 -0
  164. package/themes/original/src/components/Sessions/styles.tsx +15 -0
  165. package/themes/original/src/components/SignupForm/index.tsx +335 -128
  166. package/themes/original/src/components/SingleOrderCard/index.tsx +282 -0
  167. package/themes/original/src/components/SingleOrderCard/styles.tsx +54 -0
  168. package/themes/original/src/components/SingleProductCard/index.tsx +59 -17
  169. package/themes/original/src/components/StripeElementsForm/index.tsx +16 -8
  170. package/themes/original/src/components/StripeElementsForm/naked.tsx +2 -2
  171. package/themes/original/src/components/UpsellingProducts/index.tsx +86 -74
  172. package/themes/original/src/components/UserDetails/index.tsx +5 -96
  173. package/themes/original/src/components/UserFormDetails/index.tsx +34 -24
  174. package/themes/original/src/components/UserProfile/index.tsx +53 -6
  175. package/themes/original/src/components/UserProfileForm/index.tsx +20 -18
  176. package/themes/original/src/components/UserVerification/index.tsx +178 -192
  177. package/themes/original/src/components/VerifyPhone/index.tsx +10 -7
  178. package/themes/original/src/components/VerifyPhone/styles.tsx +2 -1
  179. package/themes/original/src/components/Wallets/index.tsx +76 -9
  180. package/themes/original/src/components/Wallets/styles.tsx +21 -0
  181. package/themes/original/src/components/shared/OModal.tsx +4 -2
  182. package/themes/original/src/config/constants.tsx +6 -6
  183. package/themes/original/src/types/index.tsx +193 -32
  184. package/themes/original/src/utils/index.tsx +85 -2
  185. package/themes/single-business/src/components/AddressList/index.tsx +1 -1
  186. package/themes/single-business/src/components/OrderTypeSelector/index.tsx +1 -1
  187. package/themes/single-business/src/components/UserProfile/index.tsx +1 -1
  188. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
@@ -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>{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;
@@ -90,36 +91,19 @@ const BusinessReviewsUI = (props: BusinessReviewsParams) => {
90
91
  </View>
91
92
  );
92
93
 
93
- const ReviewItem = ({ comment, created_at, total, customer }: any) => (
94
+ const ReviewItem = ({ comment, created_at, total }: any) => (
94
95
  <View style={{ marginBottom: 30 }}>
95
- <View
96
- style={{ flexDirection: 'row', marginBottom: 19, alignItems: 'center' }}>
97
- <OIcon
98
- url={theme.images.dummies.customerPhoto}
99
- width={38}
100
- height={38}
101
- style={{
102
- borderRadius: 7.6,
103
- borderWidth: 1,
104
- borderColor: theme.colors.border,
105
- marginEnd: 9,
106
- }}
107
- />
108
- <View>
109
- <OText size={12} color={theme.colors.textNormal} weight={'500'}>
110
- {customer?.name || 'Jane Cooper'}
111
- </OText>
112
- <OText size={10} color={theme.colors.textSecondary}>
113
- {moment(created_at).format('MMMM d, yyyy • hh:mm')}
114
- </OText>
115
- </View>
116
- </View>
117
- <OText size={10} color={theme.colors.textNormal}>
118
- {comment}
96
+ <OText size={12} color={theme.colors.textSecondary}>
97
+ {moment(created_at).format('MMMM d, yyyy hh:mm')}
119
98
  </OText>
99
+ <OText size={12} color={theme.colors.textNormal}>{comment}</OText>
120
100
  </View>
121
101
  );
122
102
 
103
+ useEffect(() => {
104
+ setLocalMoment(moment, t)
105
+ }, [])
106
+
123
107
  return (
124
108
  <BusinessReviewsContainer>
125
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 }}