ordering-ui-react-native 0.14.2 → 0.14.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 +1 -1
- package/src/components/AppleLogin/index.tsx +11 -5
- package/src/components/Checkout/index.tsx +0 -1
- package/src/components/VerifyPhone/index.tsx +1 -1
- package/themes/doordash/src/components/BusinessProductsListing/index.tsx +50 -15
- package/themes/doordash/src/components/FloatingButton/index.tsx +3 -2
- package/themes/doordash/src/components/Messages/index.tsx +2 -1
- package/themes/doordash/src/components/OrderSummary/index.tsx +3 -1
- package/themes/doordash/src/components/ProductForm/index.tsx +18 -6
- package/themes/doordash/src/components/shared/OInput.tsx +1 -0
- package/themes/doordash/src/types/index.tsx +1 -0
- package/themes/original/index.tsx +3 -1
- package/themes/original/src/components/BusinessCart/index.tsx +182 -0
- package/themes/original/src/components/BusinessCart/styles.tsx +46 -0
- package/themes/original/src/components/BusinessItemAccordion/index.tsx +17 -0
- package/themes/original/src/components/BusinessesListing/index.tsx +4 -2
- package/themes/original/src/components/Cart/index.tsx +20 -3
- package/themes/original/src/components/CartContent/index.tsx +4 -2
- package/themes/original/src/components/CartStoresListing/index.tsx +98 -0
- package/themes/original/src/components/CartStoresListing/styles.tsx +30 -0
- package/themes/original/src/components/Checkout/index.tsx +134 -32
- package/themes/original/src/components/Checkout/styles.tsx +13 -0
- package/themes/original/src/components/OrderDetails/index.tsx +16 -8
- package/themes/original/src/components/OrderDetails/styles.tsx +1 -1
- package/themes/original/src/types/index.tsx +2 -1
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect } from 'react';
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import { Platform, StyleSheet } from 'react-native';
|
|
3
3
|
import { appleAuthAndroid, appleAuth } from '@invertase/react-native-apple-authentication';
|
|
4
4
|
import { useConfig, useApi, useLanguage } from 'ordering-components/native'
|
|
@@ -22,7 +22,7 @@ export const AppleLogin = (props: AppleLoginParams) => {
|
|
|
22
22
|
const [ordering] = useApi()
|
|
23
23
|
const [, t] = useLanguage()
|
|
24
24
|
const theme = useTheme()
|
|
25
|
-
|
|
25
|
+
const [errors, setError] = useState<any>({type: '', message: ''})
|
|
26
26
|
const buttonText = t('LOGIN_WITH_APPLE', 'Login with Apple');
|
|
27
27
|
|
|
28
28
|
const onAppleButtonPress = async () => {
|
|
@@ -45,16 +45,16 @@ export const AppleLogin = (props: AppleLoginParams) => {
|
|
|
45
45
|
identityToken,
|
|
46
46
|
authorizationCode,
|
|
47
47
|
} = appleAuthRequestResponse
|
|
48
|
-
|
|
49
|
-
if (identityToken && authorizationCode) {
|
|
48
|
+
if (identityToken) {
|
|
50
49
|
console.log('auth code: ', authorizationCode)
|
|
51
|
-
handleLoginApple(
|
|
50
|
+
handleLoginApple(identityToken)
|
|
52
51
|
console.warn(`Apple Authentication Completed, ${user}, ${email}`);
|
|
53
52
|
} else {
|
|
54
53
|
handleErrors && handleErrors(t('ERROR_LOGIN_APPLE', 'Error login with apple'))
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
} catch (error: any) {
|
|
57
|
+
setError({ type: 'FROM_APPLE', message: error?.message })
|
|
58
58
|
handleErrors && handleErrors(error.message)
|
|
59
59
|
}
|
|
60
60
|
} else {
|
|
@@ -106,6 +106,7 @@ export const AppleLogin = (props: AppleLoginParams) => {
|
|
|
106
106
|
handleErrors && handleErrors(result || t('ERROR_LOGIN_AUTH_APPLE', 'Error login auth with apple'))
|
|
107
107
|
}
|
|
108
108
|
} catch (error: any) {
|
|
109
|
+
setError({ type: 'FROM_API', message: error?.message })
|
|
109
110
|
handleLoading && handleLoading(false)
|
|
110
111
|
handleErrors && handleErrors(error?.message)
|
|
111
112
|
}
|
|
@@ -120,6 +121,11 @@ export const AppleLogin = (props: AppleLoginParams) => {
|
|
|
120
121
|
|
|
121
122
|
return (
|
|
122
123
|
<Container>
|
|
124
|
+
{!!errors?.message && !!errors?.type && (
|
|
125
|
+
<OText>
|
|
126
|
+
{errors?.type} {errors?.message}
|
|
127
|
+
</OText>
|
|
128
|
+
)}
|
|
123
129
|
<AppleButton
|
|
124
130
|
onPress={onAppleButtonPress}
|
|
125
131
|
>
|
|
@@ -55,7 +55,6 @@ import { ActivityIndicator } from 'react-native-paper';
|
|
|
55
55
|
import WebView from 'react-native-webview';
|
|
56
56
|
import Icon from 'react-native-vector-icons/Feather';
|
|
57
57
|
import { OrderCreating } from '../OrderCreating';
|
|
58
|
-
import { Item } from '../../../themes/uber-eats/src/components/UpsellingProducts/styles';
|
|
59
58
|
|
|
60
59
|
const mapConfigs = {
|
|
61
60
|
mapZoom: 16,
|
|
@@ -196,7 +196,7 @@ export const VerifyPhone = (props: any) => {
|
|
|
196
196
|
<WrappCountdown>
|
|
197
197
|
<CountDownContainer color={timer === '00:00' ? theme.colors.error: theme.colors.success}>
|
|
198
198
|
<OText
|
|
199
|
-
size={
|
|
199
|
+
size={28}
|
|
200
200
|
color={timer === '00:00' ? theme.colors.error: theme.colors.success}
|
|
201
201
|
>
|
|
202
202
|
{timer}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, { useState, useRef, useCallback } from 'react'
|
|
2
|
-
import { View, TouchableOpacity, StyleSheet, TextStyle, ScrollView, I18nManager, Platform } from 'react-native'
|
|
1
|
+
import React, { useState, useRef, useCallback, useEffect } from 'react'
|
|
2
|
+
import { View, TouchableOpacity, StyleSheet, TextStyle, ScrollView, I18nManager, Platform, KeyboardAvoidingView, Keyboard } from 'react-native'
|
|
3
3
|
import {
|
|
4
4
|
BusinessAndProductList,
|
|
5
5
|
useLanguage,
|
|
@@ -36,7 +36,7 @@ import { Cart } from '../Cart'
|
|
|
36
36
|
import { OrderSummary } from '../OrderSummary'
|
|
37
37
|
import NavBar from '../NavBar'
|
|
38
38
|
import SocialShareFav from '../SocialShare'
|
|
39
|
-
|
|
39
|
+
import { SafeAreaContainer } from '../../layouts/SafeAreaContainer'
|
|
40
40
|
const PIXELS_TO_SCROLL = 1000
|
|
41
41
|
|
|
42
42
|
const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
@@ -112,6 +112,8 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
112
112
|
const [categoriesLayout, setCategoriesLayout] = useState<any>({})
|
|
113
113
|
const [productListLayout, setProductListLayout] = useState<any>(null)
|
|
114
114
|
const [selectedCategoryId, setSelectedCategoryId] = useState<any>('cat_all')
|
|
115
|
+
const [isKeyboardOpen, setIsKeyBoardOpen] = useState(false)
|
|
116
|
+
const cartRef = useRef<any>()
|
|
115
117
|
|
|
116
118
|
const scrollViewRef = useRef<any>(null)
|
|
117
119
|
|
|
@@ -187,6 +189,21 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
187
189
|
setCategoryClicked(false);
|
|
188
190
|
}, []);
|
|
189
191
|
|
|
192
|
+
useEffect(() => {
|
|
193
|
+
Keyboard.addListener('keyboardDidShow', () => {
|
|
194
|
+
setIsKeyBoardOpen(true)
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
Keyboard.addListener('keyboardDidHide', () => [
|
|
198
|
+
setIsKeyBoardOpen(false)
|
|
199
|
+
])
|
|
200
|
+
|
|
201
|
+
return () => {
|
|
202
|
+
Keyboard.removeAllListeners('keyboardDidShow')
|
|
203
|
+
Keyboard.removeAllListeners('keyboardDidHide')
|
|
204
|
+
}
|
|
205
|
+
}, [])
|
|
206
|
+
|
|
190
207
|
return (
|
|
191
208
|
<>
|
|
192
209
|
<Animated.View style={{ flex: 1, backgroundColor: theme.colors.white, position: 'absolute', width: '100%', top: top, zIndex: 1 }}>
|
|
@@ -358,18 +375,36 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
358
375
|
entireModal
|
|
359
376
|
customClose
|
|
360
377
|
>
|
|
361
|
-
<
|
|
362
|
-
<
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
378
|
+
<SafeAreaContainer>
|
|
379
|
+
<KeyboardAvoidingView
|
|
380
|
+
style={{ flex: 1 }}
|
|
381
|
+
behavior={Platform.OS === 'ios' ? 'height' : 'padding'}
|
|
382
|
+
enabled={Platform.OS === 'ios'}
|
|
383
|
+
>
|
|
384
|
+
<ScrollView
|
|
385
|
+
stickyHeaderIndices={[0]}
|
|
386
|
+
style={{ backgroundColor: 'white' }}
|
|
387
|
+
contentContainerStyle={{ paddingBottom: 100 }}
|
|
388
|
+
ref={(ref : any) => cartRef.current = ref}
|
|
389
|
+
>
|
|
390
|
+
<NavBar title={t('CART', 'Cart')} onActionLeft={handleCloseCartModal} leftImg={theme.images.general.close} noBorder btnStyle={{ paddingLeft: 0 }} />
|
|
391
|
+
<OrderSummary
|
|
392
|
+
cart={currentCart}
|
|
393
|
+
isCartPending={currentCart?.status === 2}
|
|
394
|
+
hasUpSelling={true}
|
|
395
|
+
isFromCheckout
|
|
396
|
+
title={t('ITEMS', 'Items')}
|
|
397
|
+
paddingH={40}
|
|
398
|
+
cartRef={cartRef}
|
|
399
|
+
/>
|
|
400
|
+
</ScrollView>
|
|
401
|
+
<FloatingButton
|
|
402
|
+
style={{bottom: isKeyboardOpen && Platform.OS === 'ios' ? 30 : 0}}
|
|
403
|
+
btnText={t('CHECKOUT', 'Checkout')}
|
|
404
|
+
handleClick={() => handleUpsellingPage()}
|
|
405
|
+
/>
|
|
406
|
+
</KeyboardAvoidingView>
|
|
407
|
+
</SafeAreaContainer>
|
|
373
408
|
</OModal>
|
|
374
409
|
</>
|
|
375
410
|
)
|
|
@@ -19,7 +19,8 @@ const FloatingButtonUI = (props: FloatingButtonParams) => {
|
|
|
19
19
|
btnText,
|
|
20
20
|
handleButtonClick,
|
|
21
21
|
disabled,
|
|
22
|
-
isSecondaryBtn
|
|
22
|
+
isSecondaryBtn,
|
|
23
|
+
style
|
|
23
24
|
} = props
|
|
24
25
|
|
|
25
26
|
const theme = useTheme();
|
|
@@ -39,7 +40,7 @@ const FloatingButtonUI = (props: FloatingButtonParams) => {
|
|
|
39
40
|
const { bottom } = useSafeAreaInsets();
|
|
40
41
|
|
|
41
42
|
return (
|
|
42
|
-
<Container isIos={Platform.OS === 'ios'} style={{ paddingBottom: bottom + 10 }}>
|
|
43
|
+
<Container isIos={Platform.OS === 'ios'} style={{ ...style, paddingBottom: bottom + 10 }}>
|
|
43
44
|
<Button
|
|
44
45
|
style={[isSecondaryBtn ? styles.secodaryBtn : styles.primaryBtn]}
|
|
45
46
|
onPress={handleButtonClick}
|
|
@@ -272,7 +272,8 @@ const MessagesUI = (props: MessagesParams) => {
|
|
|
272
272
|
{...props}
|
|
273
273
|
containerStyle={{
|
|
274
274
|
padding: Platform.OS === 'ios' && isKeyboardShow ? 0 : 10,
|
|
275
|
-
flexDirection: 'column-reverse'
|
|
275
|
+
flexDirection: 'column-reverse',
|
|
276
|
+
marginBottom: Platform.OS === 'ios' && isKeyboardShow ? 500 : 0
|
|
276
277
|
}}
|
|
277
278
|
primaryStyle={{ alignItems: 'center', justifyContent: 'flex-start' }}
|
|
278
279
|
renderAccessory={() => renderAccessory()}
|
|
@@ -41,7 +41,8 @@ const OrderSummaryUI = (props: any) => {
|
|
|
41
41
|
paddingH,
|
|
42
42
|
isMini,
|
|
43
43
|
commentState,
|
|
44
|
-
handleChangeComment
|
|
44
|
+
handleChangeComment,
|
|
45
|
+
cartRef
|
|
45
46
|
} = props;
|
|
46
47
|
|
|
47
48
|
const theme = useTheme();
|
|
@@ -256,6 +257,7 @@ const OrderSummaryUI = (props: any) => {
|
|
|
256
257
|
}}
|
|
257
258
|
multiline
|
|
258
259
|
inputStyle={{color: theme.colors.textPrimary}}
|
|
260
|
+
onFocus={() => cartRef?.current?.scrollToEnd?.()}
|
|
259
261
|
/>
|
|
260
262
|
{commentState?.loading && (
|
|
261
263
|
<View style={{ position: 'absolute', right: 20 }}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useState, useRef, useEffect } from 'react'
|
|
2
2
|
import {
|
|
3
3
|
ProductForm as ProductOptions,
|
|
4
4
|
useSession,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from 'ordering-components/native'
|
|
9
9
|
import { ProductIngredient } from '../ProductIngredient'
|
|
10
10
|
import { ProductOption } from '../ProductOption'
|
|
11
|
-
import { View, TouchableOpacity, StyleSheet, Dimensions, ScrollView, I18nManager, TextStyle, Platform, KeyboardAvoidingView } from 'react-native'
|
|
11
|
+
import { View, TouchableOpacity, StyleSheet, Dimensions, ScrollView, I18nManager, TextStyle, Platform, KeyboardAvoidingView, Keyboard } from 'react-native'
|
|
12
12
|
import {
|
|
13
13
|
ProductHeader,
|
|
14
14
|
WrapHeader,
|
|
@@ -107,9 +107,9 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
107
107
|
const [orderState] = useOrder()
|
|
108
108
|
const [{ auth }] = useSession()
|
|
109
109
|
const { product, loading, error } = productObject
|
|
110
|
-
|
|
111
110
|
const { bottom } = useSafeAreaInsets();
|
|
112
|
-
|
|
111
|
+
const [commentY, setCommentY] = useState(0)
|
|
112
|
+
const productFormRef = useRef<any>()
|
|
113
113
|
const isError = (id: number) => {
|
|
114
114
|
let bgColor = theme.colors.white
|
|
115
115
|
if (errors[`id:${id}`]) {
|
|
@@ -136,13 +136,25 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
136
136
|
|
|
137
137
|
const saveErrors = orderState.loading || maxProductQuantity === 0 || Object.keys(errors).length > 0
|
|
138
138
|
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
Keyboard.addListener('keyboardDidShow', () => {
|
|
141
|
+
if (commentY > 100) {
|
|
142
|
+
productFormRef?.current?.scrollTo?.({ x: 0, y: commentY + 300, animated: true })
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
return () => {
|
|
147
|
+
Keyboard.removeAllListeners('keyboardDidShow')
|
|
148
|
+
}
|
|
149
|
+
}, [productFormRef?.current, commentY])
|
|
150
|
+
|
|
139
151
|
return (
|
|
140
152
|
<KeyboardAvoidingView
|
|
141
153
|
style={{ flex: 1 }}
|
|
142
154
|
behavior={Platform.OS ? 'padding' : 'height'}
|
|
143
155
|
enabled={Platform.OS === 'ios'}
|
|
144
156
|
>
|
|
145
|
-
<ScrollView style={styles.mainContainer}>
|
|
157
|
+
<ScrollView style={styles.mainContainer} ref={(ref) => productFormRef.current = ref}>
|
|
146
158
|
{!error && (
|
|
147
159
|
<View style={{ paddingBottom: 80 }}>
|
|
148
160
|
<WrapHeader>
|
|
@@ -275,7 +287,7 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
275
287
|
</React.Fragment>
|
|
276
288
|
)
|
|
277
289
|
}))}
|
|
278
|
-
<ProductComment>
|
|
290
|
+
<ProductComment onLayout={(e: any) => setCommentY(e.nativeEvent.layout.y + e.nativeEvent.layout.height)}>
|
|
279
291
|
<SectionTitle>
|
|
280
292
|
<OText style={theme.labels.middle as TextStyle}>{t('SPECIAL_COMMENT', 'Special comment')}</OText>
|
|
281
293
|
</SectionTitle>
|
|
@@ -99,6 +99,7 @@ const OInput = (props: Props): React.ReactElement => {
|
|
|
99
99
|
returnKeyType={props.returnKeyType}
|
|
100
100
|
onSubmitEditing={props.onSubmitEditing}
|
|
101
101
|
blurOnSubmit={props.blurOnSubmit}
|
|
102
|
+
onFocus={props.onFocus}
|
|
102
103
|
ref={props.forwardRef}
|
|
103
104
|
style={{padding: 0, ...props.inputStyle}}
|
|
104
105
|
/>
|
|
@@ -9,6 +9,7 @@ import { AppleLogin } from './src/components/AppleLogin';
|
|
|
9
9
|
import { BusinessesListing } from './src/components/BusinessesListing';
|
|
10
10
|
import { BusinessProductsListing } from './src/components/BusinessProductsListing';
|
|
11
11
|
import { CartContent } from './src/components/CartContent';
|
|
12
|
+
import { BusinessCart } from './src/components/BusinessCart';
|
|
12
13
|
import { Checkout } from './src/components/Checkout';
|
|
13
14
|
import { ForgotPasswordForm } from './src/components/ForgotPasswordForm';
|
|
14
15
|
import { MomentOption } from './src/components/MomentOption';
|
|
@@ -66,6 +67,7 @@ export {
|
|
|
66
67
|
BusinessesListing,
|
|
67
68
|
BusinessProductsListing,
|
|
68
69
|
CartContent,
|
|
70
|
+
BusinessCart,
|
|
69
71
|
Checkout,
|
|
70
72
|
ForgotPasswordForm,
|
|
71
73
|
MomentOption,
|
|
@@ -110,4 +112,4 @@ export {
|
|
|
110
112
|
_setStoreData,
|
|
111
113
|
_removeStoreData,
|
|
112
114
|
_clearStoreData
|
|
113
|
-
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleSheet, TouchableOpacity, View, ActivityIndicator } from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
useUtils,
|
|
5
|
+
useLanguage,
|
|
6
|
+
useOrder
|
|
7
|
+
} from 'ordering-components/native'
|
|
8
|
+
|
|
9
|
+
import { useTheme } from 'styled-components/native';
|
|
10
|
+
import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
|
|
11
|
+
import { OIcon, OText } from '../shared';
|
|
12
|
+
import { convertHoursToMinutes } from '../../utils';
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
Card,
|
|
16
|
+
BusinessContent,
|
|
17
|
+
BusinessInfo,
|
|
18
|
+
BusinessActions,
|
|
19
|
+
Metadata,
|
|
20
|
+
Reviews,
|
|
21
|
+
BtnWrapper
|
|
22
|
+
} from './styles'
|
|
23
|
+
|
|
24
|
+
export const BusinessCart = (props: any) => {
|
|
25
|
+
const {
|
|
26
|
+
business,
|
|
27
|
+
isLoading,
|
|
28
|
+
isDisabled,
|
|
29
|
+
isSkeleton,
|
|
30
|
+
handleCartStoreClick
|
|
31
|
+
} = props
|
|
32
|
+
|
|
33
|
+
const [, t] = useLanguage()
|
|
34
|
+
const theme = useTheme();
|
|
35
|
+
const [orderState] = useOrder()
|
|
36
|
+
const [{ parsePrice, parseDistance, parseNumber }] = useUtils();
|
|
37
|
+
|
|
38
|
+
const styles = StyleSheet.create({
|
|
39
|
+
starIcon: {
|
|
40
|
+
marginHorizontal: 2,
|
|
41
|
+
marginTop: -5,
|
|
42
|
+
},
|
|
43
|
+
bullet: {
|
|
44
|
+
flexDirection: 'row',
|
|
45
|
+
alignItems: 'center',
|
|
46
|
+
justifyContent: 'flex-start',
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<Card>
|
|
52
|
+
<BusinessContent>
|
|
53
|
+
<BusinessInfo>
|
|
54
|
+
{business?.name && (
|
|
55
|
+
<OText
|
|
56
|
+
size={12}
|
|
57
|
+
weight={'500'}>
|
|
58
|
+
{business?.name}
|
|
59
|
+
</OText>
|
|
60
|
+
)}
|
|
61
|
+
{isSkeleton && (
|
|
62
|
+
<Placeholder
|
|
63
|
+
Animation={Fade}
|
|
64
|
+
style={{ marginBottom: 5 }}
|
|
65
|
+
>
|
|
66
|
+
<PlaceholderLine
|
|
67
|
+
height={10}
|
|
68
|
+
width={40}
|
|
69
|
+
style={{ marginBottom: 5 }}
|
|
70
|
+
/>
|
|
71
|
+
</Placeholder>
|
|
72
|
+
)}
|
|
73
|
+
{!!business?.address && (
|
|
74
|
+
<OText
|
|
75
|
+
size={10}
|
|
76
|
+
numberOfLines={1}
|
|
77
|
+
ellipsizeMode={'tail'}
|
|
78
|
+
style={{ marginBottom: 5 }}
|
|
79
|
+
>
|
|
80
|
+
{business?.address}
|
|
81
|
+
</OText>
|
|
82
|
+
)}
|
|
83
|
+
{isSkeleton && (
|
|
84
|
+
<Placeholder
|
|
85
|
+
Animation={Fade}
|
|
86
|
+
style={{ marginBottom: 5 }}
|
|
87
|
+
>
|
|
88
|
+
<PlaceholderLine
|
|
89
|
+
height={10}
|
|
90
|
+
width={80}
|
|
91
|
+
style={{ marginBottom: 5 }}
|
|
92
|
+
/>
|
|
93
|
+
</Placeholder>
|
|
94
|
+
)}
|
|
95
|
+
<Metadata>
|
|
96
|
+
{!isSkeleton ? (
|
|
97
|
+
<View style={styles.bullet}>
|
|
98
|
+
<OText size={10} color={theme.colors.textSecondary}>
|
|
99
|
+
{`${t('DELIVERY_FEE', 'Delivery fee')} ${parsePrice(business?.delivery_price) + ' \u2022 '}`}
|
|
100
|
+
</OText>
|
|
101
|
+
<OText size={10} color={theme.colors.textSecondary}>{`${convertHoursToMinutes(
|
|
102
|
+
orderState?.options?.type === 1
|
|
103
|
+
? business?.delivery_time
|
|
104
|
+
: business?.pickup_time,
|
|
105
|
+
)} \u2022 `}</OText>
|
|
106
|
+
<OText size={10} color={theme.colors.textSecondary}>{parseDistance(business?.distance)}</OText>
|
|
107
|
+
</View>
|
|
108
|
+
) : (
|
|
109
|
+
<Placeholder
|
|
110
|
+
Animation={Fade}
|
|
111
|
+
style={{ marginBottom: 5 }}
|
|
112
|
+
>
|
|
113
|
+
<PlaceholderLine
|
|
114
|
+
height={10}
|
|
115
|
+
width={60}
|
|
116
|
+
style={{ marginBottom: 5 }}
|
|
117
|
+
/>
|
|
118
|
+
</Placeholder>
|
|
119
|
+
)}
|
|
120
|
+
</Metadata>
|
|
121
|
+
</BusinessInfo>
|
|
122
|
+
<BusinessActions>
|
|
123
|
+
{business?.reviews?.total > 0 && (
|
|
124
|
+
<Reviews>
|
|
125
|
+
<OIcon src={theme.images.general.star} width={12} style={styles.starIcon} />
|
|
126
|
+
<OText size={10} style={{ lineHeight: 15 }}>
|
|
127
|
+
{parseNumber(business?.reviews?.total ?? 1, { separator: '.' })}
|
|
128
|
+
</OText>
|
|
129
|
+
</Reviews>
|
|
130
|
+
)}
|
|
131
|
+
<BtnWrapper>
|
|
132
|
+
{handleCartStoreClick && (
|
|
133
|
+
<TouchableOpacity
|
|
134
|
+
activeOpacity={1}
|
|
135
|
+
disabled={isDisabled}
|
|
136
|
+
onPress={() => handleCartStoreClick && handleCartStoreClick(business?.id)}
|
|
137
|
+
style={{
|
|
138
|
+
backgroundColor: isDisabled ? theme.colors.disabled : theme.colors.white,
|
|
139
|
+
borderColor: isDisabled ? theme.colors.disabled : theme.colors.primary,
|
|
140
|
+
justifyContent: 'center',
|
|
141
|
+
position: 'relative',
|
|
142
|
+
flexDirection: 'row',
|
|
143
|
+
alignItems: 'center',
|
|
144
|
+
paddingRight: 10,
|
|
145
|
+
paddingLeft: 10,
|
|
146
|
+
borderRadius: 7.6,
|
|
147
|
+
borderWidth: 1,
|
|
148
|
+
height: 30,
|
|
149
|
+
}}
|
|
150
|
+
>
|
|
151
|
+
<OText
|
|
152
|
+
style={{
|
|
153
|
+
color: isDisabled ? theme.colors.white : theme.colors.primary,
|
|
154
|
+
fontSize: 12,
|
|
155
|
+
}}
|
|
156
|
+
>
|
|
157
|
+
{isLoading ? (
|
|
158
|
+
<ActivityIndicator size="small" color={theme.colors.primary} />
|
|
159
|
+
) : (
|
|
160
|
+
t('SELECT', 'Select')
|
|
161
|
+
)}
|
|
162
|
+
</OText>
|
|
163
|
+
</TouchableOpacity>
|
|
164
|
+
)}
|
|
165
|
+
{isSkeleton && (
|
|
166
|
+
<Placeholder
|
|
167
|
+
Animation={Fade}
|
|
168
|
+
style={{ marginBottom: 5 }}
|
|
169
|
+
>
|
|
170
|
+
<PlaceholderLine
|
|
171
|
+
height={30}
|
|
172
|
+
width={80}
|
|
173
|
+
style={{ marginBottom: 5 }}
|
|
174
|
+
/>
|
|
175
|
+
</Placeholder>
|
|
176
|
+
)}
|
|
177
|
+
</BtnWrapper>
|
|
178
|
+
</BusinessActions>
|
|
179
|
+
</BusinessContent>
|
|
180
|
+
</Card>
|
|
181
|
+
)
|
|
182
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import styled from 'styled-components/native';
|
|
2
|
+
|
|
3
|
+
export const Card = styled.View`
|
|
4
|
+
margin-bottom: 20px;
|
|
5
|
+
border-radius: 7.6px;
|
|
6
|
+
width: 100%;
|
|
7
|
+
position: relative;
|
|
8
|
+
`
|
|
9
|
+
|
|
10
|
+
export const BusinessContent = styled.View`
|
|
11
|
+
border-radius: 7.6px;
|
|
12
|
+
overflow: visible;
|
|
13
|
+
flex-direction: row;
|
|
14
|
+
justify-content: space-between;
|
|
15
|
+
width: 100%;
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
export const BusinessInfo = styled.View`
|
|
19
|
+
width: 70%;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
justify-content: space-between;
|
|
22
|
+
align-items: flex-start;
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
export const BusinessActions = styled.View`
|
|
26
|
+
width: 30%;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
align-items: flex-end;
|
|
29
|
+
`
|
|
30
|
+
|
|
31
|
+
export const Metadata = styled.View`
|
|
32
|
+
flex-direction: row;
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
export const Reviews = styled.View`
|
|
36
|
+
flex-direction: row;
|
|
37
|
+
align-items: center;
|
|
38
|
+
margin-top: 5px;
|
|
39
|
+
`
|
|
40
|
+
|
|
41
|
+
export const BtnWrapper = styled.View`
|
|
42
|
+
display: flex;
|
|
43
|
+
flex-direction: row;
|
|
44
|
+
align-items: center;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
`
|
|
@@ -84,6 +84,23 @@ export const BusinessItemAccordion = (props: any) => {
|
|
|
84
84
|
<OText size={12} lineHeight={18} color={theme.colors.textSecondary} style={{ textDecorationLine: 'underline' }}>{t('CLEAR_CART', 'Clear cart')}</OText>
|
|
85
85
|
</OAlert>
|
|
86
86
|
)}
|
|
87
|
+
{props.handleChangeStore && (
|
|
88
|
+
<>
|
|
89
|
+
<OText color={theme.colors.textSecondary}>{' \u2022 '}</OText>
|
|
90
|
+
<TouchableOpacity
|
|
91
|
+
onPress={props.handleChangeStore}
|
|
92
|
+
>
|
|
93
|
+
<OText
|
|
94
|
+
size={12}
|
|
95
|
+
lineHeight={18}
|
|
96
|
+
color={theme.colors.textSecondary}
|
|
97
|
+
style={{ textDecorationLine: 'underline' }}
|
|
98
|
+
>
|
|
99
|
+
{t('CHANGE_STORE', 'Change store')}
|
|
100
|
+
</OText>
|
|
101
|
+
</TouchableOpacity>
|
|
102
|
+
</>
|
|
103
|
+
)}
|
|
87
104
|
</View>
|
|
88
105
|
</BIContentInfo>
|
|
89
106
|
</BIInfo>
|
|
@@ -277,7 +277,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
277
277
|
/>
|
|
278
278
|
</OrderProgressWrapper>
|
|
279
279
|
)}
|
|
280
|
-
{featuredBusiness && featuredBusiness.length > 0 && (
|
|
280
|
+
{!props.franchiseId && featuredBusiness && featuredBusiness.length > 0 && (
|
|
281
281
|
<FeaturedWrapper>
|
|
282
282
|
<OText size={16} style={{ marginLeft: 40 }} weight={Platform.OS === 'ios' ? '600' : 'bold'}>{t('FEATURED_BUSINESS', 'Featured business')}</OText>
|
|
283
283
|
<ScrollView
|
|
@@ -306,7 +306,9 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
306
306
|
</FeaturedWrapper>
|
|
307
307
|
)}
|
|
308
308
|
<View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100 }} />
|
|
309
|
-
|
|
309
|
+
{!props.franchiseId && (
|
|
310
|
+
<HighestRatedBusinesses onBusinessClick={handleBusinessClick} navigation={navigation} />
|
|
311
|
+
)}
|
|
310
312
|
<View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100 }} />
|
|
311
313
|
<ListWrapper>
|
|
312
314
|
<BusinessTypeFilter
|
|
@@ -23,6 +23,7 @@ import { verifyDecimals } from '../../utils';
|
|
|
23
23
|
import { ActivityIndicator, TouchableOpacity, View } from 'react-native';
|
|
24
24
|
import AntIcon from 'react-native-vector-icons/AntDesign'
|
|
25
25
|
import { TaxInformation } from '../TaxInformation';
|
|
26
|
+
import { CartStoresListing } from '../CartStoresListing';
|
|
26
27
|
|
|
27
28
|
const CartUI = (props: any) => {
|
|
28
29
|
const {
|
|
@@ -51,12 +52,16 @@ const CartUI = (props: any) => {
|
|
|
51
52
|
const [openProduct, setModalIsOpen] = useState(false)
|
|
52
53
|
const [curProduct, setCurProduct] = useState<any>(null)
|
|
53
54
|
const [openUpselling, setOpenUpselling] = useState(false)
|
|
55
|
+
const [openChangeStore, setOpenChangeStore] = useState(false)
|
|
54
56
|
const [canOpenUpselling, setCanOpenUpselling] = useState(false)
|
|
55
57
|
const [openTaxModal, setOpenTaxModal] = useState<any>({ open: false, data: null })
|
|
56
58
|
|
|
57
59
|
const isCartPending = cart?.status === 2
|
|
58
60
|
const isCouponEnabled = validationFields?.fields?.checkout?.coupon?.enabled
|
|
59
61
|
|
|
62
|
+
const business: any = (orderState?.carts && Object.values(orderState.carts).find((_cart: any) => _cart?.uuid === props.cartuuid)) ?? {}
|
|
63
|
+
const businessId = business?.business_id ?? null
|
|
64
|
+
|
|
60
65
|
const momentFormatted = !orderState?.option?.moment
|
|
61
66
|
? t('RIGHT_NOW', 'Right Now')
|
|
62
67
|
: parseDate(orderState?.option?.moment, { outputFormat: 'YYYY-MM-DD HH:mm' })
|
|
@@ -116,6 +121,7 @@ const CartUI = (props: any) => {
|
|
|
116
121
|
handleClearProducts={handleClearProducts}
|
|
117
122
|
handleCartOpen={handleCartOpen}
|
|
118
123
|
onNavigationRedirect={props.onNavigationRedirect}
|
|
124
|
+
handleChangeStore={props.isFranchiseApp ? () => setOpenChangeStore(true) : null}
|
|
119
125
|
>
|
|
120
126
|
{cart?.products?.length > 0 && cart?.products.map((product: any) => (
|
|
121
127
|
<ProductItemAccordion
|
|
@@ -217,7 +223,7 @@ const CartUI = (props: any) => {
|
|
|
217
223
|
<OSTable>
|
|
218
224
|
<OSCoupon>
|
|
219
225
|
<CouponControl
|
|
220
|
-
businessId={
|
|
226
|
+
businessId={businessId}
|
|
221
227
|
price={cart.total}
|
|
222
228
|
/>
|
|
223
229
|
</OSCoupon>
|
|
@@ -299,20 +305,31 @@ const CartUI = (props: any) => {
|
|
|
299
305
|
isCartProduct
|
|
300
306
|
productCart={curProduct}
|
|
301
307
|
businessSlug={cart?.business?.slug}
|
|
302
|
-
businessId={
|
|
308
|
+
businessId={businessId}
|
|
303
309
|
categoryId={curProduct?.category_id}
|
|
304
310
|
productId={curProduct?.id}
|
|
305
311
|
onSave={handlerProductAction}
|
|
306
312
|
onClose={() => setModalIsOpen(false)}
|
|
307
313
|
/>
|
|
314
|
+
</OModal>
|
|
308
315
|
|
|
316
|
+
<OModal
|
|
317
|
+
open={openChangeStore && props.isFranchiseApp}
|
|
318
|
+
entireModal
|
|
319
|
+
customClose
|
|
320
|
+
onClose={() => setOpenChangeStore(false)}
|
|
321
|
+
>
|
|
322
|
+
<CartStoresListing
|
|
323
|
+
cartuuid={cart?.uuid}
|
|
324
|
+
onClose={() => setOpenChangeStore(false)}
|
|
325
|
+
/>
|
|
309
326
|
</OModal>
|
|
310
327
|
|
|
311
328
|
{openUpselling && (
|
|
312
329
|
<UpsellingProducts
|
|
313
330
|
handleUpsellingPage={handleUpsellingPage}
|
|
314
331
|
openUpselling={openUpselling}
|
|
315
|
-
businessId={
|
|
332
|
+
businessId={businessId}
|
|
316
333
|
business={cart?.business}
|
|
317
334
|
cartProducts={cart?.products}
|
|
318
335
|
canOpenUpselling={canOpenUpselling}
|
|
@@ -25,12 +25,14 @@ export const CartContent = (props: any) => {
|
|
|
25
25
|
<OText size={24} lineHeight={36} weight={'600'} style={{ marginBottom: 20 }}>
|
|
26
26
|
{carts.length > 1 ? t('MY_CARTS', 'My Carts') : t('CART', 'Cart')}
|
|
27
27
|
</OText>
|
|
28
|
-
{carts.map((cart: any) => (
|
|
29
|
-
<CCList key={
|
|
28
|
+
{carts.map((cart: any, i: number) => (
|
|
29
|
+
<CCList key={i} style={{ overflow: 'visible' }}>
|
|
30
30
|
{cart.products.length > 0 && (
|
|
31
31
|
<>
|
|
32
32
|
<Cart
|
|
33
|
+
isFranchiseApp={props.isFranchiseApp}
|
|
33
34
|
cart={cart}
|
|
35
|
+
cartuuid={cart.uuid}
|
|
34
36
|
onNavigationRedirect={props.onNavigationRedirect}
|
|
35
37
|
isCartsLoading={isCartsLoading}
|
|
36
38
|
setIsCartsLoading={setIsCartsLoading}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTheme } from 'styled-components/native';
|
|
3
|
+
import {
|
|
4
|
+
CartStoresListing as StoresListingController,
|
|
5
|
+
useOrder,
|
|
6
|
+
useLanguage
|
|
7
|
+
} from 'ordering-components/native'
|
|
8
|
+
|
|
9
|
+
import { NotFoundSource } from '../NotFoundSource'
|
|
10
|
+
import { BusinessCart } from '../BusinessCart'
|
|
11
|
+
import { OIcon } from '../shared';
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
Container,
|
|
15
|
+
ItemListing,
|
|
16
|
+
TopHeader,
|
|
17
|
+
HeaderItem
|
|
18
|
+
} from './styles';
|
|
19
|
+
|
|
20
|
+
const CartStoresListingUI = (props: any) => {
|
|
21
|
+
const {
|
|
22
|
+
businessIdSelect,
|
|
23
|
+
storesState,
|
|
24
|
+
changeStoreState,
|
|
25
|
+
handleCartStoreChange,
|
|
26
|
+
} = props
|
|
27
|
+
|
|
28
|
+
const [, t] = useLanguage()
|
|
29
|
+
const theme = useTheme();
|
|
30
|
+
const [orderState] = useOrder()
|
|
31
|
+
const business: any = (orderState?.carts && Object.values(orderState.carts).find((_cart: any) => _cart?.uuid === props.cartuuid)) ?? {}
|
|
32
|
+
const businessId = business?.business_id ?? null
|
|
33
|
+
|
|
34
|
+
return(
|
|
35
|
+
<>
|
|
36
|
+
<TopHeader>
|
|
37
|
+
<HeaderItem
|
|
38
|
+
onPress={props.onClose}>
|
|
39
|
+
<OIcon src={theme.images.general.close} width={16} />
|
|
40
|
+
</HeaderItem>
|
|
41
|
+
</TopHeader>
|
|
42
|
+
<Container>
|
|
43
|
+
{!storesState?.loading && !storesState?.error && storesState?.result && (
|
|
44
|
+
<>
|
|
45
|
+
{storesState?.result?.length > 0 ? (
|
|
46
|
+
<ItemListing
|
|
47
|
+
horizontal={false}
|
|
48
|
+
>
|
|
49
|
+
{storesState?.result.map((store: any) => (
|
|
50
|
+
<BusinessCart
|
|
51
|
+
key={store.id}
|
|
52
|
+
business={store}
|
|
53
|
+
isLoading={changeStoreState.loading && businessIdSelect === store.id}
|
|
54
|
+
isDisabled={(changeStoreState?.result?.business_id ?? businessId) === store.id}
|
|
55
|
+
handleCartStoreClick={handleCartStoreChange}
|
|
56
|
+
/>
|
|
57
|
+
))}
|
|
58
|
+
</ItemListing>
|
|
59
|
+
) : (
|
|
60
|
+
<NotFoundSource
|
|
61
|
+
content={t('NOT_FOUND_CART_STORES', 'No businesses to show at this time.')}
|
|
62
|
+
/>
|
|
63
|
+
)}
|
|
64
|
+
</>
|
|
65
|
+
)}
|
|
66
|
+
|
|
67
|
+
{storesState?.loading && (
|
|
68
|
+
<ItemListing>
|
|
69
|
+
{[...Array(8).keys()].map(i => (
|
|
70
|
+
<BusinessCart
|
|
71
|
+
key={i}
|
|
72
|
+
business={{}}
|
|
73
|
+
isSkeleton
|
|
74
|
+
/>
|
|
75
|
+
))}
|
|
76
|
+
</ItemListing>
|
|
77
|
+
)}
|
|
78
|
+
|
|
79
|
+
{!storesState?.loading && storesState?.error && (
|
|
80
|
+
<NotFoundSource
|
|
81
|
+
content={t('ERROR_NOT_FOUND_CART_STORES', 'Sorry, an error has occurred')}
|
|
82
|
+
/>
|
|
83
|
+
)}
|
|
84
|
+
</Container>
|
|
85
|
+
</>
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const CartStoresListing = (props: any) => {
|
|
90
|
+
const storeProps = {
|
|
91
|
+
...props,
|
|
92
|
+
UIComponent: CartStoresListingUI
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<StoresListingController {...storeProps} />
|
|
97
|
+
)
|
|
98
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import styled from 'styled-components/native'
|
|
2
|
+
|
|
3
|
+
export const Container = styled.View`
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
justify-content: center;
|
|
7
|
+
flex-direction: row;
|
|
8
|
+
width: 100%;
|
|
9
|
+
`
|
|
10
|
+
|
|
11
|
+
export const ItemListing = styled.ScrollView`
|
|
12
|
+
padding: 0 40px;
|
|
13
|
+
margin: 0 0 140px;
|
|
14
|
+
`
|
|
15
|
+
|
|
16
|
+
export const TopHeader = styled.View`
|
|
17
|
+
width: 100%;
|
|
18
|
+
flex-direction: row;
|
|
19
|
+
align-items: center;
|
|
20
|
+
justify-content: space-between;
|
|
21
|
+
z-index: 1;
|
|
22
|
+
padding: 0 40px;
|
|
23
|
+
`
|
|
24
|
+
|
|
25
|
+
export const HeaderItem = styled.TouchableOpacity`
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
background-color: ${(props: any) => props.theme.colors.clear};
|
|
28
|
+
width: 35px;
|
|
29
|
+
margin: 18px 0;
|
|
30
|
+
`
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import { View, StyleSheet,
|
|
2
|
+
import { View, StyleSheet, TouchableOpacity, Platform, I18nManager } from 'react-native';
|
|
3
3
|
import { initStripe, useConfirmPayment } from '@stripe/stripe-react-native';
|
|
4
|
-
|
|
4
|
+
import Picker from 'react-native-country-picker-modal';
|
|
5
|
+
import MaterialIcons from 'react-native-vector-icons/MaterialIcons'
|
|
5
6
|
import {
|
|
6
7
|
Checkout as CheckoutController,
|
|
7
8
|
useOrder,
|
|
@@ -15,14 +16,13 @@ import {
|
|
|
15
16
|
ToastType,
|
|
16
17
|
} from 'ordering-components/native';
|
|
17
18
|
import { useTheme } from 'styled-components/native';
|
|
18
|
-
import { OText, OIcon } from '../shared';
|
|
19
|
+
import { OText, OIcon, OModal } from '../shared';
|
|
19
20
|
|
|
20
21
|
import { AddressDetails } from '../AddressDetails';
|
|
21
22
|
import { PaymentOptions } from '../PaymentOptions';
|
|
22
23
|
import { DriverTips } from '../DriverTips';
|
|
23
24
|
import { NotFoundSource } from '../NotFoundSource';
|
|
24
25
|
import { UserDetails } from '../UserDetails';
|
|
25
|
-
import { OrderTypeSelector } from '../OrderTypeSelector'
|
|
26
26
|
|
|
27
27
|
import {
|
|
28
28
|
ChContainer,
|
|
@@ -35,7 +35,9 @@ import {
|
|
|
35
35
|
ChErrors,
|
|
36
36
|
ChBusinessDetails,
|
|
37
37
|
ChUserDetails,
|
|
38
|
-
ChCart
|
|
38
|
+
ChCart,
|
|
39
|
+
DeliveryOptionsContainer,
|
|
40
|
+
DeliveryOptionItem
|
|
39
41
|
} from './styles';
|
|
40
42
|
import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
|
|
41
43
|
|
|
@@ -44,6 +46,7 @@ import { Container } from '../../layouts/Container';
|
|
|
44
46
|
import NavBar from '../NavBar';
|
|
45
47
|
import { OrderSummary } from '../OrderSummary';
|
|
46
48
|
import { getTypesText } from '../../utils';
|
|
49
|
+
import { CartStoresListing } from '../CartStoresListing';
|
|
47
50
|
|
|
48
51
|
const mapConfigs = {
|
|
49
52
|
mapZoom: 16,
|
|
@@ -69,14 +72,15 @@ const CheckoutUI = (props: any) => {
|
|
|
69
72
|
errors,
|
|
70
73
|
placing,
|
|
71
74
|
cartState,
|
|
75
|
+
cartUuid,
|
|
72
76
|
businessDetails,
|
|
73
77
|
paymethodSelected,
|
|
74
78
|
handlePaymethodChange,
|
|
75
79
|
handlerClickPlaceOrder,
|
|
76
80
|
onNavigationRedirect,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
deliveryOptionSelected,
|
|
82
|
+
instructionsOptions,
|
|
83
|
+
handleChangeDeliveryOption,
|
|
80
84
|
} = props
|
|
81
85
|
|
|
82
86
|
const theme = useTheme();
|
|
@@ -91,9 +95,18 @@ const CheckoutUI = (props: any) => {
|
|
|
91
95
|
justifyContent: 'flex-start',
|
|
92
96
|
paddingLeft: 0,
|
|
93
97
|
},
|
|
98
|
+
paddSection: {
|
|
99
|
+
padding: 20
|
|
100
|
+
},
|
|
94
101
|
pagePadding: {
|
|
95
102
|
paddingLeft: 40,
|
|
96
103
|
paddingRight: 40
|
|
104
|
+
},
|
|
105
|
+
icon: {
|
|
106
|
+
top: 15,
|
|
107
|
+
right: Platform.OS === 'ios' ? 5 : (I18nManager.isRTL ? 30 : 0),
|
|
108
|
+
position: 'absolute',
|
|
109
|
+
fontSize: 20
|
|
97
110
|
}
|
|
98
111
|
})
|
|
99
112
|
|
|
@@ -109,6 +122,8 @@ const CheckoutUI = (props: any) => {
|
|
|
109
122
|
const [userErrors, setUserErrors] = useState<any>([]);
|
|
110
123
|
const [isUserDetailsEdit, setIsUserDetailsEdit] = useState(false);
|
|
111
124
|
const [phoneUpdate, setPhoneUpdate] = useState(false);
|
|
125
|
+
const [openChangeStore, setOpenChangeStore] = useState(false)
|
|
126
|
+
const [isDeliveryOptionModalVisible, setIsDeliveryOptionModalVisible] = useState(false)
|
|
112
127
|
|
|
113
128
|
const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
|
|
114
129
|
? JSON.parse(configs?.driver_tip_options?.value) || []
|
|
@@ -118,6 +133,12 @@ const CheckoutUI = (props: any) => {
|
|
|
118
133
|
|
|
119
134
|
const cartsWithProducts = carts && Object.values(carts).filter((cart: any) => cart.products.length) || null
|
|
120
135
|
|
|
136
|
+
const deliveryOptions = instructionsOptions?.result && instructionsOptions?.result?.filter((option: any) => option?.enabled)?.map((option: any) => {
|
|
137
|
+
return {
|
|
138
|
+
value: option?.id, key: option?.id, label: option?.name
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
|
|
121
142
|
const handlePlaceOrder = () => {
|
|
122
143
|
if (!userErrors.length) {
|
|
123
144
|
handlerClickPlaceOrder && handlerClickPlaceOrder()
|
|
@@ -131,6 +152,11 @@ const CheckoutUI = (props: any) => {
|
|
|
131
152
|
setIsUserDetailsEdit(true)
|
|
132
153
|
}
|
|
133
154
|
|
|
155
|
+
const changeDeliveryOption = (option: any) => {
|
|
156
|
+
handleChangeDeliveryOption(option)
|
|
157
|
+
setIsDeliveryOptionModalVisible(false)
|
|
158
|
+
}
|
|
159
|
+
|
|
134
160
|
const checkValidationFields = () => {
|
|
135
161
|
setUserErrors([])
|
|
136
162
|
const errors = []
|
|
@@ -307,7 +333,56 @@ const CheckoutUI = (props: any) => {
|
|
|
307
333
|
<View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100, marginHorizontal: -40 }} />
|
|
308
334
|
</ChSection>
|
|
309
335
|
|
|
310
|
-
|
|
336
|
+
{!cartState.loading && deliveryOptionSelected !== undefined && options?.type === 1 && (
|
|
337
|
+
<DeliveryOptionsContainer>
|
|
338
|
+
<OText size={16}>{t('DELIVERY_OPTIONS', 'Delivery options')}</OText>
|
|
339
|
+
<View
|
|
340
|
+
style={{
|
|
341
|
+
backgroundColor: theme.colors.inputDisabled,
|
|
342
|
+
borderRadius: 7.5,
|
|
343
|
+
marginBottom: 20,
|
|
344
|
+
flex: 1
|
|
345
|
+
}}>
|
|
346
|
+
<Picker
|
|
347
|
+
countryCode={undefined}
|
|
348
|
+
visible={isDeliveryOptionModalVisible}
|
|
349
|
+
onClose={() => setIsDeliveryOptionModalVisible(false)}
|
|
350
|
+
withCountryNameButton
|
|
351
|
+
renderFlagButton={() => (
|
|
352
|
+
<TouchableOpacity onPress={() => setIsDeliveryOptionModalVisible(true)}>
|
|
353
|
+
<DeliveryOptionItem backgroundColor={theme?.colors?.inputDisabled}>
|
|
354
|
+
<OText
|
|
355
|
+
size={14}
|
|
356
|
+
>
|
|
357
|
+
{deliveryOptions.find((option: any) => option.value === deliveryOptionSelected).label}
|
|
358
|
+
</OText>
|
|
359
|
+
<MaterialIcons name='keyboard-arrow-down' style={styles.icon} />
|
|
360
|
+
</DeliveryOptionItem>
|
|
361
|
+
</TouchableOpacity>
|
|
362
|
+
)}
|
|
363
|
+
flatListProps={{
|
|
364
|
+
keyExtractor: (item: any) => item.value,
|
|
365
|
+
data: deliveryOptions || [],
|
|
366
|
+
renderItem: ({ item }: any) => (
|
|
367
|
+
<TouchableOpacity
|
|
368
|
+
onPress={() => changeDeliveryOption(item.value)}
|
|
369
|
+
disabled={
|
|
370
|
+
deliveryOptionSelected === item.value
|
|
371
|
+
}
|
|
372
|
+
>
|
|
373
|
+
<DeliveryOptionItem backgroundColor={deliveryOptionSelected === item.value ? theme.colors.inputDisabled : 'white'}>
|
|
374
|
+
<OText>
|
|
375
|
+
{item.label}
|
|
376
|
+
</OText>
|
|
377
|
+
</DeliveryOptionItem>
|
|
378
|
+
</TouchableOpacity>
|
|
379
|
+
)
|
|
380
|
+
}}
|
|
381
|
+
/>
|
|
382
|
+
</View>
|
|
383
|
+
<View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100, marginHorizontal: -40 }} />
|
|
384
|
+
</DeliveryOptionsContainer>
|
|
385
|
+
)}
|
|
311
386
|
|
|
312
387
|
{!cartState.loading && (cart?.status === 2 || cart?.status === 4) && (
|
|
313
388
|
<ChSection style={{ paddingBottom: 20 }}>
|
|
@@ -361,7 +436,7 @@ const CheckoutUI = (props: any) => {
|
|
|
361
436
|
location={businessDetails?.business?.location}
|
|
362
437
|
businessLogo={businessDetails?.business?.logo}
|
|
363
438
|
isCartPending={cart?.status === 2}
|
|
364
|
-
|
|
439
|
+
uuid={cartUuid}
|
|
365
440
|
apiKey={configs?.google_maps_api_key?.value}
|
|
366
441
|
mapConfigs={mapConfigs}
|
|
367
442
|
/>
|
|
@@ -384,6 +459,7 @@ const CheckoutUI = (props: any) => {
|
|
|
384
459
|
{t('DRIVER_TIPS', 'Driver Tips')}
|
|
385
460
|
</OText>
|
|
386
461
|
<DriverTips
|
|
462
|
+
uuid={cartUuid}
|
|
387
463
|
businessId={cart?.business_id}
|
|
388
464
|
driverTipsOptions={driverTipsOptions}
|
|
389
465
|
isFixedPrice={parseInt(configs?.driver_tip_type?.value, 10) === 1 || !!parseInt(configs?.driver_tip_use_custom?.value, 10)}
|
|
@@ -429,27 +505,42 @@ const CheckoutUI = (props: any) => {
|
|
|
429
505
|
)}
|
|
430
506
|
|
|
431
507
|
{!cartState.loading && cart && (
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
508
|
+
<ChSection>
|
|
509
|
+
<ChCart>
|
|
510
|
+
{cartsWithProducts && cart?.products?.length === 0 ? (
|
|
511
|
+
<NotFoundSource
|
|
512
|
+
content={t('NOT_FOUND_CARTS', 'Sorry, You don\'t seem to have any carts.')}
|
|
513
|
+
btnTitle={t('SEARCH_REDIRECT', 'Go to Businesses')}
|
|
514
|
+
/>
|
|
515
|
+
) : (
|
|
516
|
+
<>
|
|
517
|
+
<OText size={16} lineHeight={24} color={theme.colors.textNormal}>
|
|
518
|
+
{t('ORDER_SUMMARY', 'Order Summary')}
|
|
519
|
+
</OText>
|
|
520
|
+
{props.isFranchiseApp && (
|
|
521
|
+
<TouchableOpacity
|
|
522
|
+
onPress={() => setOpenChangeStore(true)}
|
|
523
|
+
style={{alignSelf: 'flex-start'}}
|
|
524
|
+
>
|
|
525
|
+
<OText
|
|
526
|
+
size={12}
|
|
527
|
+
lineHeight={18}
|
|
528
|
+
color={theme.colors.textSecondary}
|
|
529
|
+
style={{ textDecorationLine: 'underline' }}
|
|
530
|
+
>
|
|
531
|
+
{t('CHANGE_STORE', 'Change store')}
|
|
532
|
+
</OText>
|
|
533
|
+
</TouchableOpacity>
|
|
534
|
+
)}
|
|
535
|
+
<OrderSummary
|
|
536
|
+
cart={cart}
|
|
537
|
+
isCartPending={cart?.status === 2}
|
|
538
|
+
/>
|
|
539
|
+
</>
|
|
540
|
+
)}
|
|
541
|
+
</ChCart>
|
|
542
|
+
</ChSection>
|
|
543
|
+
)}
|
|
453
544
|
|
|
454
545
|
{!cartState.loading && cart && (
|
|
455
546
|
<ChSection style={{ paddingTop: 0, paddingBottom: 20, paddingHorizontal: 20 }}>
|
|
@@ -483,6 +574,17 @@ const CheckoutUI = (props: any) => {
|
|
|
483
574
|
</ChErrors>
|
|
484
575
|
</ChSection>
|
|
485
576
|
)}
|
|
577
|
+
<OModal
|
|
578
|
+
open={openChangeStore && props.isFranchiseApp}
|
|
579
|
+
entireModal
|
|
580
|
+
customClose
|
|
581
|
+
onClose={() => setOpenChangeStore(false)}
|
|
582
|
+
>
|
|
583
|
+
<CartStoresListing
|
|
584
|
+
cartuuid={cart?.uuid}
|
|
585
|
+
onClose={() => setOpenChangeStore(false)}
|
|
586
|
+
/>
|
|
587
|
+
</OModal>
|
|
486
588
|
</ChContainer>
|
|
487
589
|
</Container>
|
|
488
590
|
{!cartState.loading && cart && cart?.status !== 2 && (
|
|
@@ -660,7 +762,7 @@ export const Checkout = (props: any) => {
|
|
|
660
762
|
...props,
|
|
661
763
|
UIComponent: CheckoutUI,
|
|
662
764
|
cartState,
|
|
663
|
-
|
|
765
|
+
[props.isFranchiseApp ? 'uuid' : 'businessId']: props.isFranchiseApp ? cartUuid : cartState.cart?.business_id
|
|
664
766
|
}
|
|
665
767
|
|
|
666
768
|
return (
|
|
@@ -87,3 +87,16 @@ export const ChErrors = styled.View`
|
|
|
87
87
|
align-items: center;
|
|
88
88
|
margin-bottom: 20px;
|
|
89
89
|
`
|
|
90
|
+
|
|
91
|
+
export const DeliveryOptionsContainer = styled.View`
|
|
92
|
+
flex: 1;
|
|
93
|
+
margin-top: 10px;
|
|
94
|
+
`
|
|
95
|
+
|
|
96
|
+
export const DeliveryOptionItem = styled.View`
|
|
97
|
+
padding: 15px;
|
|
98
|
+
justify-content: ${(props : any) => props.center ? 'center' : 'space-between'};
|
|
99
|
+
align-items: center;
|
|
100
|
+
flex-direction: row;
|
|
101
|
+
background-color: ${(props : any) => props?.backgroundColor ?? '#fff'};
|
|
102
|
+
`;
|
|
@@ -597,6 +597,22 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
597
597
|
</OText>
|
|
598
598
|
</InfoBlock>
|
|
599
599
|
</Customer>
|
|
600
|
+
{order?.delivery_option !== undefined && order?.delivery_type === 1 && (
|
|
601
|
+
<View style={{ marginTop: 15 }}>
|
|
602
|
+
<OText size={16} style={{ textAlign: 'left' }} color={theme.colors.textNormal}>
|
|
603
|
+
{t('DELIVERY_PREFERENCE', 'Delivery Preference')}
|
|
604
|
+
</OText>
|
|
605
|
+
<OText size={12} style={{ textAlign: 'left' }} color={theme.colors.textNormal}>{order?.delivery_option?.name ?? t('EITHER_WAY', 'Either way')}</OText>
|
|
606
|
+
</View>
|
|
607
|
+
)}
|
|
608
|
+
{order?.comment && (
|
|
609
|
+
<View style={{ marginTop: 15 }}>
|
|
610
|
+
<OText size={16} style={{ textAlign: 'left' }} color={theme.colors.textNormal}>
|
|
611
|
+
{t('COMMENT', 'Comment')}
|
|
612
|
+
</OText>
|
|
613
|
+
<OText size={12} style={{ textAlign: 'left' }} color={theme.colors.textNormal}>{order?.comment}</OText>
|
|
614
|
+
</View>
|
|
615
|
+
)}
|
|
600
616
|
{order?.driver && (
|
|
601
617
|
<>
|
|
602
618
|
{order?.driver?.location && parseInt(order?.status) === 9 && (
|
|
@@ -810,14 +826,6 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
810
826
|
</OText>
|
|
811
827
|
</Table>
|
|
812
828
|
</Total>
|
|
813
|
-
{order?.comment && (
|
|
814
|
-
<Table>
|
|
815
|
-
<OText style={{ flex: 1 }}>{t('COMMENT', 'Comment')}</OText>
|
|
816
|
-
<OText style={{ maxWidth: '70%' }}>
|
|
817
|
-
{order?.comment}
|
|
818
|
-
</OText>
|
|
819
|
-
</Table>
|
|
820
|
-
)}
|
|
821
829
|
</OrderBill>
|
|
822
830
|
</OrderContent>
|
|
823
831
|
</>
|
|
@@ -109,7 +109,7 @@ export const OrderBill = styled.View`
|
|
|
109
109
|
export const Total = styled.View`
|
|
110
110
|
border-top-width: 1px;
|
|
111
111
|
border-top-color: ${(props: any) => props.theme.colors.border};
|
|
112
|
-
padding-vertical: 10px
|
|
112
|
+
padding-vertical: 10px;
|
|
113
113
|
`
|
|
114
114
|
|
|
115
115
|
export const Map = styled.View`
|
|
@@ -128,6 +128,7 @@ export interface BusinessesListingParams {
|
|
|
128
128
|
images?: any;
|
|
129
129
|
businessTypes?: any;
|
|
130
130
|
defaultBusinessType?: any;
|
|
131
|
+
franchiseId?: any;
|
|
131
132
|
}
|
|
132
133
|
export interface HighestRatedBusinessesParams {
|
|
133
134
|
businessesList: { businesses: Array<any>, loading: boolean, error: null | string };
|
|
@@ -472,4 +473,4 @@ export interface HelpAccountAndPaymentParams {
|
|
|
472
473
|
|
|
473
474
|
export interface MessageListingParams {
|
|
474
475
|
navigation: any;
|
|
475
|
-
}
|
|
476
|
+
}
|