ordering-ui-react-native 0.16.92-release → 0.16.93-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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.16.92-release",
3
+ "version": "0.16.93-release",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -62,6 +62,7 @@ const AddressFormUI = (props: AddressFormParams) => {
62
62
  isFromProductsList,
63
63
  hasAddressDefault,
64
64
  afterSignup,
65
+ businessSlug
65
66
  } = props;
66
67
 
67
68
  const theme = useTheme();
@@ -160,7 +161,9 @@ const AddressFormUI = (props: AddressFormParams) => {
160
161
  const maxLimitLocation =
161
162
  configState?.configs?.meters_to_change_address?.value;
162
163
  const countryCode = configState?.configs?.country_autocomplete?.value
163
- const continueAsGuest = () => navigation.navigate('BusinessList', { isGuestUser: true });
164
+ const isHideMap = theme?.address?.components?.map?.hidden
165
+ const isHideIcons = theme?.address?.components?.icons?.hidden
166
+ const continueAsGuest = () => navigation.navigate(!!businessSlug ? 'Business' : 'BusinessList', { isGuestUser: true });
164
167
  const goToBack = () => navigation?.canGoBack() && navigation.goBack();
165
168
 
166
169
  const getAddressFormatted = (address: any) => {
@@ -1,14 +1,46 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { createClient, AnalyticsProvider } from '@segment/analytics-react-native';
3
- import { useEvent, useConfig } from 'ordering-components/native';
3
+ import { useEvent, useConfig, useLanguage } from 'ordering-components/native';
4
4
 
5
5
  export const AnalyticsSegment = (props: any) => {
6
6
  const { children } = props
7
7
 
8
8
  const [events] = useEvent()
9
9
  const [configState] = useConfig()
10
+ const [, t] = useLanguage()
10
11
  const [segmentClient, setSegmentClient] = useState<any>({})
11
12
 
13
+ const handleProductsSearched = (query: any) => {
14
+ segmentClient.track('Products Searched', {
15
+ query: query
16
+ })
17
+ }
18
+
19
+ const handleProductListViewed = (category: any) => {
20
+ segmentClient.track('Product List Viewed', {
21
+ business_id: category.business_id,
22
+ category_id: category.id,
23
+ category: category.name,
24
+ products: category?.products
25
+ })
26
+ }
27
+
28
+ const handlePromotionViewed = (promotion: any) => {
29
+ segmentClient.track('Promotion Viewed', {
30
+ promotion_id: (promotion?.id || '').toString(),
31
+ name: promotion.name,
32
+ position: promotion.position
33
+ })
34
+ }
35
+
36
+ const handlePromotionClicked = (promotion: any) => {
37
+ segmentClient.track('Promotion Clicked', {
38
+ promotion_id: (promotion?.id || '').toString(),
39
+ name: promotion.name,
40
+ position: promotion.position
41
+ })
42
+ }
43
+
12
44
  const handleClickProduct = (product: any) => {
13
45
  segmentClient.track('Product Clicked', {
14
46
  id: product.id,
@@ -18,6 +50,15 @@ export const AnalyticsSegment = (props: any) => {
18
50
  })
19
51
  }
20
52
 
53
+ const handleProductViewed = (product: any) => {
54
+ segmentClient.track('Product Viewed', {
55
+ id: product.id,
56
+ name: product.name,
57
+ category: product.category_id,
58
+ price: product.price
59
+ })
60
+ }
61
+
21
62
  const handleProductAdded = (product: any) => {
22
63
  segmentClient.track('Product Added', {
23
64
  id: product.id,
@@ -38,6 +79,23 @@ export const AnalyticsSegment = (props: any) => {
38
79
  })
39
80
  }
40
81
 
82
+ const handleCartViewed = (cart: any) => {
83
+ segmentClient.track('Cart Viewed', {
84
+ id: cart.uuid,
85
+ products: cart?.products
86
+ })
87
+ }
88
+
89
+ const handleCheckoutStarted = (cart: any) => {
90
+ segmentClient.track('Checkout Started', {
91
+ cart_id: cart?.uuid,
92
+ affiliation: cart?.business?.name,
93
+ revenue: cart?.total,
94
+ tax: cart?.tax_total,
95
+ shipping: cart?.delivery_zone_price
96
+ })
97
+ }
98
+
41
99
  const handleOrderPlaced = (order: any) => {
42
100
  segmentClient.track('Order Placed', {
43
101
  id: order.id,
@@ -65,6 +123,35 @@ export const AnalyticsSegment = (props: any) => {
65
123
  tax: order.tax_total,
66
124
  shipping: order.delivery_zone_price
67
125
  })
126
+
127
+ if (order?.history?.length) {
128
+ const lasthistory = order.history[order.history.length - 1]
129
+ if (lasthistory?.data) {
130
+ lasthistory.data.forEach(item => {
131
+ if (item.attribute === 'status') {
132
+ if (item.new === 15) {
133
+ segmentClient.track('Order Completed', {
134
+ id: order.id,
135
+ affiliation: order.business?.name,
136
+ revenue: order.total,
137
+ tax: order.tax_total,
138
+ shipping: order.delivery_zone_price
139
+ })
140
+ }
141
+ const orderCancelled = [2, 5, 6, 10, 12, 16, 17]
142
+ if (orderCancelled.includes(item.new)) {
143
+ segmentClient.track('Order Cancelled', {
144
+ id: order.id,
145
+ affiliation: order.business?.name,
146
+ revenue: order.total,
147
+ tax: order.tax_total,
148
+ shipping: order.delivery_zone_price
149
+ })
150
+ }
151
+ }
152
+ })
153
+ }
154
+ }
68
155
  }
69
156
 
70
157
  const handleAddOrder = (order: any) => {
@@ -77,6 +164,51 @@ export const AnalyticsSegment = (props: any) => {
77
164
  })
78
165
  }
79
166
 
167
+ const handleCouponEntered = (cart: any) => {
168
+ segmentClient.track('Coupon Entered', {
169
+ cart_id: cart.uuid,
170
+ coupon: cart.coupon
171
+ })
172
+ }
173
+
174
+ const handleCouponApplied = (cart: any) => {
175
+ const coupon: any = cart?.offers?.find(offer => offer.type === 2)
176
+ if (coupon) {
177
+ segmentClient.track('Coupon Applied', {
178
+ cart_id: cart.uuid,
179
+ coupon_id: coupon.id,
180
+ coupon_name: coupon?.name,
181
+ discount: coupon?.summary?.discount
182
+ })
183
+ }
184
+ }
185
+
186
+ const handleCouponDenied = (coupon: any) => {
187
+ segmentClient.track('Coupon Denied', {
188
+ business_id: coupon.business_id,
189
+ coupon: coupon.coupon,
190
+ user_id: coupon.user.id,
191
+ reason: typeof coupon.reason === 'string' ? t(coupon.reason) : t(coupon.reason[0])
192
+ })
193
+ }
194
+
195
+ const handleCouponRemoved = (coupon: any) => {
196
+ segmentClient.track('Coupon Removed', {
197
+ business_id: coupon.business_id,
198
+ coupon_id: coupon.offer_id,
199
+ })
200
+ }
201
+
202
+ const handleProductReviewed = (products: any) => {
203
+ products.forEach((product: any) => {
204
+ segmentClient.track('Product Reviewed', {
205
+ product_id: product.product_id,
206
+ review_body: product.comment,
207
+ rating: product.qualification
208
+ })
209
+ })
210
+ }
211
+
80
212
  const handleLogin = (data: any) => {
81
213
  segmentClient.identify(data.id, {
82
214
  email: data.email,
@@ -86,23 +218,47 @@ export const AnalyticsSegment = (props: any) => {
86
218
 
87
219
  useEffect(() => {
88
220
  if (segmentClient?.config?.writeKey) {
221
+ events.on('products_searched', handleProductsSearched)
222
+ events.on('product_list_viewed', handleProductListViewed)
223
+ events.on('promotion_viewed', handlePromotionViewed)
224
+ events.on('promotion_clicked', handlePromotionClicked)
89
225
  events.on('product_clicked', handleClickProduct)
90
- events.on('userLogin', handleLogin)
226
+ events.on('product_viewed', handleProductViewed)
91
227
  events.on('product_added', handleProductAdded)
92
- events.on('order_placed', handleOrderPlaced)
228
+ events.on('cart_product_removed', handleProductRemoved)
229
+ events.on('cart_viewed', handleCartViewed)
230
+ events.on('checkout_started', handleCheckoutStarted)
93
231
  events.on('order_updated', handleUpdateOrder)
232
+ events.on('coupon_entered', handleCouponEntered)
233
+ events.on('offer_applied', handleCouponApplied)
234
+ events.on('offer_denied', handleCouponDenied)
235
+ events.on('offer_removed', handleCouponRemoved)
236
+ events.on('product_reviewed', handleProductReviewed)
237
+ events.on('userLogin', handleLogin)
238
+ events.on('order_placed', handleOrderPlaced)
94
239
  events.on('order_added', handleAddOrder)
95
- events.on('cart_product_removed', handleProductRemoved)
96
240
  }
97
241
  return () => {
98
242
  if (segmentClient?.config?.writeKey) {
243
+ events.off('products_searched', handleProductsSearched)
244
+ events.off('product_list_viewed', handleProductListViewed)
245
+ events.off('promotion_viewed', handlePromotionViewed)
246
+ events.off('promotion_clicked', handlePromotionClicked)
99
247
  events.off('product_clicked', handleClickProduct)
100
- events.off('userLogin', handleLogin)
248
+ events.off('product_viewed', handleProductViewed)
101
249
  events.off('product_added', handleProductAdded)
102
- events.off('order_placed', handleOrderPlaced)
250
+ events.off('cart_product_removed', handleProductRemoved)
251
+ events.off('cart_viewed', handleCartViewed)
252
+ events.off('checkout_started', handleCheckoutStarted)
103
253
  events.off('order_updated', handleUpdateOrder)
254
+ events.off('coupon_entered', handleCouponEntered)
255
+ events.off('offer_applied', handleCouponApplied)
256
+ events.off('offer_denied', handleCouponDenied)
257
+ events.off('offer_removed', handleCouponRemoved)
258
+ events.off('product_reviewed', handleProductReviewed)
259
+ events.off('userLogin', handleLogin)
260
+ events.off('order_placed', handleOrderPlaced)
104
261
  events.off('order_added', handleAddOrder)
105
- events.off('cart_product_removed', handleProductRemoved)
106
262
  }
107
263
  }
108
264
  }, [segmentClient])
@@ -110,7 +266,7 @@ export const AnalyticsSegment = (props: any) => {
110
266
  useEffect(() => {
111
267
  if (configState?.configs?.segment_track_id?.value) {
112
268
  const _segmentClient: any = createClient({
113
- writeKey: configState?.configs?.segment_track_id?.value
269
+ writeKey: configState?.configs?.segment_track_id?.value,
114
270
  });
115
271
  setSegmentClient(_segmentClient)
116
272
  }
@@ -1,6 +1,6 @@
1
1
  import React, { useState, useRef, useEffect } from 'react';
2
2
  import { TouchableOpacity, View } from 'react-native';
3
- import { useOrder, useLanguage, useUtils, useConfig } from 'ordering-components/native';
3
+ import { useOrder, useLanguage, useUtils, useConfig, useEvent } from 'ordering-components/native';
4
4
  import { useTheme } from 'styled-components/native';
5
5
  import {
6
6
  BIContainer,
@@ -22,7 +22,8 @@ export const BusinessItemAccordion = (props: any) => {
22
22
  handleClearProducts,
23
23
  handleClickCheckout,
24
24
  checkoutButtonDisabled,
25
- isMultiCheckout
25
+ isMultiCheckout,
26
+ isFromUpselling
26
27
  } = props
27
28
 
28
29
  const [orderState] = useOrder();
@@ -30,6 +31,7 @@ export const BusinessItemAccordion = (props: any) => {
30
31
  const [{ parsePrice }] = useUtils();
31
32
  const [{ configs }] = useConfig()
32
33
  const theme = useTheme();
34
+ const [events] = useEvent()
33
35
 
34
36
  const isCartPending = cart?.status === 2
35
37
  const isClosed = !cart?.valid_schedule
@@ -37,6 +39,7 @@ export const BusinessItemAccordion = (props: any) => {
37
39
  const isBusinessChangeEnabled = configs?.cart_change_business_validation?.value === '1'
38
40
 
39
41
  const [isActive, setActiveState] = useState(!!singleBusiness)
42
+ const [viewedCart, setViewedCart] = useState<any>(null)
40
43
 
41
44
  useEffect(() => {
42
45
  const cartsArray = Object.values(orderState?.carts)
@@ -52,6 +55,15 @@ export const BusinessItemAccordion = (props: any) => {
52
55
  return acc = acc
53
56
  }, cart?.subtotal)
54
57
 
58
+ useEffect(() => {
59
+ if (isActive && !isFromUpselling) {
60
+ if (cart?.uuid !== viewedCart?.uuid) {
61
+ setViewedCart(cart)
62
+ events.emit('cart_viewed', cart)
63
+ }
64
+ }
65
+ }, [isActive, viewedCart])
66
+
55
67
  return (
56
68
  <BIContainer isClosed={isClosed} isMultiCheckout={isMultiCheckout} checkoutVisible={!isActive && !isClosed && !!isProducts && !checkoutButtonDisabled}>
57
69
  <BIHeader
@@ -39,7 +39,8 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
39
39
  handleUpdateProducts,
40
40
  previouslyProducts,
41
41
  isFiltMode,
42
- navigation
42
+ navigation,
43
+ businessSingleId
43
44
  } = props;
44
45
 
45
46
  const [, t] = useLanguage();
@@ -92,6 +93,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
92
93
  handleUpdateProducts={handleUpdateProducts}
93
94
  currentCart={currentCart}
94
95
  searchValue={searchValue}
96
+ businessSingleId={businessSingleId}
95
97
  />
96
98
  )}
97
99
  {category.id &&
@@ -112,6 +114,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
112
114
  productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
113
115
  handleUpdateProducts={handleUpdateProducts}
114
116
  navigation={navigation}
117
+ businessSingleId={businessSingleId}
115
118
  />
116
119
  ))
117
120
  }
@@ -139,6 +142,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
139
142
  handleUpdateProducts={handleUpdateProducts}
140
143
  productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
141
144
  navigation={navigation}
145
+ businessSingleId={businessSingleId}
142
146
  />
143
147
  ),
144
148
  )}
@@ -240,6 +244,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
240
244
  handleUpdateProducts={handleUpdateProducts}
241
245
  navigation={navigation}
242
246
  productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
247
+ businessSingleId={businessSingleId}
243
248
  />
244
249
  ))}
245
250
  </>
@@ -11,7 +11,8 @@ import {
11
11
  useUtils,
12
12
  ToastType,
13
13
  useToast,
14
- useConfig
14
+ useConfig,
15
+ useEvent
15
16
  } from 'ordering-components/native'
16
17
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
17
18
  import { OButton, OIcon, OModal, OText } from '../shared'
@@ -68,7 +69,8 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
68
69
  professionalSelected,
69
70
  handleUpdateProfessionals,
70
71
  handleChangeProfessionalSelected,
71
- onBusinessClick
72
+ onBusinessClick,
73
+ businessSingleId
72
74
  } = props
73
75
 
74
76
  const insets = useSafeAreaInsets()
@@ -79,6 +81,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
79
81
  const [{ parsePrice }] = useUtils()
80
82
  const [, { showToast }] = useToast()
81
83
  const [{ configs }] = useConfig()
84
+ const [events] = useEvent()
82
85
  const isFocused = useIsFocused();
83
86
  const isPreOrder = configs?.preorder_status_enabled?.value === '1'
84
87
 
@@ -132,6 +135,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
132
135
  const [openService, setOpenService] = useState(false)
133
136
  const [currentProduct, setCurrentProduct] = useState(null)
134
137
  const [searchBarHeight, setSearchBarHeight] = useState(60)
138
+ const [viewedCategory, setViewedCategory] = useState<any>(null)
135
139
 
136
140
  const isCheckoutMultiBusinessEnabled: Boolean = configs?.checkout_multi_business_enabled?.value === '1'
137
141
  const isQuickAddProduct = configs?.add_product_with_one_click?.value === '1'
@@ -177,6 +181,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
177
181
  productAddedToCartLength
178
182
  })
179
183
  }
184
+ events.emit('product_clicked', product)
180
185
  }
181
186
 
182
187
  const handleCancel = () => {
@@ -308,6 +313,36 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
308
313
  return acc = acc
309
314
  }, currentCart?.subtotal)
