ordering-ui-react-native 0.15.33 → 0.15.34-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 (169) hide show
  1. package/package.json +4 -2
  2. package/src/DeliveryApp.tsx +43 -1
  3. package/src/components/BusinessController/index.tsx +8 -2
  4. package/src/components/BusinessTypeFilter/index.tsx +4 -1
  5. package/src/components/BusinessesListing/index.tsx +1 -1
  6. package/src/components/Checkout/index.tsx +23 -3
  7. package/src/components/DriverTips/index.tsx +11 -6
  8. package/src/components/LanguageSelector/index.tsx +7 -2
  9. package/src/components/LoginForm/index.tsx +3 -1
  10. package/src/components/OrderDetails/index.tsx +2 -2
  11. package/src/components/PaymentOptions/index.tsx +9 -16
  12. package/src/components/PaymentOptionsWebView/index.tsx +123 -124
  13. package/src/components/SignupForm/index.tsx +3 -1
  14. package/src/components/SingleProductCard/index.tsx +16 -4
  15. package/src/components/StripeElementsForm/index.tsx +27 -48
  16. package/src/components/UpsellingProducts/index.tsx +1 -1
  17. package/src/components/UserProfileForm/index.tsx +63 -6
  18. package/src/components/UserProfileForm/styles.tsx +8 -0
  19. package/src/components/VerifyPhone/styles.tsx +1 -2
  20. package/src/components/shared/OModal.tsx +1 -1
  21. package/src/config.json +0 -2
  22. package/src/hooks/useCountdownTimer.tsx +26 -0
  23. package/src/navigators/HomeNavigator.tsx +6 -0
  24. package/src/pages/BusinessProductsList.tsx +1 -0
  25. package/src/pages/BusinessesListing.tsx +1 -1
  26. package/src/pages/Checkout.tsx +1 -1
  27. package/src/pages/Sessions.tsx +22 -0
  28. package/src/types/index.tsx +5 -11
  29. package/src/utils/index.tsx +68 -1
  30. package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +103 -15
  31. package/themes/business/src/components/AcceptOrRejectOrder/styles.tsx +6 -0
  32. package/themes/business/src/components/Chat/index.tsx +38 -86
  33. package/themes/business/src/components/DriverMap/index.tsx +6 -5
  34. package/themes/business/src/components/Home/index.tsx +128 -55
  35. package/themes/business/src/components/Home/styles.tsx +8 -1
  36. package/themes/business/src/components/LoginForm/index.tsx +89 -2
  37. package/themes/business/src/components/LoginForm/styles.tsx +6 -0
  38. package/themes/business/src/components/LogoutButton/index.tsx +1 -1
  39. package/themes/business/src/components/NewOrderNotification/index.tsx +79 -105
  40. package/themes/business/src/components/OrderDetails/Business.tsx +1 -1
  41. package/themes/business/src/components/OrderDetails/Delivery.tsx +32 -15
  42. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +157 -89
  43. package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +6 -0
  44. package/themes/business/src/components/OrderDetails/styles.tsx +7 -0
  45. package/themes/business/src/components/OrdersListManager/index.tsx +52 -49
  46. package/themes/business/src/components/OrdersOption/index.tsx +57 -50
  47. package/themes/business/src/components/PreviousOrders/index.tsx +50 -14
  48. package/themes/business/src/components/ProductItemAccordion/index.tsx +2 -2
  49. package/themes/business/src/components/shared/OModal.tsx +1 -1
  50. package/themes/business/src/types/index.tsx +5 -1
  51. package/themes/doordash/src/components/BusinessesListing/index.tsx +1 -1
  52. package/themes/doordash/src/components/LoginForm/index.tsx +1 -2
  53. package/themes/instacart/src/components/BusinessesListing/index.tsx +1 -1
  54. package/themes/kiosk/src/components/Cart/index.tsx +99 -25
  55. package/themes/kiosk/src/components/Cart/styles.tsx +6 -0
  56. package/themes/kiosk/src/components/Checkout/index.tsx +34 -22
  57. package/themes/kiosk/src/components/CustomerName/index.tsx +0 -6
  58. package/themes/kiosk/src/components/Intro/index.tsx +12 -12
  59. package/themes/kiosk/src/components/NavBar/index.tsx +14 -14
  60. package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
  61. package/themes/kiosk/src/components/OrderDetails/index.tsx +165 -65
  62. package/themes/kiosk/src/components/OrderDetails/styles.tsx +5 -0
  63. package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +10 -12
  64. package/themes/kiosk/src/components/PaymentOptions/index.tsx +1 -1
  65. package/themes/kiosk/src/components/ProductForm/index.tsx +2 -2
  66. package/themes/kiosk/src/components/UpsellingProducts/index.tsx +48 -34
  67. package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
  68. package/themes/kiosk/src/types/index.d.ts +2 -0
  69. package/themes/original/index.tsx +184 -1
  70. package/themes/original/src/components/ActiveOrders/index.tsx +15 -132
  71. package/themes/original/src/components/ActiveOrders/styles.tsx +0 -54
  72. package/themes/original/src/components/AddressForm/index.tsx +15 -10
  73. package/themes/original/src/components/AddressList/index.tsx +56 -18
  74. package/themes/original/src/components/AppleLogin/index.tsx +117 -78
  75. package/themes/original/src/components/BusinessBasicInformation/index.tsx +96 -45
  76. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +28 -1
  77. package/themes/original/src/components/BusinessController/index.tsx +56 -16
  78. package/themes/original/src/components/BusinessController/styles.tsx +27 -0
  79. package/themes/original/src/components/BusinessFeaturedController/index.tsx +20 -1
  80. package/themes/original/src/components/BusinessFeaturedController/styles.tsx +23 -0
  81. package/themes/original/src/components/BusinessListingSearch/index.tsx +125 -7
  82. package/themes/original/src/components/BusinessListingSearch/styles.tsx +14 -1
  83. package/themes/original/src/components/BusinessMenuList/index.tsx +11 -4
  84. package/themes/original/src/components/BusinessPreorder/index.tsx +142 -122
  85. package/themes/original/src/components/BusinessProductsCategories/index.tsx +9 -7
  86. package/themes/original/src/components/BusinessProductsList/CategoryDescription/index.tsx +44 -0
  87. package/themes/original/src/components/BusinessProductsList/index.tsx +139 -36
  88. package/themes/original/src/components/BusinessProductsList/styles.tsx +29 -2
  89. package/themes/original/src/components/BusinessProductsListing/index.tsx +111 -14
  90. package/themes/original/src/components/BusinessProductsListing/styles.tsx +22 -0
  91. package/themes/original/src/components/BusinessReviews/index.tsx +4 -25
  92. package/themes/original/src/components/BusinessTypeFilter/index.tsx +1 -2
  93. package/themes/original/src/components/BusinessesListing/index.tsx +85 -45
  94. package/themes/original/src/components/Cart/index.tsx +21 -17
  95. package/themes/original/src/components/CartContent/index.tsx +2 -2
  96. package/themes/original/src/components/Checkout/index.tsx +59 -48
  97. package/themes/original/src/components/DriverTips/index.tsx +17 -12
  98. package/themes/original/src/components/Favorite/index.tsx +91 -0
  99. package/themes/original/src/components/Favorite/styles.tsx +22 -0
  100. package/themes/original/src/components/FavoriteList/index.tsx +287 -0
  101. package/themes/original/src/components/FavoriteList/styles.tsx +5 -0
  102. package/themes/original/src/components/ForgotPasswordForm/index.tsx +84 -4
  103. package/themes/original/src/components/GPSButton/index.tsx +15 -8
  104. package/themes/original/src/components/GoogleMap/index.tsx +1 -0
  105. package/themes/original/src/components/Help/index.tsx +21 -4
  106. package/themes/original/src/components/HighestRatedBusinesses/index.tsx +18 -1
  107. package/themes/original/src/components/Home/index.tsx +1 -1
  108. package/themes/original/src/components/LastOrders/index.tsx +12 -1
  109. package/themes/original/src/components/LoginForm/Otp/index.tsx +90 -0
  110. package/themes/original/src/components/LoginForm/Otp/styles.tsx +7 -0
  111. package/themes/original/src/components/LoginForm/index.tsx +394 -155
  112. package/themes/original/src/components/LoginForm/styles.tsx +7 -4
  113. package/themes/original/src/components/LogoutButton/index.tsx +7 -1
  114. package/themes/original/src/components/MessageListing/index.tsx +10 -1
  115. package/themes/original/src/components/Messages/index.tsx +6 -1
  116. package/themes/original/src/components/Messages/styles.tsx +1 -3
  117. package/themes/original/src/components/MomentOption/index.tsx +10 -1
  118. package/themes/original/src/components/MomentOption/styles.tsx +1 -1
  119. package/themes/original/src/components/OrderDetails/index.tsx +56 -33
  120. package/themes/original/src/components/OrderDetails/styles.tsx +1 -2
  121. package/themes/original/src/components/OrderProgress/index.tsx +3 -3
  122. package/themes/original/src/components/OrderProgress/styles.tsx +1 -0
  123. package/themes/original/src/components/OrderSummary/index.tsx +3 -3
  124. package/themes/original/src/components/OrderTypeSelector/index.tsx +4 -2
  125. package/themes/original/src/components/OrdersOption/index.tsx +57 -56
  126. package/themes/original/src/components/OrdersOption/styles.tsx +0 -6
  127. package/themes/original/src/components/PaymentOptionCash/index.tsx +2 -2
  128. package/themes/original/src/components/PaymentOptionWallet/index.tsx +22 -24
  129. package/themes/original/src/components/PaymentOptionWallet/styles.tsx +1 -1
  130. package/themes/original/src/components/PaymentOptions/index.tsx +9 -21
  131. package/themes/original/src/components/PhoneInputNumber/index.tsx +1 -1
  132. package/themes/original/src/components/PreviousOrders/index.tsx +18 -145
  133. package/themes/original/src/components/ProductForm/index.tsx +76 -61
  134. package/themes/original/src/components/ProductForm/styles.tsx +0 -1
  135. package/themes/original/src/components/ProductItemAccordion/index.tsx +2 -2
  136. package/themes/original/src/components/ProductOptionSubOption/index.tsx +18 -12
  137. package/themes/original/src/components/Promotions/index.tsx +250 -0
  138. package/themes/original/src/components/Promotions/styles.tsx +60 -0
  139. package/themes/original/src/components/SearchBar/index.tsx +4 -1
  140. package/themes/original/src/components/Sessions/index.tsx +160 -0
  141. package/themes/original/src/components/Sessions/styles.tsx +15 -0
  142. package/themes/original/src/components/SignupForm/index.tsx +9 -4
  143. package/themes/original/src/components/SingleOrderCard/index.tsx +282 -0
  144. package/themes/original/src/components/SingleOrderCard/styles.tsx +54 -0
  145. package/themes/original/src/components/SingleProductCard/index.tsx +82 -30
  146. package/themes/original/src/components/SingleProductCard/styles.tsx +28 -1
  147. package/themes/original/src/components/StripeElementsForm/index.tsx +55 -74
  148. package/themes/original/src/components/TaxInformation/index.tsx +10 -4
  149. package/themes/original/src/components/UpsellingProducts/index.tsx +86 -74
  150. package/themes/original/src/components/UserDetails/index.tsx +4 -95
  151. package/themes/original/src/components/UserFormDetails/index.tsx +34 -24
  152. package/themes/original/src/components/UserProfile/index.tsx +62 -8
  153. package/themes/original/src/components/UserProfileForm/index.tsx +20 -18
  154. package/themes/original/src/components/UserVerification/index.tsx +178 -192
  155. package/themes/original/src/components/VerifyPhone/index.tsx +10 -7
  156. package/themes/original/src/components/VerifyPhone/styles.tsx +2 -1
  157. package/themes/original/src/components/Wallets/index.tsx +76 -9
  158. package/themes/original/src/components/Wallets/styles.tsx +21 -0
  159. package/themes/original/src/components/shared/HeaderTitle.tsx +21 -0
  160. package/themes/original/src/components/shared/OModal.tsx +4 -2
  161. package/themes/original/src/components/shared/index.tsx +2 -0
  162. package/themes/original/src/config/constants.tsx +6 -6
  163. package/themes/original/src/types/index.tsx +107 -9
  164. package/themes/original/src/utils/index.tsx +28 -2
  165. package/themes/single-business/src/components/AddressList/index.tsx +1 -1
  166. package/themes/single-business/src/components/OrderTypeSelector/index.tsx +6 -6
  167. package/themes/single-business/src/components/UserProfile/index.tsx +1 -1
  168. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
  169. package/src/components/StripeMethodForm/index.tsx +0 -174
