ordering-ui-react-native 0.15.2 → 0.15.5
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 +3 -1
- package/themes/original/index.tsx +2 -0
- package/themes/original/src/components/AnalyticsSegment/index.tsx +127 -0
- package/themes/original/src/components/BusinessReviews/index.tsx +4 -3
- package/themes/original/src/components/HighestRatedBusinesses/index.tsx +9 -2
- package/themes/original/src/components/OrderProgress/index.tsx +2 -3
- package/themes/original/src/components/ProductForm/index.tsx +123 -93
- package/themes/original/src/components/ProductForm/styles.tsx +3 -1
- package/themes/original/src/components/ProductOptionSubOption/index.tsx +6 -1
- package/themes/original/src/types/index.tsx +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ordering-ui-react-native",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.5",
|
|
4
4
|
"description": "Reusable components made in react native",
|
|
5
5
|
"main": "src/index.tsx",
|
|
6
6
|
"author": "ordering.inc",
|
|
@@ -48,6 +48,8 @@
|
|
|
48
48
|
"@react-navigation/material-bottom-tabs": "^5.3.14",
|
|
49
49
|
"@react-navigation/native": "^5.7.6",
|
|
50
50
|
"@react-navigation/stack": "^5.9.3",
|
|
51
|
+
"@segment/analytics-react-native": "^2.1.11",
|
|
52
|
+
"@segment/sovran-react-native": "^0.2.6",
|
|
51
53
|
"@sentry/react-native": "^2.6.0",
|
|
52
54
|
"@stripe/stripe-react-native": "^0.2.0",
|
|
53
55
|
"@types/react-native-loading-spinner-overlay": "^0.5.2",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AddressForm } from './src/components/AddressForm';
|
|
2
2
|
import { AddressDetails } from './src/components/AddressDetails';
|
|
3
|
+
import { AnalyticsSegment } from './src/components/AnalyticsSegment';
|
|
3
4
|
import { Home } from './src/components/Home';
|
|
4
5
|
import { LoginForm } from './src/components/LoginForm';
|
|
5
6
|
import { SignupForm } from './src/components/SignupForm';
|
|
@@ -67,6 +68,7 @@ import {
|
|
|
67
68
|
export {
|
|
68
69
|
AddressForm,
|
|
69
70
|
AddressDetails,
|
|
71
|
+
AnalyticsSegment,
|
|
70
72
|
Home as HomeView,
|
|
71
73
|
SignupForm,
|
|
72
74
|
LoginForm,
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { createClient, AnalyticsProvider } from '@segment/analytics-react-native';
|
|
3
|
+
import { useEvent, useConfig } from 'ordering-components/native';
|
|
4
|
+
|
|
5
|
+
export const AnalyticsSegment = (props: any) => {
|
|
6
|
+
const { children } = props
|
|
7
|
+
|
|
8
|
+
const [events] = useEvent()
|
|
9
|
+
const [configState] = useConfig()
|
|
10
|
+
const [segmentClient, setSegmentClient] = useState<any>({})
|
|
11
|
+
|
|
12
|
+
const handleClickProduct = (product: any) => {
|
|
13
|
+
segmentClient.track('Product Clicked', {
|
|
14
|
+
id: product.id,
|
|
15
|
+
name: product.name,
|
|
16
|
+
category: product.category_id,
|
|
17
|
+
price: product.price
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const handleProductAdded = (product: any) => {
|
|
22
|
+
segmentClient.track('Product Added', {
|
|
23
|
+
id: product.id,
|
|
24
|
+
name: product.name,
|
|
25
|
+
category: product.category_id,
|
|
26
|
+
price: product.price,
|
|
27
|
+
quantity: product.quantity
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const handleProductRemoved = (product: any) => {
|
|
32
|
+
segmentClient.track('Product Removed', {
|
|
33
|
+
id: product.id,
|
|
34
|
+
name: product.name,
|
|
35
|
+
category: product.category_id,
|
|
36
|
+
price: product.price,
|
|
37
|
+
quantity: product.quantity
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const handleOrderPlaced = (order: any) => {
|
|
42
|
+
segmentClient.track('Order Placed', {
|
|
43
|
+
id: order.id,
|
|
44
|
+
affiliation: order.business?.name,
|
|
45
|
+
revenue: order.total,
|
|
46
|
+
tax: order.tax_total,
|
|
47
|
+
shipping: order.delivery_zone_price
|
|
48
|
+
})
|
|
49
|
+
segmentClient.track('Payment Info Entered', {
|
|
50
|
+
order: order.id,
|
|
51
|
+
business: order.business?.name,
|
|
52
|
+
business_id: order.business_id,
|
|
53
|
+
total: order.total,
|
|
54
|
+
tax: order.tax_total,
|
|
55
|
+
delivery: order.delivery_zone_price,
|
|
56
|
+
paymethod: order.paymethod
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const handleUpdateOrder = (order: any) => {
|
|
61
|
+
segmentClient.track('Order Updated', {
|
|
62
|
+
id: order.id,
|
|
63
|
+
affiliation: order.business?.name,
|
|
64
|
+
revenue: order.total,
|
|
65
|
+
tax: order.tax_total,
|
|
66
|
+
shipping: order.delivery_zone_price
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const handleAddOrder = (order: any) => {
|
|
71
|
+
segmentClient.track('Order Added', {
|
|
72
|
+
id: order.id,
|
|
73
|
+
affiliation: order.business?.name,
|
|
74
|
+
revenue: order.total,
|
|
75
|
+
tax: order.tax_total,
|
|
76
|
+
shipping: order.delivery_zone_price
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const handleLogin = (data: any) => {
|
|
81
|
+
segmentClient.identify(data.id, {
|
|
82
|
+
email: data.email,
|
|
83
|
+
name: data.name
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (segmentClient?.config?.writeKey) {
|
|
89
|
+
events.on('product_clicked', handleClickProduct)
|
|
90
|
+
events.on('userLogin', handleLogin)
|
|
91
|
+
events.on('product_added', handleProductAdded)
|
|
92
|
+
events.on('order_placed', handleOrderPlaced)
|
|
93
|
+
events.on('order_updated', handleUpdateOrder)
|
|
94
|
+
events.on('order_added', handleAddOrder)
|
|
95
|
+
events.on('cart_product_removed', handleProductRemoved)
|
|
96
|
+
}
|
|
97
|
+
return () => {
|
|
98
|
+
if (segmentClient?.config?.writeKey) {
|
|
99
|
+
events.off('product_clicked', handleClickProduct)
|
|
100
|
+
events.off('userLogin', handleLogin)
|
|
101
|
+
events.off('product_added', handleProductAdded)
|
|
102
|
+
events.off('order_placed', handleOrderPlaced)
|
|
103
|
+
events.off('order_updated', handleUpdateOrder)
|
|
104
|
+
events.off('order_added', handleAddOrder)
|
|
105
|
+
events.off('cart_product_removed', handleProductRemoved)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}, [segmentClient])
|
|
109
|
+
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
if (configState?.configs?.segment_track_id?.value) {
|
|
112
|
+
const _segmentClient: any = createClient({
|
|
113
|
+
writeKey: configState?.configs?.segment_track_id?.value
|
|
114
|
+
});
|
|
115
|
+
setSegmentClient(_segmentClient)
|
|
116
|
+
}
|
|
117
|
+
}, [configState])
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<>
|
|
121
|
+
<AnalyticsProvider client={segmentClient}>
|
|
122
|
+
{children}
|
|
123
|
+
</AnalyticsProvider>
|
|
124
|
+
</>
|
|
125
|
+
|
|
126
|
+
)
|
|
127
|
+
}
|
|
@@ -237,9 +237,10 @@ const BusinessReviewsUI = (props: BusinessReviewsParams) => {
|
|
|
237
237
|
))}
|
|
238
238
|
</>
|
|
239
239
|
)}
|
|
240
|
-
{
|
|
241
|
-
|
|
242
|
-
|
|
240
|
+
{reviewsList?.reviews
|
|
241
|
+
.filter((review: any) => searchReview !== '' ? review.comment?.toLowerCase()?.includes(searchReview?.toLowerCase()) : true).length === 0 && (
|
|
242
|
+
<OText>{t('REVIEWS_NOT_FOUND', 'Reviews Not Found')}</OText>
|
|
243
|
+
)}
|
|
243
244
|
</BusinessReviewContent>
|
|
244
245
|
</BusinessReviewsContainer>
|
|
245
246
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
BusinessList as BusinessesListingController,
|
|
4
4
|
useLanguage,
|
|
@@ -18,7 +18,9 @@ const HighestRatedBusinessesUI = (props: HighestRatedBusinessesParams) => {
|
|
|
18
18
|
const {
|
|
19
19
|
businessesList,
|
|
20
20
|
onBusinessClick,
|
|
21
|
-
navigation
|
|
21
|
+
navigation,
|
|
22
|
+
isLoading,
|
|
23
|
+
getBusinesses
|
|
22
24
|
} = props;
|
|
23
25
|
|
|
24
26
|
const [, t] = useLanguage()
|
|
@@ -26,6 +28,11 @@ const HighestRatedBusinessesUI = (props: HighestRatedBusinessesParams) => {
|
|
|
26
28
|
|
|
27
29
|
const windowWidth = Dimensions.get('window').width;
|
|
28
30
|
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (businessesList?.loading || !isLoading) return
|
|
33
|
+
getBusinesses(true)
|
|
34
|
+
}, [isLoading])
|
|
35
|
+
|
|
29
36
|
return (
|
|
30
37
|
<>
|
|
31
38
|
<ListWrapper>
|
|
@@ -9,7 +9,7 @@ import IconAntDesign from 'react-native-vector-icons/AntDesign'
|
|
|
9
9
|
import moment from 'moment';
|
|
10
10
|
import { OText } from '../shared'
|
|
11
11
|
import { NotFoundSource } from '../NotFoundSource'
|
|
12
|
-
import { View, StyleSheet, TouchableOpacity } from 'react-native'
|
|
12
|
+
import { View, StyleSheet, TouchableOpacity, Platform } from 'react-native'
|
|
13
13
|
import { Placeholder, Fade, PlaceholderLine } from "rn-placeholder";
|
|
14
14
|
import FastImage from 'react-native-fast-image'
|
|
15
15
|
import {
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
ProgressTextWrapper,
|
|
20
20
|
OrderInfoWrapper
|
|
21
21
|
} from './styles'
|
|
22
|
-
|
|
23
22
|
const OrderProgressUI = (props: any) => {
|
|
24
23
|
const {
|
|
25
24
|
orderList,
|
|
@@ -139,7 +138,7 @@ const OrderProgressUI = (props: any) => {
|
|
|
139
138
|
return (
|
|
140
139
|
<>
|
|
141
140
|
{orderList?.loading && (
|
|
142
|
-
<Placeholder Animation={Fade} height={158}>
|
|
141
|
+
<Placeholder Animation={Fade} height={Platform.OS === 'ios' ? 147.5 : 158}>
|
|
143
142
|
<PlaceholderLine height={60} style={{ borderRadius: 8, marginBottom: 10 }} />
|
|
144
143
|
<PlaceholderLine height={20} style={{ marginBottom: 10 }} />
|
|
145
144
|
<PlaceholderLine height={40} style={{ borderRadius: 8, marginBottom: 10 }} />
|
|
@@ -37,7 +37,8 @@ import {
|
|
|
37
37
|
ExtraOptionWrap,
|
|
38
38
|
WeightUnitSwitch,
|
|
39
39
|
WeightUnitItem,
|
|
40
|
-
TopActions
|
|
40
|
+
TopActions,
|
|
41
|
+
ProductSummary
|
|
41
42
|
} from './styles';
|
|
42
43
|
import { OButton, OIcon, OInput, OText } from '../shared';
|
|
43
44
|
import { ScrollView } from 'react-native-gesture-handler';
|
|
@@ -170,8 +171,11 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
170
171
|
pieces: true
|
|
171
172
|
})
|
|
172
173
|
const [pricePerWeightUnit, setPricePerWeightUnit] = useState<any>(null)
|
|
173
|
-
|
|
174
|
+
const scrollViewRef = useRef<any>(null);
|
|
174
175
|
const swiperRef: any = useRef(null)
|
|
176
|
+
const [optionLayout, setOptionLayout] = useState<any>({})
|
|
177
|
+
const [headerRefHeight, setHeaderRefHeight] = useState(0)
|
|
178
|
+
const [summaryRefHeight, setSummaryRefHeight] = useState(0)
|
|
175
179
|
|
|
176
180
|
const isError = (id: number) => {
|
|
177
181
|
let bgColor = theme.colors.white;
|
|
@@ -253,6 +257,28 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
253
257
|
handleChangeProductCartQuantity(quantity)
|
|
254
258
|
}
|
|
255
259
|
|
|
260
|
+
const scrollDown = (id: any) => {
|
|
261
|
+
const isErrors = Object.values(errors).length > 0
|
|
262
|
+
if (!isErrors) {
|
|
263
|
+
return
|
|
264
|
+
}
|
|
265
|
+
const targetOptionId = Object.getOwnPropertyNames(errors).filter(item => !item.includes(id))[0]
|
|
266
|
+
const targetY = optionLayout[targetOptionId]?.y
|
|
267
|
+
if (targetY) {
|
|
268
|
+
scrollViewRef.current.scrollTo({
|
|
269
|
+
y: targetY + headerRefHeight + summaryRefHeight,
|
|
270
|
+
animated: true
|
|
271
|
+
})
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const handleOnLayout = (event: any, optionId: any) => {
|
|
276
|
+
const _optionLayout = { ...optionLayout }
|
|
277
|
+
const optionKey = 'id:' + optionId
|
|
278
|
+
_optionLayout[optionKey] = { y: event.nativeEvent.layout?.y }
|
|
279
|
+
setOptionLayout(_optionLayout)
|
|
280
|
+
}
|
|
281
|
+
|
|
256
282
|
useEffect(() => {
|
|
257
283
|
const imageList: any = []
|
|
258
284
|
const videoList: any = []
|
|
@@ -343,10 +369,10 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
343
369
|
<OIcon src={theme.images.general.arrow_left} width={15} />
|
|
344
370
|
</TopActions>
|
|
345
371
|
</TopHeader>
|
|
346
|
-
<ScrollView>
|
|
372
|
+
<ScrollView ref={scrollViewRef}>
|
|
347
373
|
{!error && (
|
|
348
374
|
<View style={{ paddingBottom: 80 }}>
|
|
349
|
-
<WrapHeader>
|
|
375
|
+
<WrapHeader onLayout={(event: any) => setHeaderRefHeight(event.nativeEvent.layout?.height)}>
|
|
350
376
|
{loading && !product ? (
|
|
351
377
|
<View style={styles.productHeaderSkeleton}>
|
|
352
378
|
<Placeholder Animation={Fade}>
|
|
@@ -470,96 +496,98 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
470
496
|
)}
|
|
471
497
|
</WrapHeader>
|
|
472
498
|
<WrapContent>
|
|
473
|
-
<
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
<
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
<
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
{!!product?.calories && (
|
|
496
|
-
<OText size={16} style={{ color: '#808080' }}>{product?.calories} cal
|
|
499
|
+
<ProductSummary onLayout={(event: any) => setSummaryRefHeight(event.nativeEvent.layout?.height)}>
|
|
500
|
+
<ProductTitle>
|
|
501
|
+
{loading && !product ? (
|
|
502
|
+
<Placeholder Animation={Fade}>
|
|
503
|
+
<View
|
|
504
|
+
style={{
|
|
505
|
+
flexDirection: 'row',
|
|
506
|
+
justifyContent: 'space-between',
|
|
507
|
+
}}>
|
|
508
|
+
<PlaceholderLine width={40} height={20} />
|
|
509
|
+
<PlaceholderLine width={30} height={20} />
|
|
510
|
+
</View>
|
|
511
|
+
</Placeholder>
|
|
512
|
+
) : (
|
|
513
|
+
<>
|
|
514
|
+
<View style={{ flexDirection: 'row' }}>
|
|
515
|
+
<OText
|
|
516
|
+
size={20}
|
|
517
|
+
lineHeight={30}
|
|
518
|
+
weight={'600'}
|
|
519
|
+
style={{ flex: 1, marginBottom: 10 }}>
|
|
520
|
+
{product?.name || productCart.name}
|
|
497
521
|
</OText>
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
<OText size={14} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={'#909BA9'} mBottom={7}>
|
|
502
|
-
{
|
|
503
|
-
((product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (productCart?.sku && productCart?.sku !== '-1' && productCart?.sku !== '1'))
|
|
504
|
-
&& <>{t('SKU', 'Sku')}{' '}{product?.sku || productCart?.sku}</>
|
|
505
|
-
}
|
|
506
|
-
{product?.sku && product?.sku !== '-1' && product?.sku !== '1' && product?.estimated_person && (
|
|
507
|
-
<> · </>
|
|
508
|
-
)}
|
|
509
|
-
{product?.estimated_person
|
|
510
|
-
&& <>{product?.estimated_person}{' '}{t('ESTIMATED_PERSONS', 'persons')}</>
|
|
511
|
-
}
|
|
512
|
-
</OText>
|
|
513
|
-
)}
|
|
514
|
-
{isHaveWeight ? (
|
|
515
|
-
<OText size={16} lineHeight={24} color={theme.colors.primary}>{parsePrice(pricePerWeightUnit)} / {product?.weight_unit}</OText>
|
|
516
|
-
) : (
|
|
517
|
-
<View style={{ flexDirection: 'row', marginBottom: 10 }}>
|
|
518
|
-
<OText size={16} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={theme.colors.primary}>{productCart.price ? parsePrice(productCart.price) : ''}</OText>
|
|
519
|
-
{product?.offer_price !== null && product?.in_offer && (
|
|
520
|
-
<OText style={{
|
|
521
|
-
fontSize: 14,
|
|
522
|
-
color: '#808080',
|
|
523
|
-
textDecorationLine: 'line-through',
|
|
524
|
-
marginLeft: 7,
|
|
525
|
-
marginRight: 7
|
|
526
|
-
}}>{product?.offer_price ? parsePrice(product?.offer_price) : ''}</OText>
|
|
522
|
+
{!!product?.calories && (
|
|
523
|
+
<OText size={16} style={{ color: '#808080' }}>{product?.calories} cal
|
|
524
|
+
</OText>
|
|
527
525
|
)}
|
|
528
526
|
</View>
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
527
|
+
{((!!product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (!!product?.estimated_person)) && (
|
|
528
|
+
<OText size={14} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={'#909BA9'} mBottom={7}>
|
|
529
|
+
{
|
|
530
|
+
((product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (productCart?.sku && productCart?.sku !== '-1' && productCart?.sku !== '1'))
|
|
531
|
+
&& <>{t('SKU', 'Sku')}{' '}{product?.sku || productCart?.sku}</>
|
|
532
|
+
}
|
|
533
|
+
{product?.sku && product?.sku !== '-1' && product?.sku !== '1' && product?.estimated_person && (
|
|
534
|
+
<> · </>
|
|
535
|
+
)}
|
|
536
|
+
{product?.estimated_person
|
|
537
|
+
&& <>{product?.estimated_person}{' '}{t('ESTIMATED_PERSONS', 'persons')}</>
|
|
538
|
+
}
|
|
539
|
+
</OText>
|
|
540
|
+
)}
|
|
541
|
+
{isHaveWeight ? (
|
|
542
|
+
<OText size={16} lineHeight={24} color={theme.colors.primary}>{parsePrice(pricePerWeightUnit)} / {product?.weight_unit}</OText>
|
|
543
|
+
) : (
|
|
544
|
+
<View style={{ flexDirection: 'row', marginBottom: 10 }}>
|
|
545
|
+
<OText size={16} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={theme.colors.primary}>{productCart.price ? parsePrice(productCart.price) : ''}</OText>
|
|
546
|
+
{product?.offer_price !== null && product?.in_offer && (
|
|
547
|
+
<OText style={{
|
|
548
|
+
fontSize: 14,
|
|
549
|
+
color: '#808080',
|
|
550
|
+
textDecorationLine: 'line-through',
|
|
551
|
+
marginLeft: 7,
|
|
552
|
+
marginRight: 7
|
|
553
|
+
}}>{product?.offer_price ? parsePrice(product?.offer_price) : ''}</OText>
|
|
554
|
+
)}
|
|
555
|
+
</View>
|
|
556
|
+
)}
|
|
557
|
+
</>
|
|
558
|
+
)}
|
|
559
|
+
</ProductTitle>
|
|
560
|
+
<ProductDescription>
|
|
561
|
+
<OText color={theme.colors.textSecondary} size={12} lineHeight={18}>
|
|
562
|
+
{product?.description || productCart?.description}
|
|
563
|
+
</OText>
|
|
564
|
+
</ProductDescription>
|
|
565
|
+
<ScrollView
|
|
566
|
+
horizontal
|
|
567
|
+
showsHorizontalScrollIndicator={false}
|
|
568
|
+
contentContainerStyle={{ paddingBottom: 30 }}
|
|
569
|
+
>
|
|
570
|
+
{product?.tags?.map((tag: any) => (
|
|
571
|
+
<View
|
|
572
|
+
key={tag.id}
|
|
573
|
+
style={styles.productTagWrapper}
|
|
574
|
+
>
|
|
575
|
+
{!!tag?.image ? (
|
|
576
|
+
<OIcon
|
|
577
|
+
url={optimizeImage(tag?.image, 'h_40,c_limit')}
|
|
578
|
+
style={styles.productTagImageStyle}
|
|
579
|
+
/>
|
|
580
|
+
) : (
|
|
581
|
+
<OIcon
|
|
582
|
+
src={theme.images?.dummies?.product}
|
|
583
|
+
style={styles.productTagImageStyle}
|
|
584
|
+
/>
|
|
585
|
+
)}
|
|
586
|
+
<OText color={theme.colors.textSecondary} size={12} style={styles.productTagNameStyle}>{tag.name}</OText>
|
|
587
|
+
</View>
|
|
588
|
+
))}
|
|
589
|
+
</ScrollView>
|
|
590
|
+
</ProductSummary>
|
|
563
591
|
{loading && !product ? (
|
|
564
592
|
<>
|
|
565
593
|
{[...Array(2)].map((item, i) => (
|
|
@@ -658,7 +686,7 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
658
686
|
return (
|
|
659
687
|
<React.Fragment key={`popt_${option.id}`}>
|
|
660
688
|
{showOption(option) && (
|
|
661
|
-
<View style={styles.optionContainer}>
|
|
689
|
+
<View style={styles.optionContainer} onLayout={(event: any) => handleOnLayout(event, option?.id)}>
|
|
662
690
|
<ProductOption
|
|
663
691
|
option={option}
|
|
664
692
|
currentState={currentState}
|
|
@@ -695,6 +723,8 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
695
723
|
isSoldOut ||
|
|
696
724
|
maxProductQuantity <= 0
|
|
697
725
|
}
|
|
726
|
+
scrollDown={scrollDown}
|
|
727
|
+
error={errors[`id:${option.id}`]}
|
|
698
728
|
/>
|
|
699
729
|
);
|
|
700
730
|
},
|
|
@@ -855,7 +885,7 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
855
885
|
{qtyBy?.pieces && (
|
|
856
886
|
<TextInput
|
|
857
887
|
keyboardType='numeric'
|
|
858
|
-
value={`${productCart?.quantity > 0 ? productCart?.quantity: ''}`}
|
|
888
|
+
value={`${productCart?.quantity > 0 ? productCart?.quantity : ''}`}
|
|
859
889
|
onChangeText={(val: any) => onChangeProductCartQuantity(parseInt(val))}
|
|
860
890
|
editable={!orderState.loading}
|
|
861
891
|
style={{
|
|
@@ -71,7 +71,7 @@ export const ProductActions = styled.View`
|
|
|
71
71
|
position: absolute;
|
|
72
72
|
bottom: 0px;
|
|
73
73
|
min-height: 70px;
|
|
74
|
-
padding-top: ${(props
|
|
74
|
+
padding-top: ${(props: any) => props.ios ? '20px' : '0'};
|
|
75
75
|
padding-horizontal: 40px;
|
|
76
76
|
width: 100%;
|
|
77
77
|
flex-direction: row;
|
|
@@ -97,3 +97,5 @@ export const WeightUnitItem = styled.View`
|
|
|
97
97
|
background-color: ${(props: any) => props.theme.colors.primary}20;
|
|
98
98
|
`}
|
|
99
99
|
`
|
|
100
|
+
export const ProductSummary = styled.View`
|
|
101
|
+
`
|
|
@@ -27,7 +27,9 @@ export const ProductOptionSubOptionUI = (props: any) => {
|
|
|
27
27
|
suboption,
|
|
28
28
|
toggleSelect,
|
|
29
29
|
changePosition,
|
|
30
|
-
disabled
|
|
30
|
+
disabled,
|
|
31
|
+
error,
|
|
32
|
+
scrollDown
|
|
31
33
|
} = props
|
|
32
34
|
|
|
33
35
|
const theme = useTheme();
|
|
@@ -38,6 +40,9 @@ export const ProductOptionSubOptionUI = (props: any) => {
|
|
|
38
40
|
|
|
39
41
|
const handleSuboptionClick = () => {
|
|
40
42
|
toggleSelect()
|
|
43
|
+
if (error) {
|
|
44
|
+
scrollDown(option?.id)
|
|
45
|
+
}
|
|
41
46
|
if (balance === option?.max && option?.suboptions?.length > balance && !(option?.min === 1 && option?.max === 1)) {
|
|
42
47
|
setShowMessage(true)
|
|
43
48
|
}
|
|
@@ -143,6 +143,8 @@ export interface HighestRatedBusinessesParams {
|
|
|
143
143
|
businessesList: { businesses: Array<any>, loading: boolean, error: null | string };
|
|
144
144
|
onBusinessClick?: void;
|
|
145
145
|
navigation? :any;
|
|
146
|
+
isLoading?: boolean;
|
|
147
|
+
getBusinesses: (newFetch : boolean) => void
|
|
146
148
|
}
|
|
147
149
|
export interface BusinessTypeFilterParams {
|
|
148
150
|
businessTypes?: Array<any>;
|