310
315
 
316
+ const onChangeSearch = (query: any) => {
317
+ handleChangeSearch(query)
318
+ if (query) {
319
+ events.emit('products_searched', query)
320
+ }
321
+ }
322
+
323
+ useEffect(() => {
324
+ let categoryId: any = null
325
+ if (business?.lazy_load_products_recommended) {
326
+ if (categorySelected?.id) {
327
+ categoryId = categorySelected.id
328
+ }
329
+ } else {
330
+ if (selectedCategoryId) {
331
+ const originCategoryId = selectedCategoryId.replace('cat_', '')
332
+ if (!isNaN(originCategoryId)) {
333
+ categoryId = Number(originCategoryId)
334
+ }
335
+ }
336
+ }
337
+ if (categoryId) {
338
+ const _viewedCategory = business.categories.find(category => category.id === categoryId)
339
+ if (_viewedCategory?.id !== viewedCategory?.id) {
340
+ setViewedCategory(_viewedCategory)
341
+ events.emit('product_list_viewed', _viewedCategory)
342
+ }
343
+ }
344
+ }, [business?.lazy_load_products_recommended, selectedCategoryId, categorySelected?.id, viewedCategory])
345
+
311
346
  return (
312
347
  <>
313
348
  <View style={{ flex: 1, backgroundColor: backgroundColor }}>
@@ -317,12 +352,15 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
317
352
  marginTop: Platform.OS === 'ios' ? insets.top : 0
318
353
  }}