@@ -44,11 +44,11 @@ const BusinessProductsCategoriesUI = (props: any) => {
44
44
  borderTopStartRadius: 4,
45
45
  borderTopEndRadius: 4,
46
46
  backgroundColor: theme.colors.textPrimary,
47
- },
48
- tabDeactived: {
47
+ },
48
+ tabDeactived: {
49
49
  marginTop: 10,
50
50
  height: 4
51
- }
51
+ }
52
52
  });
53
53
 
54
54
  const handleCategoryScroll = (category: 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
  })
@@ -111,8 +111,10 @@ const BusinessProductsCategoriesUI = (props: any) => {
111
111
  categories.length &&
112
112
  categories.map((category: any) => (
113
113
  <Tab
114
- key={category.name}
115
- onPress={() => handleCategoryScroll(category)}
114
+ key={category.id}
115
+ onPress={() => requestAnimationFrame(() => {
116
+ handleCategoryScroll(category)
117
+ })}
116
118
  style={[
117
119
  category.id === 'featured' && !featured && styles.featuredStyle,
118
120
  {
@@ -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,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,23 +320,12 @@ 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
  };
@@ -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,17 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
44
49
  errorQuantityProducts,
45
50
  header,
46
51
  logo,
52
+ alertState,
53
+ setAlertState,
54
+ multiRemoveProducts,
47
55
  getNextProducts,
56
+ handleUpdateProducts
48
57
  } = props
49
58
 
50
59
  const theme = useTheme();
51
60
  const [, t] = useLanguage()
52
61
  const [{ auth }] = useSession()
53
- const [orderState] = useOrder()
62
+ const [orderState, { clearCart }] = useOrder()
54
63
  const [{ parsePrice }] = useUtils()
55
64
  const [, { showToast }] = useToast()
56
65
  const [{ configs }] = useConfig()
@@ -91,9 +100,11 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
91
100
  const [categoriesLayout, setCategoriesLayout] = useState<any>({})
92
101
  const [productListLayout, setProductListLayout] = useState<any>(null)
93
102
  const [isCategoryClicked, setCategoryClicked] = useState(false)
103
+ const [subcategoriesSelected, setSubcategoriesSelected] = useState([])
94
104
 
95
105
  const currentCart: any = Object.values(orderState.carts).find((cart: any) => cart?.business?.slug === business?.slug) ?? {}
96
-
106
+ const isOpenFiltProducts = isOpenSearchBar && !!searchValue
107
+ const filtProductsHeight = Platform.OS === 'ios' ? 0 : 35
97
108
  const onRedirect = (route: string, params?: any) => {
98
109
  navigation.navigate(route, params)
99
110
  }
@@ -163,12 +174,41 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
163
174
  navigation?.canGoBack() ? navigation.goBack() : navigation.navigate('BottomTab')
164
175
  }
165
176
 
177
+ const adjustBusiness = async (adjustBusinessId: number) => {
178
+ const _carts = orderState?.carts?.[adjustBusinessId]
179
+ const products = _carts?.products
180
+ const unavailableProducts = products.filter((product: any) => product.valid !== true)
181
+ const alreadyRemoved = await _retrieveStoreData('already-removed')
182
+ _removeStoreData('already-removed')
183
+ if (unavailableProducts.length > 0) {
184
+ multiRemoveProducts && await multiRemoveProducts(unavailableProducts, _carts)
185
+ return
186
+ }
187
+
188
+ if (alreadyRemoved === 'removed') {
189
+ setAlertState({ open: true, content: [t('NOT_AVAILABLE_PRODUCT', 'This product is not available.')] })
190
+ }
191
+ }
192
+
193
+ const removeCartByReOrder = async () => {
194
+ const adjustBusinessId = await _retrieveStoreData('adjust-cart-products')
195
+ if (currentCart && adjustBusinessId) {
196
+ _removeStoreData('adjust-cart-products')
197
+ adjustBusiness(adjustBusinessId)
198
+ }
199
+ }
200
+
201
+ useEffect(() => {
202
+ removeCartByReOrder()
203
+ }, [currentCart])
204
+
166
205
  return (
167
- <SafeAreaView
206
+ <ContainerSafeAreaView
168
207
  style={{ flex: 1 }}
208
+ isOpenFiltProducts={isOpenFiltProducts}
169
209
  >
170
210
  <Animated.View style={{ position: 'relative' }}>
171
- <TopHeader>
211
+ <TopHeader isIos={Platform.OS === 'ios'}>
172
212
  {!isOpenSearchBar && (
173
213
  <>
174
214
  <View style={{ ...styles.headerItem, flex: 1 }}>
@@ -206,6 +246,47 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
206
246
  )}
207
247
  </TopHeader>
208
248
  </Animated.View>
249
+
250
+ {business?.categories?.length > 0 && isOpenFiltProducts && (
251
+ <FiltProductsContainer
252
+ style={{
253
+ height: Dimensions.get('window').height - filtProductsHeight
254
+ }}
255
+ >
256
+ <View style={{ padding: 20, backgroundColor: theme.colors.white }}>
257
+ <BusinessProductsList
258
+ categories={[
259
+ { id: null, name: t('ALL', 'All') },
260
+ { id: 'featured', name: t('FEATURED', 'Featured') },
261
+ ...business?.categories.sort((a: any, b: any) => a.rank - b.rank)
262
+ ]}
263
+ category={categorySelected}
264
+ categoryState={categoryState}
265
+ businessId={business.id}
266
+ errors={errors}
267
+ onProductClick={onProductClick}
268
+ handleSearchRedirect={handleSearchRedirect}
269
+ featured={featuredProducts}
270
+ searchValue={searchValue}
271
+ handleClearSearch={handleChangeSearch}
272
+ errorQuantityProducts={errorQuantityProducts}
273
+ handleCancelSearch={handleCancel}
274
+ categoriesLayout={categoriesLayout}
275
+ subcategoriesSelected={subcategoriesSelected}
276
+ lazyLoadProductsRecommended={business?.lazy_load_products_recommended}
277
+ setCategoriesLayout={setCategoriesLayout}
278
+ currentCart={currentCart}
279
+ setSubcategoriesSelected={setSubcategoriesSelected}
280
+ onClickCategory={handleChangeCategory}
281
+ handleUpdateProducts={handleUpdateProducts}
282
+ isFiltMode
283
+ />
284
+ </View>
285
+ </FiltProductsContainer>
286
+ )}
287
+ {isOpenFiltProducts && (
288
+ <BackgroundGray />
289
+ )}
209
290
  <BusinessProductsListingContainer
210
291
  stickyHeaderIndices={[2]}
211
292
  style={styles.mainContainer}
@@ -240,6 +321,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
240
321
  lazyLoadProductsRecommended={business?.lazy_load_products_recommended}
241
322
  setSelectedCategoryId={setSelectedCategoryId}
242
323
  setCategoryClicked={setCategoryClicked}
324
+
243
325
  />
244
326
  )}
245
327
  </>
@@ -267,8 +349,13 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
267
349
  errorQuantityProducts={errorQuantityProducts}
268
350
  handleCancelSearch={handleCancel}
269
351
  categoriesLayout={categoriesLayout}
352
+ subcategoriesSelected={subcategoriesSelected}
353
+ lazyLoadProductsRecommended={business?.lazy_load_products_recommended}
270
354
  setCategoriesLayout={setCategoriesLayout}
271
355
  currentCart={currentCart}
356
+ setSubcategoriesSelected={setSubcategoriesSelected}
357
+ onClickCategory={handleChangeCategory}
358
+ handleUpdateProducts={handleUpdateProducts}
272
359
  />
273
360
  </WrapContent>
274
361
  </>
@@ -290,6 +377,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
290
377
  categoryState={categoryState}
291
378
  isBusinessLoading={loading}
292
379
  errorQuantityProducts={errorQuantityProducts}
380
+ handleUpdateProducts={handleUpdateProducts}
293
381
  />
294
382
  </WrapContent>
295
383
  </>
@@ -298,16 +386,18 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
298
386
  {!loading && auth && currentCart?.products?.length > 0 && categoryState.products.length !== 0 && (
299
387
  <FloatingButton
300
388
  btnText={
301
- currentCart?.subtotal >= currentCart?.minimum
302
- ? t('VIEW_ORDER', 'View Order')
303
- : `${t('MINIMUN_SUBTOTAL_ORDER', 'Minimum subtotal order:')} ${parsePrice(currentCart?.minimum)}`
389
+ openUpselling
390
+ ? t('LOADING', 'Loading')
391
+ : currentCart?.subtotal >= currentCart?.minimum
392
+ ? t('VIEW_ORDER', 'View Order')
393
+ : `${t('MINIMUN_SUBTOTAL_ORDER', 'Minimum subtotal order:')} ${parsePrice(currentCart?.minimum)}`
304
394
  }
305
- isSecondaryBtn={currentCart?.subtotal < currentCart?.minimum}
395
+ isSecondaryBtn={currentCart?.subtotal < currentCart?.minimum || openUpselling}
306
396
  btnLeftValueShow={currentCart?.subtotal >= currentCart?.minimum && currentCart?.products?.length > 0}
307
397
  btnRightValueShow={currentCart?.subtotal >= currentCart?.minimum && currentCart?.products?.length > 0}
308
- btnLeftValue={currentCart?.products?.length}
398
+ btnLeftValue={currentCart?.products.reduce((prev: number, product: any) => prev + product.quantity, 0)}
309
399
  btnRightValue={parsePrice(currentCart?.total)}
310
- disabled={currentCart?.subtotal < currentCart?.minimum}
400
+ disabled={currentCart?.subtotal < currentCart?.minimum || openUpselling}
311
401
  handleClick={() => setOpenUpselling(true)}
312
402
  />
313
403
  )}
@@ -326,7 +416,14 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
326
416
  onRedirect={onRedirect}
327
417
  />
328
418
  )}
329
- </SafeAreaView>
419
+ <Alert
420
+ open={alertState?.open || false}
421
+ title=''
422
+ content={[t('NOT_AVAILABLE_PRODUCTS', 'These products are not available.')]}
423
+ onAccept={() => setAlertState({ open: false, content: [] })}
424
+ onClose={() => setAlertState({ open: false, content: [] })}
425
+ />
426
+ </ContainerSafeAreaView>
330
427
  )
331
428
  }
332
429
 
@@ -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
+ `