ordering-ui-react-native 0.14.40 → 0.14.41-release
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/components/BusinessItemAccordion/index.tsx +2 -2
- package/src/components/Cart/index.tsx +135 -42
- package/src/components/Cart/styles.tsx +7 -0
- package/src/components/Checkout/index.tsx +28 -166
- package/src/components/OrderDetails/index.tsx +102 -34
- package/src/components/OrderDetails/styles.tsx +7 -0
- package/src/components/OrderSummary/index.tsx +140 -37
- package/src/components/OrderSummary/styles.tsx +10 -2
- package/src/components/PaymentOptions/index.tsx +3 -1
- package/src/components/PaymentOptionsWebView/index.tsx +150 -0
- package/src/components/ProductForm/index.tsx +6 -6
- package/src/components/SingleProductCard/index.tsx +1 -1
- package/src/components/StripeElementsForm/index.tsx +28 -13
- package/src/components/TaxInformation/index.tsx +58 -26
- package/src/components/VerifyPhone/styles.tsx +1 -2
- package/src/components/shared/OIcon.tsx +4 -1
- package/src/index.tsx +2 -0
- package/src/navigators/HomeNavigator.tsx +6 -0
- package/src/pages/ProductDetails.tsx +55 -0
- package/themes/doordash/src/components/LoginForm/index.tsx +1 -2
- package/themes/kiosk/src/components/Cart/index.tsx +14 -21
- package/themes/kiosk/src/components/CartItem/index.tsx +9 -7
- package/themes/kiosk/src/components/CustomerName/index.tsx +2 -1
- package/themes/kiosk/src/components/Intro/index.tsx +4 -4
- package/themes/kiosk/src/components/OptionCard/index.tsx +11 -6
- package/themes/kiosk/src/components/PaymentOptions/index.tsx +46 -44
- package/themes/original/src/components/BusinessItemAccordion/index.tsx +12 -9
- package/themes/original/src/components/BusinessItemAccordion/styles.tsx +3 -2
- package/themes/original/src/components/BusinessProductsListing/index.tsx +8 -4
- package/themes/original/src/components/BusinessesListing/index.tsx +100 -75
- package/themes/original/src/components/Cart/index.tsx +122 -24
- package/themes/original/src/components/Cart/styles.tsx +8 -1
- package/themes/original/src/components/Checkout/index.tsx +38 -3
- package/themes/original/src/components/Help/index.tsx +1 -1
- package/themes/original/src/components/MessageListing/index.tsx +4 -2
- package/themes/original/src/components/OrderDetails/index.tsx +114 -42
- package/themes/original/src/components/OrderDetails/styles.tsx +8 -1
- package/themes/original/src/components/OrderProgress/index.tsx +2 -1
- package/themes/original/src/components/OrderSummary/index.tsx +132 -23
- package/themes/original/src/components/OrderSummary/styles.tsx +7 -0
- package/themes/original/src/components/PaymentOptionWallet/index.tsx +6 -2
- package/themes/original/src/components/PaymentOptions/index.tsx +8 -2
- package/themes/original/src/components/ProductForm/index.tsx +58 -54
- package/themes/original/src/components/ProductOptionSubOption/index.tsx +3 -2
- package/themes/original/src/components/SingleProductCard/index.tsx +36 -19
- package/themes/original/src/components/SingleProductCard/styles.tsx +4 -0
- package/themes/original/src/components/StripeElementsForm/index.tsx +28 -13
- package/themes/original/src/components/TaxInformation/index.tsx +59 -27
- package/themes/original/src/components/UpsellingProducts/index.tsx +26 -18
- package/themes/original/src/types/index.tsx +2 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import React, { useRef, useState } from 'react'
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import Icon from 'react-native-vector-icons/Feather';
|
|
4
|
+
import WebView from 'react-native-webview';
|
|
5
|
+
import { ActivityIndicator } from 'react-native-paper';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
ToastType,
|
|
9
|
+
useToast,
|
|
10
|
+
useApi,
|
|
11
|
+
useLanguage,
|
|
12
|
+
useConfig
|
|
13
|
+
} from 'ordering-components/native';
|
|
14
|
+
|
|
15
|
+
import { OText } from '../shared';
|
|
16
|
+
|
|
17
|
+
interface PaymentOptionsWebViewParams {
|
|
18
|
+
onNavigationRedirect?: Function,
|
|
19
|
+
uri?: any,
|
|
20
|
+
user?: any,
|
|
21
|
+
token?: any,
|
|
22
|
+
cart?: any,
|
|
23
|
+
currency?: any,
|
|
24
|
+
webviewPaymethod?: any,
|
|
25
|
+
setShowGateway?: any,
|
|
26
|
+
setOpenOrderCreating?: any,
|
|
27
|
+
locationId?: any
|
|
28
|
+
}
|
|
29
|
+
export const PaymentOptionsWebView = (props: PaymentOptionsWebViewParams) => {
|
|
30
|
+
const {
|
|
31
|
+
onNavigationRedirect,
|
|
32
|
+
uri,
|
|
33
|
+
user,
|
|
34
|
+
token,
|
|
35
|
+
cart,
|
|
36
|
+
currency,
|
|
37
|
+
webviewPaymethod,
|
|
38
|
+
setShowGateway,
|
|
39
|
+
setOpenOrderCreating,
|
|
40
|
+
locationId
|
|
41
|
+
} = props
|
|
42
|
+
|
|
43
|
+
const webviewRef = useRef<any>(null)
|
|
44
|
+
const [, { showToast }] = useToast();
|
|
45
|
+
const [ordering] = useApi()
|
|
46
|
+
const [{ configs }] = useConfig();
|
|
47
|
+
const [, t] = useLanguage();
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
const [progClr, setProgClr] = useState('#424242');
|
|
51
|
+
const [prog, setProg] = useState(true);
|
|
52
|
+
|
|
53
|
+
const handleCloseWebview = () => {
|
|
54
|
+
setProg(true);
|
|
55
|
+
setShowGateway({ open: false, closedByUser: true })
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const onMessage = (e: any) => {
|
|
59
|
+
if (e?.nativeEvent?.data && e?.nativeEvent?.data !== 'undefined') {
|
|
60
|
+
let payment = JSON.parse(e.nativeEvent.data);
|
|
61
|
+
|
|
62
|
+
if (payment === 'api error') {
|
|
63
|
+
setShowGateway({ closedByUser: true, open: false })
|
|
64
|
+
setProg(true);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (payment) {
|
|
68
|
+
if (payment.error) {
|
|
69
|
+
showToast(ToastType.Error, payment.result)
|
|
70
|
+
setOpenOrderCreating && setOpenOrderCreating(false)
|
|
71
|
+
} else if (payment?.result?.order?.uuid) {
|
|
72
|
+
showToast(ToastType.Success, t('ORDER_PLACED_SUCCESSfULLY', 'The order was placed successfully'))
|
|
73
|
+
onNavigationRedirect && onNavigationRedirect('OrderDetails', { orderId: payment?.result?.order?.uuid, isFromCheckout: true})
|
|
74
|
+
}
|
|
75
|
+
setProg(true);
|
|
76
|
+
setShowGateway({ closedByUser: false, open: false })
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<View style={{ zIndex: 9999, height: '100%', width: '100%', position: 'absolute', backgroundColor: 'white' }}>
|
|
83
|
+
<Icon
|
|
84
|
+
name="x"
|
|
85
|
+
size={35}
|
|
86
|
+
style={{ backgroundColor: 'white', paddingTop: 30, paddingLeft: 10 }}
|
|
87
|
+
onPress={handleCloseWebview}
|
|
88
|
+
/>
|
|
89
|
+
<OText
|
|
90
|
+
style={{
|
|
91
|
+
textAlign: 'center',
|
|
92
|
+
fontSize: 16,
|
|
93
|
+
fontWeight: 'bold',
|
|
94
|
+
color: '#00457C',
|
|
95
|
+
marginBottom: 5,
|
|
96
|
+
marginTop: 10
|
|
97
|
+
}}>
|
|
98
|
+
{webviewPaymethod?.gateway === 'paypal' ? (t('PAYPAL_GATEWAY', 'PayPal GateWay')) : (t('SQUARE_PAYMENT', 'Square payment'))}
|
|
99
|
+
</OText>
|
|
100
|
+
<View style={{ padding: 20, opacity: prog ? 1 : 0, backgroundColor: 'white' }}>
|
|
101
|
+
<ActivityIndicator size={24} color={progClr} />
|
|
102
|
+
</View>
|
|
103
|
+
<WebView
|
|
104
|
+
source={{ uri: uri }}
|
|
105
|
+
onMessage={onMessage}
|
|
106
|
+
ref={webviewRef}
|
|
107
|
+
javaScriptEnabled={true}
|
|
108
|
+
javaScriptEnabledAndroid={true}
|
|
109
|
+
cacheEnabled={false}
|
|
110
|
+
cacheMode='LOAD_NO_CACHE'
|
|
111
|
+
style={{ flex: 1 }}
|
|
112
|
+
onShouldStartLoadWithRequest={() => true}
|
|
113
|
+
onLoadStart={() => {
|
|
114
|
+
setProg(true);
|
|
115
|
+
setProgClr('#424242');
|
|
116
|
+
}}
|
|
117
|
+
onLoadProgress={() => {
|
|
118
|
+
setProg(true);
|
|
119
|
+
setProgClr('#00457C');
|
|
120
|
+
}}
|
|
121
|
+
onLoad={() => {
|
|
122
|
+
setProg(true);
|
|
123
|
+
setProgClr('#00457C');
|
|
124
|
+
}}
|
|
125
|
+
onLoadEnd={(e) => {
|
|
126
|
+
const messageParams = locationId ? { locationId } : {}
|
|
127
|
+
const message = {
|
|
128
|
+
action: 'init',
|
|
129
|
+
data: {
|
|
130
|
+
urlPlace: `${ordering.root}/carts/${cart?.uuid}/place`,
|
|
131
|
+
urlConfirm: `${ordering.root}/carts/${cart?.uuid}/confirm`,
|
|
132
|
+
payData: {
|
|
133
|
+
paymethod_id: webviewPaymethod?.id,
|
|
134
|
+
amount: cart?.balance ?? cart?.total,
|
|
135
|
+
delivery_zone_id: cart?.delivery_zone_id,
|
|
136
|
+
user_id: user?.id,
|
|
137
|
+
user_name: user?.name
|
|
138
|
+
},
|
|
139
|
+
currency: configs?.stripe_currency?.value || currency,
|
|
140
|
+
userToken: token,
|
|
141
|
+
clientId: webviewPaymethod?.credentials?.client_id,
|
|
142
|
+
...messageParams
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
setProg(false);
|
|
146
|
+
webviewRef?.current?.postMessage?.(JSON.stringify(message))
|
|
147
|
+
}}
|
|
148
|
+
/>
|
|
149
|
+
</View>
|
|
150
|
+
)}
|
|
@@ -132,26 +132,26 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
132
132
|
<View style={{ flexDirection: 'column', width: '100%' }}>
|
|
133
133
|
<View style={{ flexDirection: 'row', marginTop: 15 }}>
|
|
134
134
|
<OText size={20} style={{ flex: I18nManager.isRTL ? 0 : 1, marginBottom: 10 }}>{product?.name || productCart.name}{' '}</OText>
|
|
135
|
-
{product?.calories && (
|
|
135
|
+
{!!product?.calories && (
|
|
136
136
|
<OText size={16} style={styles.caloriesStyle}>{product?.calories} cal</OText>
|
|
137
137
|
)}
|
|
138
138
|
</View>
|
|
139
139
|
<View style={{ flexDirection: 'row', marginBottom: 10 }}>
|
|
140
140
|
<OText size={16} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={theme.colors.primary}>{productCart.price ? parsePrice(productCart.price) : ''}</OText>
|
|
141
|
-
{product?.offer_price && (
|
|
141
|
+
{!!product?.offer_price !== null && product?.in_offer && (
|
|
142
142
|
<OText style={styles.regularPriceStyle}>{parsePrice(product?.offer_price)}</OText>
|
|
143
143
|
)}
|
|
144
144
|
</View>
|
|
145
|
-
{(product?.estimated_person || (product?.sku && product?.sku !== '-1' && product?.sku !== '1')) && (
|
|
145
|
+
{(!!product?.estimated_person || (!!product?.sku && product?.sku !== '-1' && product?.sku !== '1')) && (
|
|
146
146
|
<OText size={14} style={{ flex: I18nManager.isRTL ? 1 : 0, marginBottom: 10 }} color={'#909BA9'}>
|
|
147
147
|
{
|
|
148
148
|
((product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (productCart?.sku && productCart?.sku !== '-1' && productCart?.sku !== '1'))
|
|
149
149
|
&& <>{t('SKU', 'Sku')}{' '}{product?.sku || productCart?.sku}</>
|
|
150
150
|
}
|
|
151
|
-
{product?.sku && product?.sku !== '-1' && product?.sku !== '1' && product?.estimated_person && (
|
|
151
|
+
{!!product?.sku && product?.sku !== '-1' && product?.sku !== '1' && !!product?.estimated_person && (
|
|
152
152
|
<> · </>
|
|
153
153
|
)}
|
|
154
|
-
{product?.estimated_person
|
|
154
|
+
{!!product?.estimated_person
|
|
155
155
|
&& <>{product?.estimated_person}{' '}{t('ESTIMATED_PERSONS', 'persons')}</>
|
|
156
156
|
}
|
|
157
157
|
</OText>
|
|
@@ -335,7 +335,7 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
335
335
|
/>
|
|
336
336
|
) : (
|
|
337
337
|
<OButton
|
|
338
|
-
onClick={navigation.navigate('AddressList')}
|
|
338
|
+
onClick={() => navigation.navigate('AddressList')}
|
|
339
339
|
/>
|
|
340
340
|
)
|
|
341
341
|
)}
|
|
@@ -86,7 +86,7 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
|
|
|
86
86
|
<OText size={12} numberOfLines={2} ellipsizeMode='tail' style={styles.textStyle}>{product?.description}</OText>
|
|
87
87
|
<PricesContainer>
|
|
88
88
|
<OText color={theme.colors.primary}>{parsePrice(product?.price)}</OText>
|
|
89
|
-
{product?.offer_price && (
|
|
89
|
+
{!!product?.offer_price !== null && product?.in_offer && (
|
|
90
90
|
<OText style={styles.regularPriceStyle}>{parsePrice(product?.offer_price)}</OText>
|
|
91
91
|
)}
|
|
92
92
|
</PricesContainer>
|
|
@@ -33,19 +33,33 @@ const StripeElementsFormUI = (props: any) => {
|
|
|
33
33
|
const { confirmSetupIntent, loading: confirmSetupLoading } = useConfirmSetupIntent();
|
|
34
34
|
const [createPmLoading, setCreatePmLoading] = useState(false);
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
let billingDetails: any = {}
|
|
37
|
+
|
|
38
|
+
if (user?.name || user?.lastname) {
|
|
39
|
+
if (user?.name) {
|
|
40
|
+
billingDetails.name = user?.name
|
|
41
|
+
}
|
|
42
|
+
if (user?.lastname) {
|
|
43
|
+
billingDetails.name = `${billingDetails?.name} ${user?.lastname}`
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (user?.email) {
|
|
48
|
+
billingDetails.email = user?.email
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (user?.address) {
|
|
52
|
+
billingDetails.addressLine1 = user?.address
|
|
53
|
+
}
|
|
41
54
|
|
|
42
55
|
const createPayMethod = async () => {
|
|
56
|
+
const params: any = { type: 'Card' }
|
|
57
|
+
if (Object.keys(billingDetails).length > 0) {
|
|
58
|
+
params.billingDetails = billingDetails
|
|
59
|
+
}
|
|
43
60
|
try {
|
|
44
61
|
setCreatePmLoading(true)
|
|
45
|
-
const { paymentMethod } = await createPaymentMethod(
|
|
46
|
-
type: 'Card',
|
|
47
|
-
billingDetails,
|
|
48
|
-
});
|
|
62
|
+
const { paymentMethod } = await createPaymentMethod(params);
|
|
49
63
|
|
|
50
64
|
setCreatePmLoading(false)
|
|
51
65
|
handleSource && handleSource({
|
|
@@ -68,11 +82,12 @@ const StripeElementsFormUI = (props: any) => {
|
|
|
68
82
|
createPayMethod();
|
|
69
83
|
return
|
|
70
84
|
}
|
|
85
|
+
const params: any = { type: 'Card' }
|
|
86
|
+
if (Object.keys(billingDetails).length > 0) {
|
|
87
|
+
params.billingDetails = billingDetails
|
|
88
|
+
}
|
|
71
89
|
try {
|
|
72
|
-
const { setupIntent, error } = await confirmSetupIntent(requirements,
|
|
73
|
-
type: 'Card',
|
|
74
|
-
billingDetails,
|
|
75
|
-
});
|
|
90
|
+
const { setupIntent, error } = await confirmSetupIntent(requirements, params);
|
|
76
91
|
|
|
77
92
|
if (setupIntent?.status === 'Succeeded') {
|
|
78
93
|
stripeTokenHandler(setupIntent?.paymentMethodId, user, businessId);
|
|
@@ -1,51 +1,83 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { useLanguage
|
|
2
|
+
import { useLanguage } from 'ordering-components/native'
|
|
3
3
|
import { SingleProductCard } from '../SingleProductCard'
|
|
4
4
|
import { TaxInformationContainer, ProductContainer } from './styles'
|
|
5
5
|
import { OText } from '../shared'
|
|
6
6
|
|
|
7
7
|
interface taxInformationParams {
|
|
8
|
-
data: {
|
|
9
|
-
|
|
8
|
+
data: {
|
|
9
|
+
name: string,
|
|
10
|
+
description?: string,
|
|
11
|
+
rate: string | number,
|
|
12
|
+
type: number,
|
|
13
|
+
fixed?: number,
|
|
14
|
+
percentage?: number,
|
|
15
|
+
id: number,
|
|
16
|
+
discounts?: any
|
|
17
|
+
},
|
|
18
|
+
products: Array<any>,
|
|
19
|
+
type: string
|
|
10
20
|
}
|
|
11
21
|
|
|
12
22
|
export const TaxInformation = (props: taxInformationParams) => {
|
|
13
23
|
const {
|
|
14
24
|
data,
|
|
15
|
-
products
|
|
25
|
+
products,
|
|
26
|
+
type
|
|
16
27
|
} = props
|
|
17
28
|
|
|
18
29
|
const [, t] = useLanguage()
|
|
19
|
-
const [{ parsePrice }] = useUtils()
|
|
20
30
|
|
|
21
|
-
const isTax = typeof data?.rate === 'number'
|
|
22
|
-
const TaxFeeString = isTax ? 'tax' : 'fee'
|
|
23
31
|
const includedOnPriceString = data?.type === 1 ? `(${t('INCLUDED_ON_PRICE', 'Included on price')})` : `(${t('NOT_INCLUDED_ON_PRICE', 'Not included on price')})`
|
|
24
32
|
|
|
33
|
+
const getFilterValidation = (product: any) => {
|
|
34
|
+
return (
|
|
35
|
+
type === 'tax'
|
|
36
|
+
? (product.tax?.id ? product.tax?.id === data?.id : product.tax?.id === null && data?.id === null)
|
|
37
|
+
: type === 'fee'
|
|
38
|
+
? (product.fee?.id ? product.fee?.id === data?.id : (product.fee?.id === null && data?.id === null))
|
|
39
|
+
: Object.keys(data?.discounts ?? {}).map(code => code.includes(product?.code)) && product?.offers?.find(offer => offer?.name === data?.name)
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const getTypeString = () => {
|
|
44
|
+
return (
|
|
45
|
+
type === 'offer_target_1'
|
|
46
|
+
? t('PRODUCT_DISCOUNT', 'Product discount')
|
|
47
|
+
: type === 'tax'
|
|
48
|
+
? t('TAX', 'Tax')
|
|
49
|
+
: t('Fee', 'Fee')
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
25
53
|
return (
|
|
26
54
|
<TaxInformationContainer>
|
|
27
|
-
|
|
28
|
-
{
|
|
29
|
-
t('
|
|
30
|
-
|
|
31
|
-
|
|
55
|
+
{!!data?.description ? (
|
|
56
|
+
<OText size={24} style={{ alignSelf: 'center', textAlign: 'center' }} mBottom={10}>
|
|
57
|
+
{t('DESCRIPTION', 'Description')}: {data?.description} {data?.type && !type?.includes('offer') && includedOnPriceString}
|
|
58
|
+
</OText>
|
|
59
|
+
) : (
|
|
32
60
|
<OText mBottom={10} size={18} style={{ alignSelf: 'center', textAlign: 'center' }}>
|
|
33
|
-
{t('
|
|
61
|
+
{t('WITHOUT_DESCRIPTION', 'Without description')}
|
|
34
62
|
</OText>
|
|
35
63
|
)}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
64
|
+
{!(type === 'offer_target_2' || type === 'offer_target_3') && (
|
|
65
|
+
<>
|
|
66
|
+
<OText>{t('OTHER_PRODUCTS_WITH_THIS', 'Other products with this')} {getTypeString()}:</OText>
|
|
67
|
+
<ProductContainer>
|
|
68
|
+
{
|
|
69
|
+
products.filter((product: any) => getFilterValidation(product)).map(product => (
|
|
70
|
+
<SingleProductCard
|
|
71
|
+
key={product.id}
|
|
72
|
+
product={product}
|
|
73
|
+
isSoldOut={false}
|
|
74
|
+
businessId={product?.business_id}
|
|
75
|
+
/>
|
|
76
|
+
))
|
|
77
|
+
}
|
|
78
|
+
</ProductContainer>
|
|
79
|
+
</>
|
|
80
|
+
)}
|
|
49
81
|
</TaxInformationContainer>
|
|
50
82
|
)
|
|
51
83
|
}
|
|
@@ -2,7 +2,7 @@ import styled from 'styled-components/native';
|
|
|
2
2
|
|
|
3
3
|
export const Container = styled.View`
|
|
4
4
|
width: 100%;
|
|
5
|
-
padding: 0
|
|
5
|
+
padding: 0 30px;
|
|
6
6
|
`
|
|
7
7
|
|
|
8
8
|
export const CountDownContainer = styled.View`
|
|
@@ -20,7 +20,6 @@ export const ResendSection = styled.View`
|
|
|
20
20
|
display: flex;
|
|
21
21
|
flex-direction: row;
|
|
22
22
|
justify-content: center;
|
|
23
|
-
flex-wrap: wrap;
|
|
24
23
|
`
|
|
25
24
|
|
|
26
25
|
export const WrappCountdown = styled.View`
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import * as React from 'react'
|
|
3
3
|
import { ImageStyle } from 'react-native'
|
|
4
4
|
import styled from 'styled-components/native'
|
|
5
|
+
import { useTheme } from 'styled-components/native'
|
|
5
6
|
|
|
6
7
|
const Wrapper = styled.View``
|
|
7
8
|
|
|
@@ -23,10 +24,12 @@ interface Props {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
const OImage = (props: Props): React.ReactElement => {
|
|
27
|
+
const theme = useTheme();
|
|
28
|
+
|
|
26
29
|
return (
|
|
27
30
|
<Wrapper style={{ borderRadius: props.style?.borderRadius, overflow: 'hidden', marginHorizontal: props.style?.marginHorizontal }}>
|
|
28
31
|
<SImage
|
|
29
|
-
source={props.src ? props.src : props.url ? { uri: props.url } : props.dummy ? props.dummy : require('../../assets/icons/lunch.png')}
|
|
32
|
+
source={props.src ? props.src : props.url ? { uri: props.url } : props.dummy ? props.dummy : theme.images.general.lunch || require('../../assets/icons/lunch.png')}
|
|
30
33
|
style={{
|
|
31
34
|
tintColor: props.color,
|
|
32
35
|
flex: props.isWrap ? 1 : 0,
|
package/src/index.tsx
CHANGED
|
@@ -45,6 +45,7 @@ import { OrdersOption } from './components/OrdersOption';
|
|
|
45
45
|
import { PaymentOptionCash } from './components/PaymentOptionCash';
|
|
46
46
|
import { PaymentOptionStripe } from './components/PaymentOptionStripe';
|
|
47
47
|
import { PaymentOptions } from './components/PaymentOptions';
|
|
48
|
+
import { PaymentOptionsWebView } from './components/PaymentOptionsWebView';
|
|
48
49
|
import { PhoneInputNumber } from './components/PhoneInputNumber';
|
|
49
50
|
import { PreviousOrders } from './components/PreviousOrders';
|
|
50
51
|
import { ProductForm } from './components/ProductForm';
|
|
@@ -144,6 +145,7 @@ export {
|
|
|
144
145
|
PaymentOptionCash,
|
|
145
146
|
PaymentOptionStripe,
|
|
146
147
|
PaymentOptions,
|
|
148
|
+
PaymentOptionsWebView,
|
|
147
149
|
PhoneInputNumber,
|
|
148
150
|
PreviousOrders,
|
|
149
151
|
ProductForm,
|
|
@@ -21,6 +21,7 @@ import HelpOrder from '../pages/HelpOrder'
|
|
|
21
21
|
import HelpGuide from '../pages/HelpGuide'
|
|
22
22
|
import HelpAccountAndPayment from '../pages/HelpAccountAndPayment'
|
|
23
23
|
import Splash from '../pages/Splash';
|
|
24
|
+
import ProductDetails from '../pages/ProductDetails';
|
|
24
25
|
const Stack = createStackNavigator();
|
|
25
26
|
|
|
26
27
|
const HomeNavigator = (e : any) => {
|
|
@@ -101,6 +102,11 @@ const HomeNavigator = (e : any) => {
|
|
|
101
102
|
component={BusinessProductsList}
|
|
102
103
|
options={{ headerShown: false }}
|
|
103
104
|
/>
|
|
105
|
+
<Stack.Screen
|
|
106
|
+
name="ProductDetails"
|
|
107
|
+
component={ProductDetails}
|
|
108
|
+
options={{ headerShown: false }}
|
|
109
|
+
/>
|
|
104
110
|
<Stack.Screen
|
|
105
111
|
name="ReviewOrder"
|
|
106
112
|
component={ReviewOrder}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import styled, { useTheme } from 'styled-components/native';
|
|
3
|
+
import { Platform } from 'react-native';
|
|
4
|
+
import { ProductForm as ProductFormController } from '../components/ProductForm';
|
|
5
|
+
interface Props {
|
|
6
|
+
navigation: any;
|
|
7
|
+
route: any;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const ProductDetails = (props: Props) => {
|
|
11
|
+
const theme = useTheme()
|
|
12
|
+
|
|
13
|
+
const productProps = {
|
|
14
|
+
...props,
|
|
15
|
+
isCartProduct: props.route.params?.isCartProduct,
|
|
16
|
+
isFromCheckout: props.route.params?.isFromCheckout,
|
|
17
|
+
productCart: props.route.params?.productCart,
|
|
18
|
+
product: props.route.params?.product,
|
|
19
|
+
businessSlug: props.route.params?.businessSlug,
|
|
20
|
+
businessId: props.route.params?.businessId,
|
|
21
|
+
categoryId: props.route.params?.categoryId,
|
|
22
|
+
productId: props.route.params?.productId,
|
|
23
|
+
onSave: props?.navigation?.canGoBack()
|
|
24
|
+
? () => { props.route.params?.onAction && props.route.params?.onAction(); props?.navigation?.goBack(); }
|
|
25
|
+
: () => { props.route.params?.onAction && props.route.params?.onAction(); props?.navigation?.navigate('BottomTab') }
|
|
26
|
+
,
|
|
27
|
+
handleGoBack: props?.navigation?.canGoBack()
|
|
28
|
+
? () => {
|
|
29
|
+
props.route.params?.onAction &&
|
|
30
|
+
props.route.params?.onAction();
|
|
31
|
+
props?.navigation?.goBack();
|
|
32
|
+
}
|
|
33
|
+
: (businessSlug: any) => {
|
|
34
|
+
props.route.params?.onAction &&
|
|
35
|
+
props.route.params?.onAction();
|
|
36
|
+
businessSlug
|
|
37
|
+
? props?.navigation.navigate('Business', { store: businessSlug })
|
|
38
|
+
: props?.navigation.navigate('BottomTab')
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const BusinessProductsListView = styled.SafeAreaView`
|
|
43
|
+
flex: 1;
|
|
44
|
+
background-color: ${theme.colors.backgroundPage};
|
|
45
|
+
padding-top: ${Platform.OS === 'ios' ? '0px' : '20px'};
|
|
46
|
+
`;
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<BusinessProductsListView>
|
|
50
|
+
<ProductFormController {...productProps} />
|
|
51
|
+
</BusinessProductsListView>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default ProductDetails;
|
|
@@ -410,8 +410,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
410
410
|
textInputProps={{
|
|
411
411
|
returnKeyType: 'next',
|
|
412
412
|
onSubmitEditing: () => inputRef?.current?.focus?.(),
|
|
413
|
-
style: { borderWidth: 0, fontSize: 12 }
|
|
414
|
-
maxLength: 10
|
|
413
|
+
style: { borderWidth: 0, fontSize: 12 }
|
|
415
414
|
}}
|
|
416
415
|
textWrapStyle={{ borderColor: theme.colors.clear, borderWidth: 0, height: 40, paddingStart: 0 }}
|
|
417
416
|
/>
|
|
@@ -21,10 +21,10 @@ import { Cart as TypeCart } from '../../types';
|
|
|
21
21
|
import CartItem from '../CartItem';
|
|
22
22
|
import NavBar from '../NavBar';
|
|
23
23
|
import { CouponControl } from '../CouponControl';
|
|
24
|
-
import { LANDSCAPE, PORTRAIT, useDeviceOrientation} from "../../../../../src/hooks/DeviceOrientation";
|
|
24
|
+
import { LANDSCAPE, PORTRAIT, useDeviceOrientation } from "../../../../../src/hooks/DeviceOrientation";
|
|
25
25
|
import { useCartBottomSheet } from '../../providers/CartBottomSheetProvider';
|
|
26
26
|
import { Container } from '../../../../../src/layouts/Container';
|
|
27
|
-
|
|
27
|
+
import AntDesignIcon from 'react-native-vector-icons/AntDesign'
|
|
28
28
|
const CartUI = (props: any) => {
|
|
29
29
|
const {
|
|
30
30
|
cart,
|
|
@@ -35,7 +35,7 @@ const CartUI = (props: any) => {
|
|
|
35
35
|
removeProduct,
|
|
36
36
|
setIsCartsLoading,
|
|
37
37
|
navigation,
|
|
38
|
-
}
|
|
38
|
+
}: CartUIProps = props
|
|
39
39
|
|
|
40
40
|
const theme = useTheme()
|
|
41
41
|
const [, t] = useLanguage()
|
|
@@ -83,8 +83,8 @@ const CartUI = (props: any) => {
|
|
|
83
83
|
|
|
84
84
|
const handleChangeOrderType = () => {
|
|
85
85
|
navigation.push('DeliveryType', {
|
|
86
|
-
callback
|
|
87
|
-
goBack: () => {navigation.pop(1)},
|
|
86
|
+
callback: () => { navigation.pop(1) },
|
|
87
|
+
goBack: () => { navigation.pop(1) },
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -97,7 +97,7 @@ const CartUI = (props: any) => {
|
|
|
97
97
|
title={t('CONFIRM_YOUR_ORDER', 'Confirm your order')}
|
|
98
98
|
onActionLeft={goToBack}
|
|
99
99
|
style={{ height: orientationState?.dimensions?.height * 0.08 }}
|
|
100
|
-
btnStyle={{paddingLeft: 0}}
|
|
100
|
+
btnStyle={{ paddingLeft: 0 }}
|
|
101
101
|
rightComponent={(
|
|
102
102
|
<OButton
|
|
103
103
|
text={t('CANCEL_ORDER', 'Cancel order')}
|
|
@@ -183,6 +183,7 @@ const CartUI = (props: any) => {
|
|
|
183
183
|
</OText>
|
|
184
184
|
</OSTable>
|
|
185
185
|
{cart?.discount > 0 && cart?.total >= 0 && orientationState?.orientation == PORTRAIT && (
|
|
186
|
+
|
|
186
187
|
<OSTable
|
|
187
188
|
style={{
|
|
188
189
|
backgroundColor: theme.colors.success,
|
|
@@ -197,10 +198,7 @@ const CartUI = (props: any) => {
|
|
|
197
198
|
flexDirection: 'row',
|
|
198
199
|
}}
|
|
199
200
|
>
|
|
200
|
-
<
|
|
201
|
-
src={theme.images.general.check_decagram}
|
|
202
|
-
/>
|
|
203
|
-
|
|
201
|
+
<AntDesignIcon name='checkcircle' size={24} color='#00D27A' />
|
|
204
202
|
{cart?.discount_type === 1 ? (
|
|
205
203
|
<OText
|
|
206
204
|
mLeft={15}
|
|
@@ -219,8 +217,6 @@ const CartUI = (props: any) => {
|
|
|
219
217
|
</OText>
|
|
220
218
|
)}
|
|
221
219
|
</View>
|
|
222
|
-
|
|
223
|
-
|
|
224
220
|
<OText
|
|
225
221
|
size={16}
|
|
226
222
|
color={theme.colors.green}
|
|
@@ -252,9 +248,9 @@ const CartUI = (props: any) => {
|
|
|
252
248
|
{cart?.driver_tip_rate > 0 &&
|
|
253
249
|
parseInt(configs?.driver_tip_type?.value, 10) === 2 &&
|
|
254
250
|
!!!parseInt(configs?.driver_tip_use_custom?.value, 10) &&
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
251
|
+
(
|
|
252
|
+
`(${parseNumber(cart?.driver_tip_rate)}%)`
|
|
253
|
+
)}
|
|
258
254
|
</OText>
|
|
259
255
|
<OText>{parsePrice(cart?.driver_tip)}</OText>
|
|
260
256
|
</OSTable>
|
|
@@ -294,7 +290,7 @@ const CartUI = (props: any) => {
|
|
|
294
290
|
<>
|
|
295
291
|
<FloatingLayout isIos={Platform.OS === 'ios'}>
|
|
296
292
|
<CheckoutAction>
|
|
297
|
-
<View style={{display: 'flex', flexDirection: 'row'}}>
|
|
293
|
+
<View style={{ display: 'flex', flexDirection: 'row' }}>
|
|
298
294
|
{cart?.discount > 0 && cart?.total >= 0 && orientationState?.orientation == LANDSCAPE && (
|
|
299
295
|
<OSTable
|
|
300
296
|
style={{
|
|
@@ -311,10 +307,7 @@ const CartUI = (props: any) => {
|
|
|
311
307
|
flexDirection: 'row',
|
|
312
308
|
}}
|
|
313
309
|
>
|
|
314
|
-
<
|
|
315
|
-
src={theme.images.general.check_decagram}
|
|
316
|
-
/>
|
|
317
|
-
|
|
310
|
+
<AntDesignIcon name='checkcircle' size={24} color='#00D27A' />
|
|
318
311
|
{cart?.discount_type === 1 ? (
|
|
319
312
|
<OText
|
|
320
313
|
mLeft={15}
|
|
@@ -369,7 +362,7 @@ const CartUI = (props: any) => {
|
|
|
369
362
|
imgRightSrc={null}
|
|
370
363
|
textStyle={{ color: 'white', textAlign: 'center', flex: 1 }}
|
|
371
364
|
onClick={() => { navigation?.navigate('CustomerName', { cartUuid: cart?.uuid }) }}
|
|
372
|
-
style={{width: '100%', marginTop: 4}}
|
|
365
|
+
style={{ width: '100%', marginTop: 4 }}
|
|
373
366
|
/>
|
|
374
367
|
</View>
|
|
375
368
|
</View>
|
|
@@ -16,6 +16,7 @@ import { Product } from '../../types';
|
|
|
16
16
|
import QuantityControl from '../QuantityControl';
|
|
17
17
|
import { LANDSCAPE, useDeviceOrientation } from '../../../../../src/hooks/DeviceOrientation';
|
|
18
18
|
import { useTheme } from 'styled-components/native';
|
|
19
|
+
import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome'
|
|
19
20
|
|
|
20
21
|
const CartItem = (props: CartItemProps) => {
|
|
21
22
|
const theme = useTheme()
|
|
@@ -97,7 +98,6 @@ const CartItem = (props: CartItemProps) => {
|
|
|
97
98
|
<OButton
|
|
98
99
|
bgColor="transparent"
|
|
99
100
|
borderColor="transparent"
|
|
100
|
-
imgLeftSrc={theme.images.general.edit}
|
|
101
101
|
text={t('EDIT', 'Edit')}
|
|
102
102
|
style={{ justifyContent: 'flex-start', paddingLeft: 0, maxWidth: 80 }}
|
|
103
103
|
textStyle={{
|
|
@@ -105,16 +105,18 @@ const CartItem = (props: CartItemProps) => {
|
|
|
105
105
|
marginLeft: 6,
|
|
106
106
|
}}
|
|
107
107
|
onClick={() => { onEditProduct ? onEditProduct(product) : null }}
|
|
108
|
+
iconProps={{ name: 'edit' }}
|
|
109
|
+
IconCustom={() => <FontAwesomeIcon name='edit' size={24} color={theme.colors.primary} />}
|
|
108
110
|
/>
|
|
109
111
|
<OIconButton
|
|
110
112
|
bgColor="transparent"
|
|
111
113
|
borderColor="transparent"
|
|
112
|
-
RenderIcon={isProductIngredients && (() =>
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
114
|
+
RenderIcon={isProductIngredients && (() =>
|
|
115
|
+
<EvilIcons
|
|
116
|
+
name={isActive ? 'chevron-up' : 'chevron-down'}
|
|
117
|
+
size={40}
|
|
118
|
+
color={theme.colors.primary}
|
|
119
|
+
/>
|
|
118
120
|
)}
|
|
119
121
|
style={{ justifyContent: 'flex-start', right: 40 }}
|
|
120
122
|
onClick={() => (!product?.valid_menu && isCartProduct)
|