319
354
  onLayout={(event: any) => setSearchBarHeight(event.nativeEvent.layout.height)}
355
+ hideArrow={(businessSingleId && auth)}
320
356
  >
321
357
  {!isOpenSearchBar && (
322
358
  <>
323
- <TopActions onPress={() => handleBackNavigation()}>
324
- <OIcon src={theme.images.general.arrow_left} color={theme.colors.textNormal} />
325
- </TopActions>
359
+ {!(businessSingleId && auth) && (
360
+ <TopActions onPress={() => handleBackNavigation()}>
361
+ <OIcon src={theme.images.general.arrow_left} color={theme.colors.textNormal} />
362
+ </TopActions>
363
+ )}
326
364
  {!errorQuantityProducts && (
327
365
  <View style={{ ...styles.headerItem }}>
328
366
  <TouchableOpacity
@@ -339,12 +377,12 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
339
377
  <WrapSearchBar>
340
378
  <SearchBar
341
379
  autoFocus
342
- onSearch={handleChangeSearch}
380
+ onSearch={onChangeSearch}
343
381
  onCancel={() => handleCancel()}
344
382
  isCancelXButtonShow
345
383
  noBorderShow
346
384
  placeholder={t('SEARCH_PRODUCTS', 'Search Products')}
347
- lazyLoad={businessState?.business?.lazy_load_products_recommended}
385
+ lazyLoad
348
386
  />
349
387
  </WrapSearchBar>
350
388
  )}
@@ -412,6 +450,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
412
450
  previouslyProducts={business?.previously_products}
413
451
  navigation={navigation}
414
452
  isFiltMode
453
+ businessSingleId={businessSingleId}
415
454
  />
416
455
  </View>
417
456
  </FiltProductsContainer>
@@ -514,6 +553,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
514
553
  handleUpdateProducts={handleUpdateProducts}
515
554
  navigation={navigation}
516
555
  previouslyProducts={business?.previously_products}
556
+ businessSingleId={businessSingleId}
517
557
  />
518
558
  </WrapContent>
519
559
  </>
@@ -7,7 +7,7 @@ export const TopHeader = styled.View`
7
7
  width: 100%;
8
8
  flex-direction: row;
9
9
  align-items: center;
10
- justify-content: space-between;
10
+ justify-content: ${({ hideArrow }: any) => hideArrow ? 'flex-end' : 'space-between'};
11
11
  z-index: 1;
12
12
  height: 60px;
13
13
  min-height: 60px;
@@ -50,7 +50,8 @@ const CartUI = (props: any) => {
50
50
  preorderTimeRange,
51
51
  preorderMaximumDays,
52
52
  preorderMinimumDays,
53
- cateringTypes
53
+ cateringTypes,
54
+ isFromUpselling
54
55
  } = props
55
56
 
56
57
  const theme = useTheme();
@@ -218,6 +219,7 @@ const CartUI = (props: any) => {
218
219
  handleClickCheckout={() => setOpenUpselling(true)}
219
220
  checkoutButtonDisabled={(openUpselling && !canOpenUpselling) || subtotalWithTaxes < cart?.minimum || !cart?.valid_address}
220
221
  isMultiCheckout={isMultiCheckout}
222
+ isFromUpselling={isFromUpselling}
221
223
  >
222
224
  {cart?.products?.length > 0 && cart?.products.map((product: any, i: number) => (
223
225
  <ProductItemAccordion
@@ -402,6 +404,7 @@ const CartUI = (props: any) => {
402
404
  <CouponControl
403
405
  businessId={businessId}
404
406
  price={cart.total}
407
+ cart={cart}
405
408
  />
406
409
  </OSCoupon>
407
410
  </OSTable>
@@ -14,6 +14,7 @@ import {
14
14
  useConfig,
15
15
  useToast,
16
16
  ToastType,
17
+ useEvent
17
18
  } from 'ordering-components/native';
18
19
  import { useTheme } from 'styled-components/native';
19
20
  import { OText, OIcon, OModal, OButton } from '../shared';
@@ -138,6 +139,7 @@ const CheckoutUI = (props: any) => {
138
139
  const [{ parsePrice, parseDate }] = useUtils();
139
140
  const [{ options, carts, loading }, { confirmCart }] = useOrder();
140
141
  const [validationFields] = useValidationFields();
142
+ const [events] = useEvent()
141
143
 
142
144
  const [errorCash, setErrorCash] = useState(false);
143
145
  const [userErrors, setUserErrors] = useState<any>([]);
@@ -329,6 +331,10 @@ const CheckoutUI = (props: any) => {
329
331
  )
330
332
  }
331
333
 
334
+ useEffect(() => {
335
+ cart && events.emit('checkout_started', cart)
336
+ }, [])
337
+
332
338
  return (
333
339
  <>
334
340
  <Container noPadding>
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect } from 'react';
2
2
  import { StyleSheet, Alert, Text } from 'react-native';
3
- import { CouponControl as CouponController, useLanguage } from 'ordering-components/native';
3
+ import { CouponControl as CouponController, useLanguage, useEvent } from 'ordering-components/native';
4
4
  import { useTheme } from 'styled-components/native';
5
5
  import {
6
6
  CContainer,
@@ -18,11 +18,13 @@ const CouponControlUI = (props: any) => {
18
18
  handleRemoveCouponClick,
19
19
  onChangeInputCoupon,
20
20
  confirm,
21
- setConfirm
21
+ setConfirm,
22
+ cart
22
23
  } = props
23
24
 
24
25
  const [, t] = useLanguage()
25
26
  const theme = useTheme();
27
+ const [events] = useEvent()
26
28
 
27
29
  const styles = StyleSheet.create({
28
30
  inputsStyle: {
@@ -45,6 +47,11 @@ const CouponControlUI = (props: any) => {
45
47
  setConfirm({ ...confirm, open: false, error: false })
46
48
  }
47
49
 
50
+ const onButtonApplyClick = () => {
51
+ events.emit('coupon_entered', { ...cart, coupon: couponInput })
52
+ handleButtonApplyClick()
53
+ }
54
+
48
55
  useEffect(() => {
49
56
  if (confirm.content) {
50
57
  Alert.alert(
@@ -94,7 +101,7 @@ const CouponControlUI = (props: any) => {
94
101
  inputStyle={{ fontSize: 12 }}
95
102
  />
96
103
  <OButton
97
- onClick={() => handleButtonApplyClick()}
104
+ onClick={() => onButtonApplyClick()}
98
105
  bgColor={theme.colors.primary}
99
106
  borderColor={theme.colors.primary}
100
107
  textStyle={{ color: 'white', fontSize: 12 }}
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
- import { useLanguage, useOrder } from 'ordering-components/native';
1
+ import React, { useEffect } from 'react';
2
+ import { useLanguage, useOrder, useConfig } from 'ordering-components/native';
3
3
  import { useTheme } from 'styled-components/native';
4
4
  import { StyleSheet, View } from 'react-native';
5
5
  import { OButton, OIcon, OText } from '../shared';
@@ -8,12 +8,21 @@ import { TouchableOpacity } from 'react-native-gesture-handler';
8
8
  import { useWindowDimensions, Platform } from 'react-native';
9
9
 
10
10
  export const Home = (props: any) => {
11
- const { onNavigationRedirect } = props;
11
+ const { onNavigationRedirect, businessSlug } = props;
12
12
  const { width, height } = useWindowDimensions();
13
13
  const [, t] = useLanguage();
14
14
  const [orderState] = useOrder();
15
+ const [{ configs }] = useConfig()
15
16
 
16
17
  const theme = useTheme();
18
+ const unaddressedTypes = configs?.unaddressed_order_types_allowed?.value.split('|').map((value: any) => Number(value)) || []
19
+ const isAllowUnaddressOrderType = unaddressedTypes.includes(orderState?.options?.type)
20
+
21
+ useEffect(() => {
22
+ if (isAllowUnaddressOrderType) {
23
+ onNavigationRedirect(!!businessSlug ? 'Business' : 'BusinessList')
24
+ }
25
+ }, [isAllowUnaddressOrderType])
17
26
 
18
27
  return (
19
28
  <View style={styles.container}>
@@ -60,7 +69,7 @@ export const Home = (props: any) => {
60
69
  style={{ ...styles.textLink, marginTop: 12 }}
61
70
  onPress={() =>
62
71
  orderState?.options?.address?.address
63
- ? onNavigationRedirect('BusinessList', { isGuestUser: true })
72
+ ? onNavigationRedirect(!!businessSlug ? 'Business' : 'BusinessList', { isGuestUser: true })
64
73
  : onNavigationRedirect('AddressForm', { isGuestUser: true })
65
74
  }>
66
75
  <OText weight="normal" size={18} color={theme.colors.white}>
@@ -20,7 +20,8 @@ export const OrderItAgain = (props: OrderItAgainParams) => {
20
20
  currentCart,
21
21
  handleUpdateProducts,
22
22
  navigation,
23
- searchValue
23
+ searchValue,
24
+ businessSingleId
24
25
  } = props
25
26
 
26
27
  const [, t] = useLanguage()
@@ -65,6 +66,7 @@ export const OrderItAgain = (props: OrderItAgainParams) => {
65
66
  handleUpdateProducts={handleUpdateProducts}
66
67
  navigation={navigation}
67
68
  isPreviously
69
+ businessSingleId={businessSingleId}
68
70
  />
69
71
  </ProductWrapper>
70
72
  ))}
@@ -1,5 +1,5 @@
1
- import React, { useRef } from 'react'
2
- import { useUtils, PageBanner as PageBannerController } from 'ordering-components/native'
1
+ import React, { useEffect, useState, useRef } from 'react'
2
+ import { useUtils, useEvent, PageBanner as PageBannerController } from 'ordering-components/native'
3
3
  import { View, StyleSheet, Dimensions, TouchableOpacity } from 'react-native'
4
4
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
5
5
  import Carousel from 'react-native-snap-carousel'
@@ -16,7 +16,10 @@ const PageBannerUI = (props: any) => {
16
16
 
17
17
  const theme = useTheme();
18
18
  const [{ optimizeImage }] = useUtils();
19
- const carouselRef = useRef(null)
19
+ const [events] = useEvent()
20
+ const carouselRef = useRef<any>(null)
21
+ const [currentIndex, setCurrentIndex] = useState(0)
22
+ const [viewedBanner, setViewedBanner] = useState<any>(null)
20
23
 
21
24
  const windowWidth = Dimensions.get('window').width;
22
25
 
@@ -44,7 +47,8 @@ const PageBannerUI = (props: any) => {
44
47
  navigation.navigate(route, params)
45
48
  }
46
49
 
47
- const handleGoToPage = (action: any) => {
50
+ const handleGoToPage = (item: any) => {
51
+ const action = item.action
48
52
  if (!action?.url) return
49
53
  let slug
50
54
  if (action.type === 'business') {
@@ -62,12 +66,14 @@ const PageBannerUI = (props: any) => {
62
66
  productId: action.product_id
63
67
  })
64
68
  }
69
+ const clickedBanner = pageBannerState.result.find(banner => banner.id === item?.banner_id)
70
+ events.emit('promotion_clicked', clickedBanner)
65
71
  }
66
72
 
67
73
  const renderItem = ({ item, index }) => {
68
74
  return (
69
75
  <TouchableOpacity
70
- onPress={() => handleGoToPage(item.action)}
76
+ onPress={() => handleGoToPage(item)}
71
77
  >
72
78
  <View style={styles.sliderWrapper}>
73
79
  <FastImage
@@ -80,6 +86,24 @@ const PageBannerUI = (props: any) => {
80
86
  )
81
87
  }
82
88
 
89
+ const updateIndex = () => {
90
+ setCurrentIndex(carouselRef?.current?.currentIndex)
91
+ }
92
+
93
+ useEffect(() => {
94
+ if (pageBannerState.loading) return
95
+ if (pageBannerState.banner?.items && pageBannerState.banner?.items.length > 0) {
96
+ const bannerId = pageBannerState.banner.items[currentIndex]?.banner_id
97
+ if (pageBannerState.result && bannerId) {
98
+ const _viewedBanner = pageBannerState.result.find(banner => banner.id === bannerId)
99
+ if (_viewedBanner?.id !== viewedBanner?.id) {
100
+ setViewedBanner(_viewedBanner)
101
+ events.emit('promotion_viewed', _viewedBanner)
102
+ }
103
+ }
104
+ }
105
+ }, [pageBannerState.loading, currentIndex, viewedBanner])
106
+
83
107
  return (
84
108
  <>
85
109
  {pageBannerState.loading ? (
@@ -128,6 +152,7 @@ const PageBannerUI = (props: any) => {
128
152
  pagingEnabled
129
153
  removeClippedSubviews={false}
130
154
  inactiveSlideOpacity={1}
155
+ onSnapToItem={updateIndex}
131
156
  />
132
157
  </PageBannerWrapper>
133
158
  )}
@@ -20,7 +20,8 @@ import {
20
20
  useUtils,
21
21
  ToastType,
22
22
  useToast,
23
- useConfig
23
+ useConfig,
24
+ useEvent
24
25
  } from 'ordering-components/native';
25
26
  import uuid from 'react-native-uuid';
26
27
  import { useTheme } from 'styled-components/native';
@@ -81,6 +82,7 @@ export const ProductOptionsUI = (props: any) => {
81
82
 
82
83
  const theme = useTheme();
83
84
  const [, { showToast }] = useToast()
85
+ const [events] = useEvent()
84
86
 
85
87
  const isChewLayout = theme?.header?.components?.layout?.type?.toLowerCase() === 'chew'
86
88
 
@@ -203,6 +205,7 @@ export const ProductOptionsUI = (props: any) => {
203
205
  const [summaryRefHeight, setSummaryRefHeight] = useState(0)
204
206
  const [isScrollAvailable, setIsScrollAvailable] = useState(null)
205
207
  const [editionsLayoutY, setEditionsLayoutY] = useState(null)
208
+ const [viewedProduct, setViewedProduct] = useState<any>(null)
206
209
 
207
210
  const guestCheckoutEnabled = configs?.guest_checkout_enabled?.value === '1'
208
211
  const orderTypeEnabled = !orderTypeList[orderState?.options?.type - 1] || configs?.allowed_order_types_guest_checkout?.value?.includes(orderTypeList[orderState?.options?.type - 1])
@@ -515,6 +518,12 @@ export const ProductOptionsUI = (props: any) => {
515
518
  }
516
519
  }, [])
517
520
 
521
+ useEffect(() => {
522
+ if (!product?.id || product?.id === viewedProduct?.id) return
523
+ setViewedProduct(product)
524
+ events.emit('product_viewed', product)
525
+ }, [product?.id, viewedProduct])
526
+
518
527
  return (
519
528
  <SafeAreaView style={{ flex: 1 }}>
520
529
  <View style={styles.wrapperNavbar}>
@@ -40,7 +40,8 @@ const SingleProductCardUI = React.memo((props: SingleProductCardParams) => {
40
40
  navigation,
41
41
  businessId,
42
42
  isPreviously,
43
- viewString
43
+ viewString,
44
+ businessSingleId
44
45
  } = props;
45
46
 
46
47
  const theme = useTheme();
@@ -180,7 +181,7 @@ const SingleProductCardUI = React.memo((props: SingleProductCardParams) => {
180
181
  >
181
182
  <View style={{ flexDirection: logoPosition === 'left' ? 'row-reverse' : 'row' }}>
182
183
  {productAddedToCartLength > 0 && (
183
- <QuantityContainer style={[styles.quantityContainer, {
184
+ <QuantityContainer businessSingleId={businessSingleId} style={[styles.quantityContainer, {
184
185
  transform: [{ translateX: 25 }, { translateY: -25 }],
185
186
  }]}>
186
187
  <OText size={12} color={theme.colors.white}>{productAddedToCartLength.toString()}</OText>
@@ -18,6 +18,11 @@ export const QuantityContainer = styled.View`
18
18
  background: ${({ theme }: any) => theme.colors.primary};
19
19
  align-items: center;
20
20
  justify-content: center;
21
+ ${({businessSingleId} : any) => businessSingleId ? css`
22
+ left: 0;
23
+ ` : css`
24
+ right: 0;
25
+ `}
21
26
  `
22
27
  export const PricesContainer = styled.View`
23
28
  flex-direction: row;
@@ -196,6 +196,7 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
196
196
  {showCartList && cartList.map((cart: any, i: number) => (
197
197
  <CartList key={i}>
198
198
  <Cart
199
+ isFromUpselling
199
200
  cart={cart}
200
201
  cartuuid={cart.uuid}
201
202
  hideUpselling
@@ -92,7 +92,8 @@ export interface AddressFormParams {
92
92
  hasAddressDefault?: any,
93
93
  isFromCheckout?: boolean
94
94
  afterSignup?: boolean
95
- isGuestFromStore?: boolean
95
+ isGuestFromStore?: boolean,
96
+ businessSlug?: number | string
96
97
  }
97
98
  export interface SignupParams {
98
99
  navigation?: any;
@@ -254,6 +255,7 @@ export interface BusinessProductsListingParams {
254
255
  handleUpdateProfessionals?: any;
255
256
  onBusinessClick?: any;
256
257
  onNavigationRedirect?: any;
258
+ businessSingleId?: number | string
257
259
  }
258
260
  export interface BusinessBasicInformationParams {
259
261
  navigation?: any;
@@ -305,6 +307,7 @@ export interface BusinessProductsListParams {
305
307
  handleUpdateProducts?: any,
306
308
  navigation?: any;
307
309
  previouslyProducts?: any;
310
+ businessSingleId?: number | string
308
311
  }
309
312
  export interface SingleProductCardParams {
310
313
  businessId: any;
@@ -320,6 +323,8 @@ export interface SingleProductCardParams {
320
323
  navigation?: any;
321
324
  isPreviously?: any;
322
325
  isProductId?: any;
326
+ viewString?: string;
327
+ businessSingleId?: number
323
328
  }
324
329
  export interface BusinessInformationParams {
325
330
  navigation?: any,
@@ -788,7 +793,8 @@ export interface OrderItAgainParams {
788
793
  currentCart: any,
789
794
  handleUpdateProducts: any,
790
795
  navigation: any,
791
- searchValue?: string
796
+ searchValue?: string,
797
+ businessSingleId?: number | string
792
798
  }
793
799
 
794
800
  export interface PreviousProductsOrderedParams {