ordering-ui-react-native 0.15.3 → 0.15.6
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/BusinessBasicInformation/index.tsx +12 -8
- package/themes/original/src/components/BusinessProductsListing/index.tsx +5 -2
- package/themes/original/src/components/Checkout/index.tsx +16 -7
- 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 +1 -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.6",
|
|
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
|
+
}
|
|
@@ -29,7 +29,7 @@ const types = ['food', 'laundry', 'alcohol', 'groceries'];
|
|
|
29
29
|
export const BusinessBasicInformation = (
|
|
30
30
|
props: BusinessBasicInformationParams,
|
|
31
31
|
) => {
|
|
32
|
-
const { navigation, businessState, isBusinessInfoShow, logo, header } = props;
|
|
32
|
+
const { navigation, businessState, isBusinessInfoShow, logo, header, isPreOrder } = props;
|
|
33
33
|
const { business, loading } = businessState;
|
|
34
34
|
|
|
35
35
|
const theme = useTheme();
|
|
@@ -181,12 +181,16 @@ export const BusinessBasicInformation = (
|
|
|
181
181
|
<WrapReviews>
|
|
182
182
|
{!isBusinessInfoShow && (
|
|
183
183
|
<>
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
184
|
+
{ isPreOrder && (
|
|
185
|
+
<>
|
|
186
|
+
<TouchableOpacity onPress={() => navigation.navigate('BusinessPreorder', { business: businessState?.business, handleBusinessClick: () => navigation?.goBack() })}>
|
|
187
|
+
<OText color={theme.colors.textSecondary} style={{ textDecorationLine: 'underline' }}>
|
|
188
|
+
{t('PRE_ORDER', 'Preorder')}
|
|
189
|
+
</OText>
|
|
190
|
+
</TouchableOpacity>
|
|
191
|
+
<OText size={12} color={theme.colors.textSecondary}>{' \u2022 '}</OText>
|
|
192
|
+
</>
|
|
193
|
+
)}
|
|
190
194
|
<TouchableOpacity onPress={() => setOpenBusinessReviews(true)}>
|
|
191
195
|
<OText color={theme.colors.textSecondary} style={{ textDecorationLine: 'underline' }}>
|
|
192
196
|
{t('REVIEWS', 'Reviews')}
|
|
@@ -262,4 +266,4 @@ const styles = StyleSheet.create({
|
|
|
262
266
|
zIndex: 100,
|
|
263
267
|
left: 40
|
|
264
268
|
},
|
|
265
|
-
});
|
|
269
|
+
});
|
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
useSession,
|
|
9
9
|
useUtils,
|
|
10
10
|
ToastType,
|
|
11
|
-
useToast
|
|
11
|
+
useToast,
|
|
12
|
+
useConfig
|
|
12
13
|
} from 'ordering-components/native'
|
|
13
14
|
import { OButton, OIcon, OModal, OText } from '../shared'
|
|
14
15
|
import { BusinessBasicInformation } from '../BusinessBasicInformation'
|
|
@@ -52,7 +53,8 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
52
53
|
const [orderState] = useOrder()
|
|
53
54
|
const [{ parsePrice }] = useUtils()
|
|
54
55
|
const [, { showToast }] = useToast()
|
|
55
|
-
|
|
56
|
+
const [{ configs }] = useConfig()
|
|
57
|
+
const isPreOrder = configs?.preorder_status_enabled?.value === '1'
|
|
56
58
|
const styles = StyleSheet.create({
|
|
57
59
|
mainContainer: {
|
|
58
60
|
flex: 1,
|
|
@@ -231,6 +233,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
231
233
|
openBusinessInformation={openBusinessInformation}
|
|
232
234
|
header={header}
|
|
233
235
|
logo={logo}
|
|
236
|
+
isPreOrder={isPreOrder}
|
|
234
237
|
/>
|
|
235
238
|
<View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100 }} />
|
|
236
239
|
{!loading && business?.id && (
|
|
@@ -134,6 +134,7 @@ const CheckoutUI = (props: any) => {
|
|
|
134
134
|
|
|
135
135
|
|
|
136
136
|
const isWalletEnabled = configs?.wallet_enabled?.value === '1' && (configs?.wallet_cash_enabled?.value === '1' || configs?.wallet_credit_point_enabled?.value === '1')
|
|
137
|
+
const isPreOrder = configs?.preorder_status_enabled?.value === '1'
|
|
137
138
|
|
|
138
139
|
const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
|
|
139
140
|
? JSON.parse(configs?.driver_tip_options?.value) || []
|
|
@@ -149,6 +150,12 @@ const CheckoutUI = (props: any) => {
|
|
|
149
150
|
}
|
|
150
151
|
})
|
|
151
152
|
|
|
153
|
+
const handleMomentClick = () => {
|
|
154
|
+
if (isPreOrder) {
|
|
155
|
+
navigation.navigate('MomentOption')
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
152
159
|
const handlePlaceOrder = () => {
|
|
153
160
|
if (!userErrors.length) {
|
|
154
161
|
handlerClickPlaceOrder && handlerClickPlaceOrder()
|
|
@@ -260,19 +267,21 @@ const CheckoutUI = (props: any) => {
|
|
|
260
267
|
/>
|
|
261
268
|
</CHMomentWrapper>
|
|
262
269
|
<CHMomentWrapper
|
|
263
|
-
|
|
264
|
-
|
|
270
|
+
onPress={() => handleMomentClick()}
|
|
271
|
+
disabled={loading}
|
|
265
272
|
>
|
|
266
273
|
<OText size={12} numberOfLines={1} ellipsizeMode='tail' color={theme.colors.textSecondary}>
|
|
267
274
|
{options?.moment
|
|
268
275
|
? parseDate(options?.moment, { outputFormat: configs?.dates_moment_format?.value })
|
|
269
276
|
: t('ASAP_ABBREVIATION', 'ASAP')}
|
|
270
277
|
</OText>
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
278
|
+
{ isPreOrder && (
|
|
279
|
+
<OIcon
|
|
280
|
+
src={theme.images.general.arrow_down}
|
|
281
|
+
width={10}
|
|
282
|
+
style={{ marginStart: 8 }}
|
|
283
|
+
/>
|
|
284
|
+
)}
|
|
276
285
|
</CHMomentWrapper>
|
|
277
286
|
</ChHeader>
|
|
278
287
|
<View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100, marginTop: 18, marginHorizontal: -40 }} />
|
|
@@ -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
|
}
|