ordering-ui-react-native 0.15.30 → 0.15.31-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 (170) hide show
  1. package/package.json +4 -2
  2. package/src/DeliveryApp.tsx +43 -1
  3. package/src/components/BusinessController/index.tsx +8 -2
  4. package/src/components/BusinessTypeFilter/index.tsx +4 -1
  5. package/src/components/BusinessesListing/index.tsx +1 -1
  6. package/src/components/Checkout/index.tsx +23 -3
  7. package/src/components/DriverTips/index.tsx +11 -6
  8. package/src/components/LanguageSelector/index.tsx +7 -2
  9. package/src/components/LoginForm/index.tsx +3 -1
  10. package/src/components/OrderDetails/index.tsx +2 -2
  11. package/src/components/PaymentOptions/index.tsx +9 -16
  12. package/src/components/PaymentOptionsWebView/index.tsx +123 -124
  13. package/src/components/SignupForm/index.tsx +3 -1
  14. package/src/components/SingleProductCard/index.tsx +16 -4
  15. package/src/components/StripeElementsForm/index.tsx +27 -48
  16. package/src/components/UpsellingProducts/index.tsx +1 -1
  17. package/src/components/UserProfileForm/index.tsx +63 -6
  18. package/src/components/UserProfileForm/styles.tsx +8 -0
  19. package/src/components/VerifyPhone/styles.tsx +1 -2
  20. package/src/components/shared/OModal.tsx +1 -1
  21. package/src/config.json +0 -2
  22. package/src/hooks/useCountdownTimer.tsx +26 -0
  23. package/src/navigators/HomeNavigator.tsx +6 -0
  24. package/src/pages/BusinessProductsList.tsx +1 -0
  25. package/src/pages/BusinessesListing.tsx +1 -1
  26. package/src/pages/Checkout.tsx +1 -1
  27. package/src/pages/Sessions.tsx +22 -0
  28. package/src/types/index.tsx +5 -11
  29. package/src/utils/index.tsx +68 -1
  30. package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +103 -15
  31. package/themes/business/src/components/AcceptOrRejectOrder/styles.tsx +6 -0
  32. package/themes/business/src/components/Chat/index.tsx +38 -86
  33. package/themes/business/src/components/DriverMap/index.tsx +6 -5
  34. package/themes/business/src/components/Home/index.tsx +128 -55
  35. package/themes/business/src/components/Home/styles.tsx +8 -1
  36. package/themes/business/src/components/LoginForm/index.tsx +89 -2
  37. package/themes/business/src/components/LoginForm/styles.tsx +6 -0
  38. package/themes/business/src/components/LogoutButton/index.tsx +1 -1
  39. package/themes/business/src/components/NewOrderNotification/index.tsx +79 -105
  40. package/themes/business/src/components/OrderDetails/Business.tsx +1 -1
  41. package/themes/business/src/components/OrderDetails/Delivery.tsx +32 -15
  42. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +157 -89
  43. package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +6 -0
  44. package/themes/business/src/components/OrderDetails/styles.tsx +7 -0
  45. package/themes/business/src/components/OrdersListManager/index.tsx +52 -49
  46. package/themes/business/src/components/OrdersOption/index.tsx +58 -51
  47. package/themes/business/src/components/PreviousOrders/index.tsx +58 -17
  48. package/themes/business/src/components/shared/OModal.tsx +1 -1
  49. package/themes/business/src/types/index.tsx +5 -1
  50. package/themes/doordash/src/components/BusinessesListing/index.tsx +1 -1
  51. package/themes/doordash/src/components/LoginForm/index.tsx +1 -2
  52. package/themes/instacart/src/components/BusinessesListing/index.tsx +1 -1
  53. package/themes/kiosk/src/components/Cart/index.tsx +98 -24
  54. package/themes/kiosk/src/components/Cart/styles.tsx +6 -0
  55. package/themes/kiosk/src/components/CartBottomSheet/index.tsx +1 -1
  56. package/themes/kiosk/src/components/CartBottomSheet/styles.tsx +1 -1
  57. package/themes/kiosk/src/components/CartContent/index.tsx +13 -3
  58. package/themes/kiosk/src/components/CartItem/index.tsx +20 -8
  59. package/themes/kiosk/src/components/Checkout/index.tsx +34 -22
  60. package/themes/kiosk/src/components/CustomerName/index.tsx +7 -8
  61. package/themes/kiosk/src/components/Intro/index.tsx +13 -13
  62. package/themes/kiosk/src/components/NavBar/index.tsx +14 -14
  63. package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
  64. package/themes/kiosk/src/components/OrderDetails/index.tsx +145 -45
  65. package/themes/kiosk/src/components/OrderDetails/styles.tsx +5 -0
  66. package/themes/kiosk/src/components/OrderSummary/index.tsx +1 -1
  67. package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +10 -12
  68. package/themes/kiosk/src/components/PaymentOptions/index.tsx +1 -1
  69. package/themes/kiosk/src/components/ProductForm/index.tsx +174 -125
  70. package/themes/kiosk/src/components/ProductForm/styles.tsx +1 -1
  71. package/themes/kiosk/src/components/ProductOption/index.tsx +1 -0
  72. package/themes/kiosk/src/components/ProductOption/styles.tsx +1 -0
  73. package/themes/kiosk/src/components/UpsellingProducts/index.tsx +48 -34
  74. package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
  75. package/themes/kiosk/src/types/index.d.ts +2 -0
  76. package/themes/original/index.tsx +178 -1
  77. package/themes/original/src/components/AddressForm/index.tsx +15 -10
  78. package/themes/original/src/components/AddressList/index.tsx +56 -18
  79. package/themes/original/src/components/AppleLogin/index.tsx +117 -78
  80. package/themes/original/src/components/BusinessBasicInformation/index.tsx +96 -45
  81. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +28 -1
  82. package/themes/original/src/components/BusinessController/index.tsx +52 -22
  83. package/themes/original/src/components/BusinessController/styles.tsx +22 -0
  84. package/themes/original/src/components/BusinessFeaturedController/index.tsx +20 -1
  85. package/themes/original/src/components/BusinessFeaturedController/styles.tsx +23 -0
  86. package/themes/original/src/components/BusinessListingSearch/index.tsx +121 -7
  87. package/themes/original/src/components/BusinessListingSearch/styles.tsx +14 -1
  88. package/themes/original/src/components/BusinessMenuList/index.tsx +11 -4
  89. package/themes/original/src/components/BusinessPreorder/index.tsx +142 -122
  90. package/themes/original/src/components/BusinessProductsCategories/index.tsx +9 -7
  91. package/themes/original/src/components/BusinessProductsList/CategoryDescription/index.tsx +44 -0
  92. package/themes/original/src/components/BusinessProductsList/index.tsx +140 -37
  93. package/themes/original/src/components/BusinessProductsList/styles.tsx +29 -2
  94. package/themes/original/src/components/BusinessProductsListing/index.tsx +108 -14
  95. package/themes/original/src/components/BusinessProductsListing/styles.tsx +22 -0
  96. package/themes/original/src/components/BusinessReviews/index.tsx +4 -25
  97. package/themes/original/src/components/BusinessTypeFilter/index.tsx +1 -2
  98. package/themes/original/src/components/BusinessesListing/index.tsx +74 -70
  99. package/themes/original/src/components/Cart/index.tsx +21 -17
  100. package/themes/original/src/components/CartContent/index.tsx +2 -2
  101. package/themes/original/src/components/Checkout/index.tsx +59 -48
  102. package/themes/original/src/components/DriverTips/index.tsx +17 -12
  103. package/themes/original/src/components/ForgotPasswordForm/index.tsx +84 -4
  104. package/themes/original/src/components/GPSButton/index.tsx +15 -8
  105. package/themes/original/src/components/GoogleMap/index.tsx +1 -0
  106. package/themes/original/src/components/Help/index.tsx +21 -4
  107. package/themes/original/src/components/HighestRatedBusinesses/index.tsx +97 -89
  108. package/themes/original/src/components/Home/index.tsx +1 -1
  109. package/themes/original/src/components/LastOrders/index.tsx +12 -1
  110. package/themes/original/src/components/LoginForm/Otp/index.tsx +90 -0
  111. package/themes/original/src/components/LoginForm/Otp/styles.tsx +7 -0
  112. package/themes/original/src/components/LoginForm/index.tsx +394 -155
  113. package/themes/original/src/components/LoginForm/styles.tsx +7 -4
  114. package/themes/original/src/components/LogoutButton/index.tsx +7 -1
  115. package/themes/original/src/components/MessageListing/index.tsx +10 -1
  116. package/themes/original/src/components/Messages/index.tsx +34 -25
  117. package/themes/original/src/components/Messages/styles.tsx +1 -3
  118. package/themes/original/src/components/MomentOption/index.tsx +10 -1
  119. package/themes/original/src/components/MomentOption/styles.tsx +1 -1
  120. package/themes/original/src/components/OrderDetails/index.tsx +56 -33
  121. package/themes/original/src/components/OrderDetails/styles.tsx +1 -2
  122. package/themes/original/src/components/OrderProgress/index.tsx +4 -4
  123. package/themes/original/src/components/OrderProgress/styles.tsx +1 -0
  124. package/themes/original/src/components/OrderSummary/index.tsx +3 -3
  125. package/themes/original/src/components/OrderTypeSelector/index.tsx +4 -2
  126. package/themes/original/src/components/OrdersOption/index.tsx +55 -58
  127. package/themes/original/src/components/OrdersOption/styles.tsx +0 -6
  128. package/themes/original/src/components/PaymentOptionCash/index.tsx +2 -2
  129. package/themes/original/src/components/PaymentOptionWallet/index.tsx +22 -24
  130. package/themes/original/src/components/PaymentOptionWallet/styles.tsx +1 -1
  131. package/themes/original/src/components/PaymentOptions/index.tsx +9 -21
  132. package/themes/original/src/components/PhoneInputNumber/index.tsx +1 -1
  133. package/themes/original/src/components/PreviousOrders/index.tsx +16 -14
  134. package/themes/original/src/components/ProductForm/index.tsx +76 -61
  135. package/themes/original/src/components/ProductForm/styles.tsx +2 -2
  136. package/themes/original/src/components/ProductItemAccordion/index.tsx +2 -2
  137. package/themes/original/src/components/ProductOptionSubOption/index.tsx +18 -12
  138. package/themes/original/src/components/Promotions/index.tsx +250 -0
  139. package/themes/original/src/components/Promotions/styles.tsx +60 -0
  140. package/themes/original/src/components/ReviewOrder/index.tsx +10 -9
  141. package/themes/original/src/components/ReviewProducts/index.tsx +1 -1
  142. package/themes/original/src/components/SearchBar/index.tsx +4 -1
  143. package/themes/original/src/components/Sessions/index.tsx +160 -0
  144. package/themes/original/src/components/Sessions/styles.tsx +15 -0
  145. package/themes/original/src/components/SignupForm/index.tsx +9 -4
  146. package/themes/original/src/components/SingleProductCard/index.tsx +47 -21
  147. package/themes/original/src/components/SingleProductCard/styles.tsx +28 -1
  148. package/themes/original/src/components/StripeElementsForm/index.tsx +55 -74
  149. package/themes/original/src/components/TaxInformation/index.tsx +10 -4
  150. package/themes/original/src/components/UpsellingProducts/index.tsx +86 -74
  151. package/themes/original/src/components/UserDetails/index.tsx +4 -95
  152. package/themes/original/src/components/UserFormDetails/index.tsx +34 -24
  153. package/themes/original/src/components/UserProfile/index.tsx +62 -14
  154. package/themes/original/src/components/UserProfileForm/index.tsx +20 -18
  155. package/themes/original/src/components/UserVerification/index.tsx +178 -192
  156. package/themes/original/src/components/VerifyPhone/index.tsx +10 -7
  157. package/themes/original/src/components/VerifyPhone/styles.tsx +2 -1
  158. package/themes/original/src/components/Wallets/index.tsx +76 -9
  159. package/themes/original/src/components/Wallets/styles.tsx +21 -0
  160. package/themes/original/src/components/shared/HeaderTitle.tsx +21 -0
  161. package/themes/original/src/components/shared/OModal.tsx +4 -2
  162. package/themes/original/src/components/shared/index.tsx +2 -0
  163. package/themes/original/src/config/constants.tsx +6 -6
  164. package/themes/original/src/types/index.tsx +68 -6
  165. package/themes/original/src/utils/index.tsx +28 -2
  166. package/themes/single-business/src/components/AddressList/index.tsx +1 -1
  167. package/themes/single-business/src/components/OrderTypeSelector/index.tsx +6 -6
  168. package/themes/single-business/src/components/UserProfile/index.tsx +1 -1
  169. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
  170. package/src/components/StripeMethodForm/index.tsx +0 -174
