ordering-ui-react-native 0.18.26 → 0.18.28
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 +1 -1
- package/themes/original/src/components/AnalyticsSegment/index.tsx +164 -8
- package/themes/original/src/components/BusinessItemAccordion/index.tsx +14 -2
- package/themes/original/src/components/BusinessProductsListing/index.tsx +37 -3
- package/themes/original/src/components/Cart/index.tsx +6 -2
- package/themes/original/src/components/Checkout/index.tsx +15 -3
- package/themes/original/src/components/CouponControl/index.tsx +10 -3
- package/themes/original/src/components/MultiCheckout/index.tsx +8 -2
- package/themes/original/src/components/PageBanner/index.tsx +30 -5
- package/themes/original/src/components/ProductForm/index.tsx +10 -1
- package/themes/original/src/components/UpsellingProducts/index.tsx +1 -0
package/package.json
CHANGED
|
@@ -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('
|
|
226
|
+
events.on('product_viewed', handleProductViewed)
|
|
91
227
|
events.on('product_added', handleProductAdded)
|
|
92
|
-
events.on('
|
|
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('
|
|
248
|
+
events.off('product_viewed', handleProductViewed)
|
|
101
249
|
events.off('product_added', handleProductAdded)
|
|
102
|
-
events.off('
|
|
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
|
|
@@ -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'
|
|
@@ -80,6 +81,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
80
81
|
const [{ parsePrice }] = useUtils()
|
|
81
82
|
const [, { showToast }] = useToast()
|
|
82
83
|
const [{ configs }] = useConfig()
|
|
84
|
+
const [events] = useEvent()
|
|
83
85
|
const isFocused = useIsFocused();
|
|
84
86
|
const isPreOrder = configs?.preorder_status_enabled?.value === '1'
|
|
85
87
|
|
|
@@ -133,6 +135,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
133
135
|
const [openService, setOpenService] = useState(false)
|
|
134
136
|
const [currentProduct, setCurrentProduct] = useState(null)
|
|
135
137
|
const [searchBarHeight, setSearchBarHeight] = useState(60)
|
|
138
|
+
const [viewedCategory, setViewedCategory] = useState<any>(null)
|
|
136
139
|
|
|
137
140
|
const isCheckoutMultiBusinessEnabled: Boolean = configs?.checkout_multi_business_enabled?.value === '1'
|
|
138
141
|
const isQuickAddProduct = configs?.add_product_with_one_click?.value === '1'
|
|
@@ -178,6 +181,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
178
181
|
productAddedToCartLength
|
|
179
182
|
})
|
|
180
183
|
}
|
|
184
|
+
events.emit('product_clicked', product)
|
|
181
185
|
}
|
|
182
186
|
|
|
183
187
|
const handleCancel = () => {
|
|
@@ -309,6 +313,36 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
309
313
|
return acc = acc
|
|
310
314
|
}, currentCart?.subtotal)
|
|
311
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
|
+
|
|
312
346
|
return (
|
|
313
347
|
<>
|
|
314
348
|
<View style={{ flex: 1, backgroundColor: backgroundColor }}>
|
|
@@ -343,12 +377,12 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
343
377
|
<WrapSearchBar>
|
|
344
378
|
<SearchBar
|
|
345
379
|
autoFocus
|
|
346
|
-
onSearch={
|
|
380
|
+
onSearch={onChangeSearch}
|
|
347
381
|
onCancel={() => handleCancel()}
|
|
348
382
|
isCancelXButtonShow
|
|
349
383
|
noBorderShow
|
|
350
384
|
placeholder={t('SEARCH_PRODUCTS', 'Search Products')}
|
|
351
|
-
lazyLoad
|
|
385
|
+
lazyLoad
|
|
352
386
|
/>
|
|
353
387
|
</WrapSearchBar>
|
|
354
388
|
)}
|
|
@@ -51,7 +51,8 @@ const CartUI = (props: any) => {
|
|
|
51
51
|
preorderTimeRange,
|
|
52
52
|
preorderMaximumDays,
|
|
53
53
|
preorderMinimumDays,
|
|
54
|
-
cateringTypes
|
|
54
|
+
cateringTypes,
|
|
55
|
+
isFromUpselling
|
|
55
56
|
} = props
|
|
56
57
|
|
|
57
58
|
const theme = useTheme();
|
|
@@ -74,6 +75,7 @@ const CartUI = (props: any) => {
|
|
|
74
75
|
const business: any = (orderState?.carts && Object.values(orderState.carts).find((_cart: any) => _cart?.uuid === props.cartuuid)) ?? {}
|
|
75
76
|
const businessId = business?.business_id ?? null
|
|
76
77
|
const placeSpotTypes = [4]
|
|
78
|
+
const isChewLayout = theme?.header?.components?.layout?.type?.toLowerCase() === 'chew'
|
|
77
79
|
const hideCartComments = theme?.business_view?.components?.cart?.components?.comments?.hidden
|
|
78
80
|
const hideCartDiscount = theme?.business_view?.components?.cart?.components?.discount?.hidden
|
|
79
81
|
const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
|
|
@@ -231,6 +233,7 @@ const CartUI = (props: any) => {
|
|
|
231
233
|
handleClickCheckout={() => setOpenUpselling(true)}
|
|
232
234
|
checkoutButtonDisabled={(openUpselling && !canOpenUpselling) || subtotalWithTaxes < cart?.minimum || !cart?.valid_address}
|
|
233
235
|
isMultiCheckout={isMultiCheckout}
|
|
236
|
+
isFromUpselling={isFromUpselling}
|
|
234
237
|
>
|
|
235
238
|
{cart?.products?.length > 0 && cart?.products.map((product: any, i: number) => (
|
|
236
239
|
<ProductItemAccordion
|
|
@@ -383,7 +386,7 @@ const CartUI = (props: any) => {
|
|
|
383
386
|
</OSTable>
|
|
384
387
|
))
|
|
385
388
|
}
|
|
386
|
-
{orderState?.options?.type === 1 && cart?.delivery_price > 0 && cart?.delivery_price_with_discount >= 0 && !hideDeliveryFee && (
|
|
389
|
+
{orderState?.options?.type === 1 && cart?.delivery_price > 0 && cart?.delivery_price_with_discount >= 0 && !hideDeliveryFee && isChewLayout && (
|
|
387
390
|
<OSTable>
|
|
388
391
|
<OText size={12} lineHeight={18}>{t('DELIVERY_FEE_AFTER_DISCOUNT', 'Delivery Fee After Discount')}</OText>
|
|
389
392
|
<OText size={12} lineHeight={18}>{parsePrice(cart?.delivery_price_with_discount)}</OText>
|
|
@@ -417,6 +420,7 @@ const CartUI = (props: any) => {
|
|
|
417
420
|
<CouponControl
|
|
418
421
|
businessId={businessId}
|
|
419
422
|
price={cart.total}
|
|
423
|
+
cart={cart}
|
|
420
424
|
/>
|
|
421
425
|
</OSCoupon>
|
|
422
426
|
</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>([]);
|
|
@@ -166,6 +168,9 @@ const CheckoutUI = (props: any) => {
|
|
|
166
168
|
const hideBusinessMap = theme?.checkout?.components?.business?.components?.map?.hidden
|
|
167
169
|
const hideCustomerDetails = theme?.checkout?.components?.customer?.hidden
|
|
168
170
|
|
|
171
|
+
const creditPointPlan = loyaltyPlansState?.result?.find((loyal: any) => loyal.type === 'credit_point')
|
|
172
|
+
const creditPointPlanOnBusiness = creditPointPlan?.businesses?.find((b: any) => b.business_id === cart?.business_id && b.accumulates)
|
|
173
|
+
|
|
169
174
|
const isPreOrder = configs?.preorder_status_enabled?.value === '1'
|
|
170
175
|
const subtotalWithTaxes = cart?.taxes?.reduce((acc: any, item: any) => {
|
|
171
176
|
if (item?.type === 1)
|
|
@@ -326,6 +331,10 @@ const CheckoutUI = (props: any) => {
|
|
|
326
331
|
)
|
|
327
332
|
}
|
|
328
333
|
|
|
334
|
+
useEffect(() => {
|
|
335
|
+
cart && events.emit('checkout_started', cart)
|
|
336
|
+
}, [])
|
|
337
|
+
|
|
329
338
|
return (
|
|
330
339
|
<>
|
|
331
340
|
<Container noPadding>
|
|
@@ -729,7 +738,10 @@ const CheckoutUI = (props: any) => {
|
|
|
729
738
|
placeSpotTypes={placeSpotTypes}
|
|
730
739
|
businessConfigs={businessConfigs}
|
|
731
740
|
maxDate={maxDate}
|
|
732
|
-
loyaltyRewardRate={
|
|
741
|
+
loyaltyRewardRate={
|
|
742
|
+
creditPointPlanOnBusiness?.accumulation_rate ??
|
|
743
|
+
(!!creditPointPlanOnBusiness && creditPointPlan?.accumulation_rate) ?? 0
|
|
744
|
+
}
|
|
733
745
|
/>
|
|
734
746
|
</>
|
|
735
747
|
)}
|
|
@@ -739,7 +751,7 @@ const CheckoutUI = (props: any) => {
|
|
|
739
751
|
|
|
740
752
|
{!cartState.loading && cart && (
|
|
741
753
|
<View>
|
|
742
|
-
<ChErrors style={{ marginBottom:
|
|
754
|
+
<ChErrors style={{ marginBottom: 30 }}>
|
|
743
755
|
{!cart?.valid_address && cart?.status !== 2 && (
|
|
744
756
|
<OText
|
|
745
757
|
color={theme.colors.error}
|
|
@@ -766,7 +778,7 @@ const CheckoutUI = (props: any) => {
|
|
|
766
778
|
{t('WARNING_INVALID_PRODUCTS_CHECKOUT', 'To continue with your checkout, please remove from your cart the products that are not available.')}
|
|
767
779
|
</OText>
|
|
768
780
|
)}
|
|
769
|
-
{!cart?.valid_preorder && (
|
|
781
|
+
{cart?.valid_preorder !== undefined && !cart?.valid_preorder && (
|
|
770
782
|
<OText
|
|
771
783
|
color={theme.colors.error}
|
|
772
784
|
size={12}
|
|
@@ -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={() =>
|
|
104
|
+
onClick={() => onButtonApplyClick()}
|
|
98
105
|
bgColor={theme.colors.primary}
|
|
99
106
|
borderColor={theme.colors.primary}
|
|
100
107
|
textStyle={{ color: 'white', fontSize: 12 }}
|
|
@@ -60,7 +60,7 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
60
60
|
handleSelectWallet,
|
|
61
61
|
handlePaymethodDataChange,
|
|
62
62
|
cartUuid,
|
|
63
|
-
|
|
63
|
+
loyaltyPlansState,
|
|
64
64
|
totalCartsFee,
|
|
65
65
|
cartGroup,
|
|
66
66
|
onNavigationRedirectReplace
|
|
@@ -92,7 +92,13 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
92
92
|
? JSON.parse(configs?.driver_tip_options?.value) || []
|
|
93
93
|
: configs?.driver_tip_options?.value || []
|
|
94
94
|
|
|
95
|
-
const
|
|
95
|
+
const creditPointPlan = loyaltyPlansState?.result?.find((loyal: any) => loyal.type === 'credit_point')
|
|
96
|
+
const businessIds = openCarts.map((cart: any) => cart.business_id)
|
|
97
|
+
const loyalBusinessIds = creditPointPlan?.businesses?.filter((b: any) => b.accumulates).map((item: any) => item.business_id)
|
|
98
|
+
const creditPointPlanOnBusiness = businessIds.every((bid: any) => loyalBusinessIds.includes(bid)) && creditPointPlan
|
|
99
|
+
|
|
100
|
+
const loyaltyRewardValue = creditPointPlanOnBusiness?.accumulation_rate
|
|
101
|
+
? Math.round(openCarts.reduce((sum: any, cart: any) => sum + cart?.subtotal, 0) / creditPointPlanOnBusiness?.accumulation_rate) : 0
|
|
96
102
|
|
|
97
103
|
const [isUserDetailsEdit, setIsUserDetailsEdit] = useState(false);
|
|
98
104
|
const [phoneUpdate, setPhoneUpdate] = useState(false);
|
|
@@ -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
|
|
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 = (
|
|
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
|
|
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}>
|