ordering-ui-react-native 0.18.27 → 0.18.29
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/business/src/components/NewOrderNotification/index.tsx +4 -4
- package/themes/original/src/components/AddressForm/index.tsx +9 -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 +49 -4
- package/themes/original/src/components/Cart/index.tsx +4 -1
- package/themes/original/src/components/Checkout/index.tsx +6 -0
- package/themes/original/src/components/CouponControl/index.tsx +10 -3
- package/themes/original/src/components/GiftCard/PurchaseGiftCard/index.tsx +7 -3
- package/themes/original/src/components/GiftCard/PurchaseGiftCard/styles.tsx +2 -0
- package/themes/original/src/components/MultiCartsPaymethodsAndWallets/index.tsx +26 -4
- package/themes/original/src/components/MultiCheckout/index.tsx +16 -3
- package/themes/original/src/components/PageBanner/index.tsx +31 -6
- package/themes/original/src/components/ProductForm/index.tsx +10 -1
- package/themes/original/src/components/Promotions/index.tsx +1 -1
- package/themes/original/src/components/UpsellingProducts/index.tsx +1 -0
package/package.json
CHANGED
|
@@ -45,7 +45,7 @@ const NewOrderNotificationUI = (props: any) => {
|
|
|
45
45
|
},
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const notificationSound = new Sound(theme.sounds.notification, '', () => {});
|
|
48
|
+
const notificationSound = new Sound(theme.sounds.notification, '', () => { });
|
|
49
49
|
|
|
50
50
|
let _timeout: any = null
|
|
51
51
|
|
|
@@ -75,11 +75,11 @@ const NewOrderNotificationUI = (props: any) => {
|
|
|
75
75
|
await fetch(`${ordering.root}/users/${user.id}/locations`, {
|
|
76
76
|
method: 'POST',
|
|
77
77
|
body: JSON.stringify({
|
|
78
|
-
location: JSON.stringify({location: `{lat: ${location.latitude}, lng: ${location.longitude}}`})
|
|
78
|
+
location: JSON.stringify({ location: `{lat: ${location.latitude}, lng: ${location.longitude}}` })
|
|
79
79
|
}),
|
|
80
80
|
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }
|
|
81
81
|
})
|
|
82
|
-
} catch {}
|
|
82
|
+
} catch { }
|
|
83
83
|
const duration = moment.duration(moment().diff(moment.utc(value?.last_driver_assigned_at)))
|
|
84
84
|
const assignedSecondsDiff = duration.asSeconds()
|
|
85
85
|
if (assignedSecondsDiff < 5 && !isBusinessApp) {
|
|
@@ -89,7 +89,7 @@ const NewOrderNotificationUI = (props: any) => {
|
|
|
89
89
|
if (evtType === 3 || value.author_id === user.id) return
|
|
90
90
|
handlePlayNotificationSound({
|
|
91
91
|
evt: evtType,
|
|
92
|
-
orderId:
|
|
92
|
+
orderId: value?.order_id
|
|
93
93
|
})
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
useToast,
|
|
17
17
|
ToastType
|
|
18
18
|
} from 'ordering-components/native';
|
|
19
|
+
import { DeviceOrientationMethods } from '../../../../../src/hooks/DeviceOrientation'
|
|
20
|
+
|
|
19
21
|
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
|
|
20
22
|
import Spinner from 'react-native-loading-spinner-overlay';
|
|
21
23
|
import { useForm, Controller } from 'react-hook-form';
|
|
@@ -38,6 +40,8 @@ import {
|
|
|
38
40
|
import { GPSButton } from '../GPSButton';
|
|
39
41
|
import { ScrollView } from 'react-native-gesture-handler';
|
|
40
42
|
|
|
43
|
+
const { useDeviceOrientation } = DeviceOrientationMethods
|
|
44
|
+
|
|
41
45
|
const inputNames = [
|
|
42
46
|
{ name: 'address', code: 'Address' },
|
|
43
47
|
{ name: 'internal_number', code: 'Internal number' },
|
|
@@ -66,6 +70,8 @@ const AddressFormUI = (props: AddressFormParams) => {
|
|
|
66
70
|
} = props;
|
|
67
71
|
|
|
68
72
|
const theme = useTheme();
|
|
73
|
+
const [orientationState] = useDeviceOrientation();
|
|
74
|
+
|
|
69
75
|
const [autoCompleteInputFocused, setAutoCompleteInputFocused] = useState(false)
|
|
70
76
|
|
|
71
77
|
const tagsName = [
|
|
@@ -75,6 +81,8 @@ const AddressFormUI = (props: AddressFormParams) => {
|
|
|
75
81
|
{ icon: theme.images.general.tag_plus, value: 'other' },
|
|
76
82
|
];
|
|
77
83
|
|
|
84
|
+
const HEIGHT_SCREEN = orientationState?.dimensions?.height
|
|
85
|
+
|
|
78
86
|
const styles = StyleSheet.create({
|
|
79
87
|
iconContainer: {
|
|
80
88
|
display: 'flex',
|
|
@@ -524,7 +532,7 @@ const AddressFormUI = (props: AddressFormParams) => {
|
|
|
524
532
|
/>
|
|
525
533
|
</View>
|
|
526
534
|
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
|
|
527
|
-
<AddressFormContainer style={{ height:
|
|
535
|
+
<AddressFormContainer style={{ height: HEIGHT_SCREEN * .78, overflow: 'scroll' }}>
|
|
528
536
|
<View>
|
|
529
537
|
<FormInput>
|
|
530
538
|
<AutocompleteInput>
|
|
@@ -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
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
|
2
|
-
import { View, TouchableOpacity, StyleSheet, SafeAreaView, Dimensions, Platform, KeyboardAvoidingViewBase, KeyboardAvoidingView, Vibration } from 'react-native'
|
|
2
|
+
import { View, TouchableOpacity, StyleSheet, SafeAreaView, Dimensions, Platform, KeyboardAvoidingViewBase, KeyboardAvoidingView, Vibration, BackHandler } from 'react-native'
|
|
3
3
|
import { IOScrollView } from 'react-native-intersection-observer'
|
|
4
4
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
5
5
|
import { useTheme } from 'styled-components/native';
|
|
@@ -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,47 @@ 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
|
+
|
|
346
|
+
useEffect(() => {
|
|
347
|
+
const handleArrowBack: any = () => {
|
|
348
|
+
navigation.goBack()
|
|
349
|
+
return true
|
|
350
|
+
}
|
|
351
|
+
BackHandler.addEventListener('hardwareBackPress', handleArrowBack);
|
|
352
|
+
return () => {
|
|
353
|
+
BackHandler.removeEventListener('hardwareBackPress', handleArrowBack);
|
|
354
|
+
}
|
|
355
|
+
}, [])
|
|
356
|
+
|
|
312
357
|
return (
|
|
313
358
|
<>
|
|
314
359
|
<View style={{ flex: 1, backgroundColor: backgroundColor }}>
|
|
@@ -343,12 +388,12 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
343
388
|
<WrapSearchBar>
|
|
344
389
|
<SearchBar
|
|
345
390
|
autoFocus
|
|
346
|
-
onSearch={
|
|
391
|
+
onSearch={onChangeSearch}
|
|
347
392
|
onCancel={() => handleCancel()}
|
|
348
393
|
isCancelXButtonShow
|
|
349
394
|
noBorderShow
|
|
350
395
|
placeholder={t('SEARCH_PRODUCTS', 'Search Products')}
|
|
351
|
-
lazyLoad
|
|
396
|
+
lazyLoad
|
|
352
397
|
/>
|
|
353
398
|
</WrapSearchBar>
|
|
354
399
|
)}
|
|
@@ -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();
|
|
@@ -232,6 +233,7 @@ const CartUI = (props: any) => {
|
|
|
232
233
|
handleClickCheckout={() => setOpenUpselling(true)}
|
|
233
234
|
checkoutButtonDisabled={(openUpselling && !canOpenUpselling) || subtotalWithTaxes < cart?.minimum || !cart?.valid_address}
|
|
234
235
|
isMultiCheckout={isMultiCheckout}
|
|
236
|
+
isFromUpselling={isFromUpselling}
|
|
235
237
|
>
|
|
236
238
|
{cart?.products?.length > 0 && cart?.products.map((product: any, i: number) => (
|
|
237
239
|
<ProductItemAccordion
|
|
@@ -418,6 +420,7 @@ const CartUI = (props: any) => {
|
|
|
418
420
|
<CouponControl
|
|
419
421
|
businessId={businessId}
|
|
420
422
|
price={cart.total}
|
|
423
|
+
cart={cart}
|
|
421
424
|
/>
|
|
422
425
|
</OSCoupon>
|
|
423
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>([]);
|
|
@@ -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={() =>
|
|
104
|
+
onClick={() => onButtonApplyClick()}
|
|
98
105
|
bgColor={theme.colors.primary}
|
|
99
106
|
borderColor={theme.colors.primary}
|
|
100
107
|
textStyle={{ color: 'white', fontSize: 12 }}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
useLanguage,
|
|
4
4
|
PurchaseGiftCard as PurchaseGiftCardController
|
|
5
5
|
} from 'ordering-components/native'
|
|
6
|
-
import { StyleSheet, View, TouchableOpacity } from 'react-native'
|
|
6
|
+
import { StyleSheet, View, TouchableOpacity, ScrollView } from 'react-native'
|
|
7
7
|
import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
|
|
8
8
|
import { useTheme } from 'styled-components/native';
|
|
9
9
|
import { OText, OButton, OIcon } from '../../shared';
|
|
@@ -44,7 +44,11 @@ const PurchaseGiftCardUI = (props: any) => {
|
|
|
44
44
|
<Container>
|
|
45
45
|
<OText color={theme.colors.textNormal} weight='bold' size={20} mBottom={40}>{t('PURCHASE_GIFT_CARD', 'Purchase gift card')}</OText>
|
|
46
46
|
<OText color={theme.colors.textNormal} size={14}>{t('SELECT_ONE_OPTION', 'Select one option')}</OText>
|
|
47
|
-
<
|
|
47
|
+
<ScrollView
|
|
48
|
+
contentContainerStyle={{
|
|
49
|
+
flexGrow: 1
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
48
52
|
{productsListState.loading && (
|
|
49
53
|
[...Array(5).keys()].map(i => (
|
|
50
54
|
<View key={i} style={style.itemStyle}>
|
|
@@ -72,7 +76,7 @@ const PurchaseGiftCardUI = (props: any) => {
|
|
|
72
76
|
<OText color={theme.colors.textNormal} size={14}>{product.name}</OText>
|
|
73
77
|
</TouchableOpacity>
|
|
74
78
|
))}
|
|
75
|
-
</
|
|
79
|
+
</ScrollView>
|
|
76
80
|
<OButton
|
|
77
81
|
onClick={() => handleAccept()}
|
|
78
82
|
text={t('ACCEPT', 'Accept')}
|
|
@@ -25,6 +25,7 @@ const MultiCartsPaymethodsAndWalletsUI = (props: any) => {
|
|
|
25
25
|
businessIds,
|
|
26
26
|
paymethodsAndWallets,
|
|
27
27
|
walletsState,
|
|
28
|
+
walletsPaymethod,
|
|
28
29
|
paymethodSelected,
|
|
29
30
|
handleSelectPaymethod,
|
|
30
31
|
handleSelectWallet,
|
|
@@ -52,6 +53,8 @@ const MultiCartsPaymethodsAndWalletsUI = (props: any) => {
|
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
|
|
56
|
+
const creditBalance: any = (wallet: any) => ` = ${parsePrice(wallet.balance / wallet.redemption_rate, { isTruncable: true })}`
|
|
57
|
+
|
|
55
58
|
const getPayIcon = (method: string) => {
|
|
56
59
|
switch (method) {
|
|
57
60
|
case 'cash':
|
|
@@ -169,13 +172,16 @@ const MultiCartsPaymethodsAndWalletsUI = (props: any) => {
|
|
|
169
172
|
</>
|
|
170
173
|
) : (
|
|
171
174
|
<>
|
|
172
|
-
{walletsState?.result?.filter((wallet: any) =>
|
|
175
|
+
{walletsState?.result?.filter((wallet: any) =>
|
|
176
|
+
paymethodsAndWallets.wallets.find((item: any) => item.type === wallet.type))
|
|
177
|
+
.map((wallet: any, idx: any) => walletName[wallet.type]?.isActive &&
|
|
178
|
+
(
|
|
173
179
|
<WalletItem
|
|
174
180
|
key={wallet.type}
|
|
175
181
|
isBottomBorder={idx === paymethodsAndWallets.wallets?.length - 1}
|
|
176
|
-
onPress={() => handleSelectWallet(
|
|
182
|
+
onPress={() => handleSelectWallet(!!!walletsPaymethod?.find((walletPay: any) => walletPay.wallet_id === wallet.id)?.id, wallet)}
|
|
177
183
|
>
|
|
178
|
-
{
|
|
184
|
+
{!!walletsPaymethod?.find((walletPay: any) => walletPay.wallet_id === wallet.id)?.id ? (
|
|
179
185
|
<MaterialCommunityIcons
|
|
180
186
|
name="checkbox-marked"
|
|
181
187
|
size={25}
|
|
@@ -189,7 +195,23 @@ const MultiCartsPaymethodsAndWalletsUI = (props: any) => {
|
|
|
189
195
|
/>
|
|
190
196
|
)}
|
|
191
197
|
<OText size={12} style={{ flex: 1, marginLeft: 15 }}>{walletName[wallet.type]?.name}</OText>
|
|
192
|
-
|
|
198
|
+
{wallet.type === 'cash' && (
|
|
199
|
+
<OText>
|
|
200
|
+
{parsePrice(wallet?.balance, { isTruncable: true })}
|
|
201
|
+
</OText>
|
|
202
|
+
)}
|
|
203
|
+
{wallet.type === 'credit_point' && (
|
|
204
|
+
<OText>
|
|
205
|
+
<OText color={theme.colors.primary} weight='bold'>
|
|
206
|
+
{`${wallet?.balance} ${t('POINTS', 'Points')}`}
|
|
207
|
+
</OText>
|
|
208
|
+
<OText>
|
|
209
|
+
{wallet?.balance > 0
|
|
210
|
+
? creditBalance(wallet)
|
|
211
|
+
: null}
|
|
212
|
+
</OText>
|
|
213
|
+
</OText>
|
|
214
|
+
)}
|
|
193
215
|
</WalletItem>
|
|
194
216
|
))}
|
|
195
217
|
</>
|
|
@@ -63,6 +63,7 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
63
63
|
loyaltyPlansState,
|
|
64
64
|
totalCartsFee,
|
|
65
65
|
cartGroup,
|
|
66
|
+
walletState,
|
|
66
67
|
onNavigationRedirectReplace
|
|
67
68
|
} = props
|
|
68
69
|
|
|
@@ -86,8 +87,11 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
86
87
|
const configTypes = configs?.order_types_allowed?.value.split('|').map((value: any) => Number(value)) || []
|
|
87
88
|
const isPreOrder = configs?.preorder_status_enabled?.value === '1'
|
|
88
89
|
const isMultiDriverTips = configs?.checkout_multi_business_enabled?.value === '1'
|
|
89
|
-
const isDisablePlaceOrderButton = !(paymethodSelected?.paymethod_id || paymethodSelected?.wallet_id) || (paymethodSelected?.paymethod?.gateway === 'stripe' && !paymethodSelected?.paymethod_data)
|
|
90
90
|
const walletCarts = (Object.values(carts)?.filter((cart: any) => cart?.products && cart?.products?.length && cart?.status !== 2 && cart?.valid_schedule && cart?.valid_products && cart?.valid_address && cart?.valid_maximum && cart?.valid_minimum && cart?.wallets) || null) || []
|
|
91
|
+
const isDisablePlaceOrderButton = cartGroup?.loading || (!(paymethodSelected?.paymethod_id || paymethodSelected?.wallet_id) && cartGroup?.result?.balance > 0) ||
|
|
92
|
+
(paymethodSelected?.paymethod?.gateway === 'stripe' && !paymethodSelected?.paymethod_data) ||
|
|
93
|
+
walletCarts.length > 0
|
|
94
|
+
|
|
91
95
|
const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
|
|
92
96
|
? JSON.parse(configs?.driver_tip_options?.value) || []
|
|
93
97
|
: configs?.driver_tip_options?.value || []
|
|
@@ -171,6 +175,12 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
171
175
|
}
|
|
172
176
|
}, [openCarts])
|
|
173
177
|
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
if (walletState.error) {
|
|
180
|
+
showToast(ToastType.Error, t(walletState.error, walletState.error?.[0]?.replace(/_/g, ' ')))
|
|
181
|
+
}
|
|
182
|
+
}, [walletState.error])
|
|
183
|
+
|
|
174
184
|
return (
|
|
175
185
|
<>
|
|
176
186
|
<Container noPadding>
|
|
@@ -248,6 +258,7 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
248
258
|
<MultiCartsPaymethodsAndWallets
|
|
249
259
|
openCarts={openCarts}
|
|
250
260
|
paymethodSelected={paymethodSelected}
|
|
261
|
+
walletsPaymethod={cartGroup?.result?.wallets}
|
|
251
262
|
handleSelectPaymethod={handleSelectPaymethod}
|
|
252
263
|
handleSelectWallet={handleSelectWallet}
|
|
253
264
|
handlePaymethodDataChange={handlePaymethodDataChange}
|
|
@@ -346,12 +357,14 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
346
357
|
)}
|
|
347
358
|
{openCarts.length > 1 && (
|
|
348
359
|
<ChCartsTotal>
|
|
349
|
-
{totalCartsFee && configs?.multi_business_checkout_show_combined_delivery_fee?.value === '1' && (
|
|
360
|
+
{!!totalCartsFee && configs?.multi_business_checkout_show_combined_delivery_fee?.value === '1' && (
|
|
350
361
|
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
351
362
|
<OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>
|
|
352
363
|
{t('TOTAL_DELIVERY_FEE', 'Total delivery fee')}
|
|
353
364
|
</OText>
|
|
354
|
-
<OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>
|
|
365
|
+
<OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>
|
|
366
|
+
{parsePrice(totalCartsFee)}
|
|
367
|
+
</OText>
|
|
355
368
|
</View>
|
|
356
369
|
)}
|
|
357
370
|
{openCarts.reduce((sum: any, cart: any) => sum + cart?.driver_tip, 0) > 0 &&
|
|
@@ -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
|
|
|
@@ -41,10 +44,11 @@ const PageBannerUI = (props: any) => {
|
|
|
41
44
|
})
|
|
42
45
|
|
|
43
46
|
const onRedirect = (route: string, params?: any) => {
|
|
44
|
-
navigation.
|
|
47
|
+
navigation.push(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}>
|
|
@@ -212,7 +212,7 @@ const PromotionsUI = (props: PromotionParams) => {
|
|
|
212
212
|
</OText>
|
|
213
213
|
<ScrollView
|
|
214
214
|
showsVerticalScrollIndicator={false}
|
|
215
|
-
style={{ height: '
|
|
215
|
+
style={{ height: '68%' }}
|
|
216
216
|
>
|
|
217
217
|
{offerSelected?.businesses?.map((business: any) => {
|
|
218
218
|
return (
|