@@ -4,11 +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 } 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
+ import { shape } from '../../utils'
13
+ import { CategoryDescriptionMemoized } from './CategoryDescription';
12
14
 
13
15
  const BusinessProductsListUI = (props: BusinessProductsListParams) => {
14
16
  const {
@@ -27,7 +29,13 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
27
29
  handleCancelSearch,
28
30
  categoriesLayout,
29
31
  setCategoriesLayout,
30
- currentCart
32
+ currentCart,
33
+ setSubcategoriesSelected,
34
+ subcategoriesSelected,
35
+ onClickCategory,
36
+ lazyLoadProductsRecommended,
37
+ handleUpdateProducts,
38
+ isFiltMode
31
39
  } = props;
32
40
 
33
41
  const [, t] = useLanguage();
@@ -43,20 +51,86 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
43
51
  setCategoriesLayout(_categoriesLayout)
44
52
  }
45
53
 
46
- return (
47
- <ProductsContainer>
48
- {category.id &&
49
- categoryState.products?.sort((a: any, b: any) => a.rank - b.rank).map((product: any) => (
50
- <SingleProductCard
51
- key={'prod_' + product.id}
52
- isSoldOut={product.inventoried && !product.quantity}
53
- product={product}
54
- businessId={businessId}
55
- onProductClick={() => onProductClick(product)}
56
- productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
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 }}
57
84
  />
58
- ))}
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
+ }
59
107
 
108
+ return (
109
+ <ProductsContainer renderToHardwareTextureAndroid={categoryState.loading || isBusinessLoading}>
110
+ <HeaderWrapper>
111
+ {category?.subcategories?.length > 0 && (
112
+ <SubcategoriesComponent category={category} />
113
+ )}
114
+ </HeaderWrapper>
115
+ {category.id &&
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
+ }
60
134
  {!category.id &&
61
135
  featured &&
62
136
  categoryState?.products?.find((product: any) => product.featured) && (
@@ -71,11 +145,13 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
71
145
  (product: any, i: any) =>
72
146
  product.featured && (
73
147
  <SingleProductCard
74
- key={i}
148
+ key={'feat_' + product.id + `_${i}`}
75
149
  isSoldOut={product.inventoried && !product.quantity}
76
150
  product={product}
77
151
  businessId={businessId}
152
+ categoryState={categoryState}
78
153
  onProductClick={onProductClick}
154
+ handleUpdateProducts={handleUpdateProducts}
79
155
  productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
80
156
  />
81
157
  ),
@@ -85,9 +161,14 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
85
161
  )}
86
162
 
87
163
  {!category?.id && categories.filter(category => category?.id !== null).map((category, i, _categories) => {
88
- const products = !isUseParentCategory
164
+ const _products = !isUseParentCategory
89
165
  ? categoryState?.products?.filter((product: any) => product?.category_id === category?.id) ?? []
90
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
91
172
 
92
173
  const shortCategoryDescription = category?.description?.length > 80 ? `${category?.description?.substring(0, 80)}...` : category?.description
93
174
 
@@ -110,15 +191,33 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
110
191
  <OText size={16} weight="600">
111
192
  {category.name}
112
193
  </OText>
194
+ {category?.ribbon?.enabled && (
195
+ <RibbonBox
196
+ bgColor={category?.ribbon?.color}
197
+ isRoundRect={category?.ribbon?.shape === shape?.rectangleRound}
198
+ isCapsule={category?.ribbon?.shape === shape?.capsuleShape}
199
+ >
200
+ <OText
201
+ size={10}
202
+ weight={'400'}
203
+ color={theme.colors.white}
204
+ numberOfLines={2}
205
+ ellipsizeMode='tail'
206
+ lineHeight={13}
207
+ >
208
+ {category?.ribbon?.text}
209
+ </OText>
210
+ </RibbonBox>
211
+ )}
113
212
  </View>
114
213
  {!!category?.description && (
115
214
  <View style={{ position: 'relative' }}>
116
- <OText size={12} weight={'500'} mBottom={5}>
215
+ <OText size={12} weight={'500'} mBottom={10} color='#909BA9'>
117
216
  {shortCategoryDescription}
118
217
  {category?.description?.length > 80 && (
119
218
  <OButton
120
219
  style={{ height: 15, paddingRight: 0, paddingLeft: 0, borderWidth: 0 }}
121
- text={t('SEE_MORE', 'See more')}
220
+ text={t('VIEW_MORE', 'View more')}
122
221
  parentStyle={{ padding: 0 }}
123
222
  onClick={() => setOpenDescription(category)}
124
223
  bgColor='transparent'
@@ -133,14 +232,19 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
133
232
  </OText>
134
233
  </View>
135
234
  )}
235
+ {category?.subcategories?.length > 0 && !isFiltMode && (
236
+ <SubcategoriesComponent category={category} />
237
+ )}
136
238
  <>
137
239
  {products.sort((a: any, b: any) => a.rank - b.rank).map((product: any, i: any) => (
138
240
  <SingleProductCard
139
- key={i}
241
+ key={`${product?.id}_${i}`}
140
242
  isSoldOut={product.inventoried && !product.quantity}
141
243
  businessId={businessId}
142
244
  product={product}
245
+ categoryState={categoryState}
143
246
  onProductClick={onProductClick}
247
+ handleUpdateProducts={handleUpdateProducts}
144
248
  productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
145
249
  />
146
250
  ))}
@@ -176,6 +280,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
176
280
  !isBusinessLoading &&
177
281
  categoryState.products.length === 0 &&
178
282
  !errors &&
283
+ !isFiltMode &&
179
284
  !(
180
285
  (searchValue && errorQuantityProducts) ||
181
286
  (!searchValue && !errorQuantityProducts)
@@ -215,29 +320,18 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
215
320
  <OText>{e}</OText>
216
321
  </ErrorMessage>
217
322
  ))}
218
- <OModal
219
- open={!!openDescription}
220
- title={openDescription?.name}
221
- onClose={() => setOpenDescription(null)}
222
- >
223
- <ScrollView style={{ padding: 20 }}>
224
- {!!openDescription?.image && (
225
- <OIcon
226
- url={optimizeImage(openDescription?.image, 'h_100,c_limit')}
227
- width={240}
228
- height={240}
229
- style={{ borderRadius: 7.6 }}
230
- />
231
- )}
232
- <OText>{openDescription?.description}</OText>
233
- </ScrollView>
234
- </OModal>
323
+ {!!openDescription && (
324
+ <CategoryDescriptionMemoized
325
+ openDescription={openDescription}
326
+ setOpenDescription={setOpenDescription}
327
+ />
328
+ )}
235
329
  </ProductsContainer>
236
330
  );
237
331
  };
238
332
 
239
333
  const bpStyles = StyleSheet.create({
240
- catWrap: { flexDirection: 'row', alignItems: 'center', height: 41, marginBottom: 19 },
334
+ catWrap: { flexDirection: 'row', alignItems: 'center', marginBottom: 19 },
241
335
  catIcon: {
242
336
  borderRadius: 7.6,
243
337
  shadowColor: '#000000',
@@ -246,6 +340,15 @@ const bpStyles = StyleSheet.create({
246
340
  shadowRadius: 1,
247
341
  marginEnd: 13,
248
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
+ }
249
352
  });
250
353
 
251
354
  export const BusinessProductsList = (props: BusinessProductsListParams) => {
@@ -1,4 +1,4 @@
1
- import styled from 'styled-components/native'
1
+ import styled, { css } from 'styled-components/native'
2
2
 
3
3
  export const ProductsContainer = styled.View`
4
4
  `
@@ -11,4 +11,31 @@ export const ErrorMessage = styled.View`
11
11
 
12
12
  export const WrapperNotFound = styled.View`
13
13
  height: 500px;
14
- `
14
+ `
15
+
16
+ export const RibbonBox = styled.View`
17
+ margin-left: 5px;
18
+ background-color: ${(props: any) => props.theme.colors.primary};
19
+ padding: 2px 8px;
20
+ max-width: 180px;
21
+ ${(props: any) => props.bgColor && css`
22
+ background-color: ${props.bgColor};
23
+ `}
24
+ ${(props: any) => props.isRoundRect && css`
25
+ border-radius: 7.6px;
26
+ `}
27
+ ${(props: any) => props.isCapsule && css`
28
+ border-radius: 50px;
29
+ `}
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,22 +12,27 @@ 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'
18
19
  import { BusinessProductsList } from '../BusinessProductsList'
19
20
  import { BusinessProductsListingParams } from '../../types'
21
+ import { _retrieveStoreData, _removeStoreData } from '../../providers/StoreUtil';
20
22
  import {
21
23
  TopHeader,
22
24
  WrapSearchBar,
23
25
  WrapContent,
24
- BusinessProductsListingContainer
26
+ BusinessProductsListingContainer,
27
+ FiltProductsContainer,
28
+ ContainerSafeAreaView,
29
+ BackgroundGray
25
30
  } from './styles'
26
31
  import { FloatingButton } from '../FloatingButton'
27
32
  import { UpsellingRedirect } from './UpsellingRedirect'
28
33
  import Animated from 'react-native-reanimated'
29
34
 
30
- const PIXELS_TO_SCROLL = 1000
35
+ const PIXELS_TO_SCROLL = 2000
31
36
 
32
37
  const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
33
38
  const {
@@ -44,13 +49,16 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
44
49
  errorQuantityProducts,
45
50
  header,
46
51
  logo,
52
+ alertState,
53
+ setAlertState,
54
+ multiRemoveProducts,
47
55
  getNextProducts,
48
56
  } = props
49
57
 
50
58
  const theme = useTheme();
51
59
  const [, t] = useLanguage()
52
60
  const [{ auth }] = useSession()
53
- const [orderState] = useOrder()
61
+ const [orderState, { clearCart }] = useOrder()
54
62
  const [{ parsePrice }] = useUtils()
55
63
  const [, { showToast }] = useToast()
56
64
  const [{ configs }] = useConfig()
@@ -72,6 +80,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
72
80
  borderWidth: 0,
73
81
  backgroundColor: theme.colors.clear,
74
82
  shadowColor: theme.colors.clear,
83
+ padding: 40,
75
84
  },
76
85
  searchIcon: {
77
86
  borderWidth: 0,
@@ -90,9 +99,11 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
90
99
  const [categoriesLayout, setCategoriesLayout] = useState<any>({})
91
100
  const [productListLayout, setProductListLayout] = useState<any>(null)
92
101
  const [isCategoryClicked, setCategoryClicked] = useState(false)
102
+ const [subcategoriesSelected, setSubcategoriesSelected] = useState([])
93
103
 
94
104
  const currentCart: any = Object.values(orderState.carts).find((cart: any) => cart?.business?.slug === business?.slug) ?? {}
95
-
105
+ const isOpenFiltProducts = isOpenSearchBar && !!searchValue
106
+ const filtProductsHeight = Platform.OS === 'ios' ? 0 : 35
96
107
  const onRedirect = (route: string, params?: any) => {
97
108
  navigation.navigate(route, params)
98
109
  }
@@ -162,12 +173,41 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
162
173
  navigation?.canGoBack() ? navigation.goBack() : navigation.navigate('BottomTab')
163
174
  }
164
175
 
176
+ const adjustBusiness = async (adjustBusinessId: number) => {
177
+ const _carts = orderState?.carts?.[adjustBusinessId]
178
+ const products = _carts?.products
179
+ const unavailableProducts = products.filter((product: any) => product.valid !== true)
180
+ const alreadyRemoved = await _retrieveStoreData('already-removed')
181
+ _removeStoreData('already-removed')
182
+ if (unavailableProducts.length > 0) {
183
+ multiRemoveProducts && await multiRemoveProducts(unavailableProducts, _carts)
184
+ return
185
+ }
186
+
187
+ if (alreadyRemoved === 'removed') {
188
+ setAlertState({ open: true, content: [t('NOT_AVAILABLE_PRODUCT', 'This product is not available.')] })
189
+ }
190
+ }
191
+
192
+ const removeCartByReOrder = async () => {
193
+ const adjustBusinessId = await _retrieveStoreData('adjust-cart-products')
194
+ if (currentCart && adjustBusinessId) {
195
+ _removeStoreData('adjust-cart-products')
196
+ adjustBusiness(adjustBusinessId)
197
+ }
198
+ }
199
+
200
+ useEffect(() => {
201
+ removeCartByReOrder()
202
+ }, [currentCart])
203
+
165
204
  return (
166
- <SafeAreaView
205
+ <ContainerSafeAreaView
167
206
  style={{ flex: 1 }}
207
+ isOpenFiltProducts={isOpenFiltProducts}
168
208
  >
169
209
  <Animated.View style={{ position: 'relative' }}>
170
- <TopHeader>
210
+ <TopHeader isIos={Platform.OS === 'ios'}>
171
211
  {!isOpenSearchBar && (
172
212
  <>
173
213
  <View style={{ ...styles.headerItem, flex: 1 }}>
@@ -205,6 +245,46 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
205
245
  )}
206
246
  </TopHeader>
207
247
  </Animated.View>
248
+
249
+ {business?.categories?.length > 0 && isOpenFiltProducts && (
250
+ <FiltProductsContainer
251
+ style={{
252
+ height: Dimensions.get('window').height - filtProductsHeight
253
+ }}
254
+ >
255
+ <View style={{ padding: 20, backgroundColor: theme.colors.white }}>
256
+ <BusinessProductsList
257
+ categories={[
258
+ { id: null, name: t('ALL', 'All') },
259
+ { id: 'featured', name: t('FEATURED', 'Featured') },
260
+ ...business?.categories.sort((a: any, b: any) => a.rank - b.rank)
261
+ ]}
262
+ category={categorySelected}
263
+ categoryState={categoryState}
264
+ businessId={business.id}
265
+ errors={errors}
266
+ onProductClick={onProductClick}
267
+ handleSearchRedirect={handleSearchRedirect}
268
+ featured={featuredProducts}
269
+ searchValue={searchValue}
270
+ handleClearSearch={handleChangeSearch}
271
+ errorQuantityProducts={errorQuantityProducts}
272
+ handleCancelSearch={handleCancel}
273
+ categoriesLayout={categoriesLayout}
274
+ subcategoriesSelected={subcategoriesSelected}
275
+ lazyLoadProductsRecommended={business?.lazy_load_products_recommended}
276
+ setCategoriesLayout={setCategoriesLayout}
277
+ currentCart={currentCart}
278
+ setSubcategoriesSelected={setSubcategoriesSelected}
279
+ onClickCategory={handleChangeCategory}
280
+ isFiltMode
281
+ />
282
+ </View>
283
+ </FiltProductsContainer>
284
+ )}
285
+ {isOpenFiltProducts && (
286
+ <BackgroundGray />
287
+ )}
208
288
  <BusinessProductsListingContainer
209
289
  stickyHeaderIndices={[2]}
210
290
  style={styles.mainContainer}
@@ -239,6 +319,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
239
319
  lazyLoadProductsRecommended={business?.lazy_load_products_recommended}
240
320
  setSelectedCategoryId={setSelectedCategoryId}
241
321
  setCategoryClicked={setCategoryClicked}
322
+
242
323
  />
243
324
  )}
244
325
  </>
@@ -266,8 +347,12 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
266
347
  errorQuantityProducts={errorQuantityProducts}
267
348
  handleCancelSearch={handleCancel}
268
349
  categoriesLayout={categoriesLayout}
350
+ subcategoriesSelected={subcategoriesSelected}
351
+ lazyLoadProductsRecommended={business?.lazy_load_products_recommended}
269
352
  setCategoriesLayout={setCategoriesLayout}
270
353
  currentCart={currentCart}
354
+ setSubcategoriesSelected={setSubcategoriesSelected}
355
+ onClickCategory={handleChangeCategory}
271
356
  />
272
357
  </WrapContent>
273
358
  </>
@@ -297,16 +382,18 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
297
382
  {!loading && auth && currentCart?.products?.length > 0 && categoryState.products.length !== 0 && (
298
383
  <FloatingButton
299
384
  btnText={
300
- currentCart?.subtotal >= currentCart?.minimum
301
- ? t('VIEW_ORDER', 'View Order')
302
- : `${t('MINIMUN_SUBTOTAL_ORDER', 'Minimum subtotal order:')} ${parsePrice(currentCart?.minimum)}`
385
+ openUpselling
386
+ ? t('LOADING', 'Loading')
387
+ : currentCart?.subtotal >= currentCart?.minimum
388
+ ? t('VIEW_ORDER', 'View Order')
389
+ : `${t('MINIMUN_SUBTOTAL_ORDER', 'Minimum subtotal order:')} ${parsePrice(currentCart?.minimum)}`
303
390
  }
304
- isSecondaryBtn={currentCart?.subtotal < currentCart?.minimum}
391
+ isSecondaryBtn={currentCart?.subtotal < currentCart?.minimum || openUpselling}
305
392
  btnLeftValueShow={currentCart?.subtotal >= currentCart?.minimum && currentCart?.products?.length > 0}
306
393
  btnRightValueShow={currentCart?.subtotal >= currentCart?.minimum && currentCart?.products?.length > 0}
307
- btnLeftValue={currentCart?.products?.length}
394
+ btnLeftValue={currentCart?.products.reduce((prev: number, product: any) => prev + product.quantity, 0)}
308
395
  btnRightValue={parsePrice(currentCart?.total)}
309
- disabled={currentCart?.subtotal < currentCart?.minimum}
396
+ disabled={currentCart?.subtotal < currentCart?.minimum || openUpselling}
310
397
  handleClick={() => setOpenUpselling(true)}
311
398
  />
312
399
  )}
@@ -325,7 +412,14 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
325
412
  onRedirect={onRedirect}
326
413
  />
327
414
  )}
328
- </SafeAreaView>
415
+ <Alert
416
+ open={alertState?.open || false}
417
+ title=''
418
+ content={[t('NOT_AVAILABLE_PRODUCTS', 'These products are not available.')]}
419
+ onAccept={() => setAlertState({ open: false, content: [] })}
420
+ onClose={() => setAlertState({ open: false, content: [] })}
421
+ />
422
+ </ContainerSafeAreaView>
329
423
  )
330
424
  }
331
425
 
@@ -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
+ `
@@ -90,33 +90,12 @@ const BusinessReviewsUI = (props: BusinessReviewsParams) => {
90
90
  </View>
91
91
  );
92
92
 
93
- const ReviewItem = ({ comment, created_at, total, customer }: any) => (
93
+ const ReviewItem = ({ comment, created_at, total }: any) => (
94
94
  <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}
95
+ <OText size={12} color={theme.colors.textSecondary}>
96
+ {moment(created_at).format('MMMM d, yyyy hh:mm')}
119
97
  </OText>
98
+ <OText size={12} color={theme.colors.textNormal}>{comment}</OText>
120
99
  </View>
121
100
  );
122
101
 
@@ -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 }}