ordering-ui-react-native 0.18.38 → 0.18.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/themes/business/src/components/DriverMap/index.tsx +1 -1
- package/themes/original/src/components/AddressForm/index.tsx +7 -4
- package/themes/original/src/components/AddressList/index.tsx +1 -1
- package/themes/original/src/components/BusinessBasicInformation/index.tsx +18 -3
- package/themes/original/src/components/BusinessBasicInformation/styles.tsx +0 -3
- package/themes/original/src/components/BusinessController/index.tsx +3 -3
- package/themes/original/src/components/BusinessListingSearch/index.tsx +331 -276
- package/themes/original/src/components/BusinessProductsList/index.tsx +3 -3
- package/themes/original/src/components/BusinessProductsListing/UpsellingRedirect.tsx +1 -1
- package/themes/original/src/components/BusinessProductsListing/index.tsx +49 -8
- package/themes/original/src/components/CartContent/index.tsx +56 -14
- package/themes/original/src/components/CartContent/styles.tsx +4 -0
- package/themes/original/src/components/Checkout/index.tsx +6 -5
- package/themes/original/src/components/GoogleMap/index.tsx +11 -2
- package/themes/original/src/components/LoginForm/index.tsx +15 -14
- package/themes/original/src/components/MultiCheckout/index.tsx +6 -5
- package/themes/original/src/components/MyOrders/index.tsx +14 -1
- package/themes/original/src/components/NavBar/index.tsx +9 -4
- package/themes/original/src/components/OrderSummary/index.tsx +4 -2
- package/themes/original/src/components/OrdersOption/index.tsx +3 -1
- package/themes/original/src/components/ProductForm/index.tsx +23 -11
- package/themes/original/src/components/ProductOptionSubOption/index.tsx +7 -5
- package/themes/original/src/components/ProductOptionSubOption/styles.tsx +2 -2
- package/themes/original/src/components/SignupForm/index.tsx +14 -14
- package/themes/original/src/components/SingleOrderCard/index.tsx +7 -1
- package/themes/original/src/components/StripeElementsForm/index.tsx +17 -16
- package/themes/original/src/components/UserFormDetails/index.tsx +34 -5
- package/themes/original/src/components/UserProfile/index.tsx +2 -20
- package/themes/original/src/components/UserProfileForm/index.tsx +7 -2
- package/themes/original/src/components/WalletTransactions/index.tsx +3 -3
- package/themes/original/src/components/Wallets/index.tsx +4 -4
- package/themes/original/src/types/index.tsx +2 -2
- package/themes/original/src/utils/index.tsx +11 -0
|
@@ -106,7 +106,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
|
|
|
106
106
|
<SingleProductCard
|
|
107
107
|
key={'prod_' + product.id + `_${i}`}
|
|
108
108
|
isSoldOut={product.inventoried && !product.quantity}
|
|
109
|
-
enableIntersection={!isFiltMode
|
|
109
|
+
enableIntersection={!isFiltMode}
|
|
110
110
|
product={product}
|
|
111
111
|
businessId={businessId}
|
|
112
112
|
categoryState={categoryState}
|
|
@@ -135,7 +135,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
|
|
|
135
135
|
key={'feat_' + product.id + `_${i}`}
|
|
136
136
|
isSoldOut={product.inventoried && !product.quantity}
|
|
137
137
|
product={product}
|
|
138
|
-
enableIntersection={!isFiltMode
|
|
138
|
+
enableIntersection={!isFiltMode}
|
|
139
139
|
businessId={businessId}
|
|
140
140
|
categoryState={categoryState}
|
|
141
141
|
onProductClick={onProductClick}
|
|
@@ -237,7 +237,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
|
|
|
237
237
|
{products.sort((a: any, b: any) => a.rank - b.rank).map((product: any, i: any) => (
|
|
238
238
|
<SingleProductCard
|
|
239
239
|
key={`${product?.id}_${i}`}
|
|
240
|
-
enableIntersection={!isFiltMode
|
|
240
|
+
enableIntersection={!isFiltMode}
|
|
241
241
|
isSoldOut={product.inventoried && !product.quantity}
|
|
242
242
|
businessId={businessId}
|
|
243
243
|
product={product}
|
|
@@ -13,7 +13,7 @@ const UpsellingRedirectUI = (props: any) => {
|
|
|
13
13
|
if (!upsellingProducts.loading) {
|
|
14
14
|
if (upsellingProducts?.products?.length) {
|
|
15
15
|
onRedirect &&
|
|
16
|
-
onRedirect('UpsellingPage', props)
|
|
16
|
+
onRedirect('UpsellingPage', {...props, products: upsellingProducts?.products })
|
|
17
17
|
} else {
|
|
18
18
|
handleUpsellingPage && handleUpsellingPage()
|
|
19
19
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
|
2
|
-
import { View, TouchableOpacity, StyleSheet, SafeAreaView, Dimensions, Platform, KeyboardAvoidingViewBase, KeyboardAvoidingView,
|
|
2
|
+
import { View, TouchableOpacity, StyleSheet, SafeAreaView, Dimensions, Platform, KeyboardAvoidingViewBase, KeyboardAvoidingView, Keyboard, KeyboardEvent, BackHandler } from 'react-native'
|
|
3
3
|
import { IOScrollView } from 'react-native-intersection-observer'
|
|
4
4
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
5
5
|
import { useTheme } from 'styled-components/native';
|
|
@@ -25,6 +25,7 @@ import { BusinessProductsListingParams } from '../../types'
|
|
|
25
25
|
import { _retrieveStoreData, _removeStoreData } from '../../providers/StoreUtil';
|
|
26
26
|
import IconAntDesign from 'react-native-vector-icons/AntDesign';
|
|
27
27
|
import { useIsFocused } from '@react-navigation/native';
|
|
28
|
+
import AntDesignIcon from 'react-native-vector-icons/AntDesign'
|
|
28
29
|
|
|
29
30
|
import {
|
|
30
31
|
TopHeader,
|
|
@@ -43,6 +44,7 @@ import { ProfessionalFilter } from '../ProfessionalFilter';
|
|
|
43
44
|
import { ServiceForm } from '../ServiceForm';
|
|
44
45
|
import { BusinessesListing } from '../BusinessesListing/Layout/Original'
|
|
45
46
|
import { PageBanner } from '../PageBanner'
|
|
47
|
+
import { vibrateApp } from '../../utils';
|
|
46
48
|
|
|
47
49
|
const PIXELS_TO_SCROLL = 2000
|
|
48
50
|
|
|
@@ -135,20 +137,23 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
135
137
|
const [openService, setOpenService] = useState(false)
|
|
136
138
|
const [currentProduct, setCurrentProduct] = useState(null)
|
|
137
139
|
const [searchBarHeight, setSearchBarHeight] = useState(60)
|
|
140
|
+
const [keyboardHeight, setKeyboardHeight] = useState(0);
|
|
138
141
|
const [viewedCategory, setViewedCategory] = useState<any>(null)
|
|
142
|
+
const [showTitle, setShowTitle] = useState(false)
|
|
139
143
|
|
|
140
144
|
const isCheckoutMultiBusinessEnabled: Boolean = configs?.checkout_multi_business_enabled?.value === '1'
|
|
141
145
|
const isQuickAddProduct = configs?.add_product_with_one_click?.value === '1'
|
|
142
146
|
const openCarts = (Object.values(orderState?.carts)?.filter((cart: any) => cart?.products && cart?.products?.length && cart?.status !== 2 && cart?.valid_schedule && cart?.valid_products && cart?.valid_address && cart?.valid_maximum && cart?.valid_minimum && !cart?.wallets) || null) || []
|
|
143
|
-
|
|
144
147
|
const currentCart: any = Object.values(orderState.carts).find((cart: any) => cart?.business?.slug === business?.slug) ?? {}
|
|
145
148
|
const isOpenFiltProducts = isOpenSearchBar && !!searchValue
|
|
146
149
|
const filtProductsHeight = Platform.OS === 'ios' ? 165 : 100
|
|
150
|
+
const viewOrderButtonVisible = !loading && auth && currentCart?.products?.length > 0 && categoryState.products.length !== 0
|
|
151
|
+
|
|
147
152
|
const onRedirect = (route: string, params?: any) => {
|
|
148
153
|
navigation.navigate(route, params)
|
|
149
154
|
}
|
|
150
155
|
const onProductClick = async (product: any) => {
|
|
151
|
-
if (product.extras.length === 0 && !product.inventoried && auth && isQuickAddProduct) {
|
|
156
|
+
if (product.ingredients?.length === 0 && product.extras.length === 0 && !product.inventoried && auth && isQuickAddProduct) {
|
|
152
157
|
const isProductAddedToCart = currentCart?.products?.find((Cproduct: any) => Cproduct.id === product.id)
|
|
153
158
|
const productQuantity = isProductAddedToCart?.quantity
|
|
154
159
|
const addCurrentProduct = {
|
|
@@ -156,11 +161,12 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
156
161
|
quantity: 1
|
|
157
162
|
}
|
|
158
163
|
const updateCurrentProduct = {
|
|
164
|
+
name: product?.name,
|
|
159
165
|
id: product.id,
|
|
160
166
|
code: isProductAddedToCart?.code,
|
|
161
167
|
quantity: productQuantity + 1
|
|
162
168
|
}
|
|
163
|
-
|
|
169
|
+
vibrateApp()
|
|
164
170
|
const cartData = currentCart?.business_id ? currentCart : { business_id: business.id }
|
|
165
171
|
if (isProductAddedToCart) {
|
|
166
172
|
await updateProduct(updateCurrentProduct, cartData, isQuickAddProduct)
|
|
@@ -239,6 +245,8 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
239
245
|
|
|
240
246
|
const handlePageScroll = useCallback(({ nativeEvent }: any) => {
|
|
241
247
|
const scrollOffset = nativeEvent.contentOffset.y
|
|
248
|
+
setShowTitle(scrollOffset > 30)
|
|
249
|
+
|
|
242
250
|
if (businessState?.business?.lazy_load_products_recommended) {
|
|
243
251
|
const height = nativeEvent.contentSize.height
|
|
244
252
|
const hasMore = !(categoryState.pagination.totalPages === categoryState.pagination.currentPage)
|
|
@@ -307,6 +315,24 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
307
315
|
}
|
|
308
316
|
}, [isFocused])
|
|
309
317
|
|
|
318
|
+
|
|
319
|
+
useEffect(() => {
|
|
320
|
+
function onKeyboardDidShow(e: KeyboardEvent) {
|
|
321
|
+
setKeyboardHeight(e?.endCoordinates?.height);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function onKeyboardDidHide() {
|
|
325
|
+
setKeyboardHeight(0);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const showSubscription = Keyboard.addListener('keyboardDidShow', onKeyboardDidShow);
|
|
329
|
+
const hideSubscription = Keyboard.addListener('keyboardDidHide', onKeyboardDidHide);
|
|
330
|
+
return () => {
|
|
331
|
+
showSubscription.remove();
|
|
332
|
+
hideSubscription.remove();
|
|
333
|
+
};
|
|
334
|
+
}, []);
|
|
335
|
+
|
|
310
336
|
const subtotalWithTaxes = currentCart?.taxes?.reduce((acc: any, item: any) => {
|
|
311
337
|
if (item?.type === 1)
|
|
312
338
|
return acc = acc + item?.summary?.tax
|
|
@@ -369,9 +395,23 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
369
395
|
<>
|
|
370
396
|
{!(businessSingleId && auth) && (
|
|
371
397
|
<TopActions onPress={() => handleBackNavigation()}>
|
|
372
|
-
<
|
|
398
|
+
<AntDesignIcon
|
|
399
|
+
name='arrowleft'
|
|
400
|
+
size={26}
|
|
401
|
+
/>
|
|
373
402
|
</TopActions>
|
|
374
403
|
)}
|
|
404
|
+
{showTitle && (
|
|
405
|
+
<OText
|
|
406
|
+
size={16}
|
|
407
|
+
style={{ flex: 1, textAlign: 'center' }}
|
|
408
|
+
weight={Platform.OS === 'ios' ? '600' : 'bold'}
|
|
409
|
+
numberOfLines={2}
|
|
410
|
+
ellipsizeMode='tail'
|
|
411
|
+
>
|
|
412
|
+
{business?.name}
|
|
413
|
+
</OText>
|
|
414
|
+
)}
|
|
375
415
|
{!errorQuantityProducts && (
|
|
376
416
|
<View style={{ ...styles.headerItem }}>
|
|
377
417
|
<TouchableOpacity
|
|
@@ -427,8 +467,8 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
427
467
|
{business?.categories?.length > 0 && isOpenFiltProducts && (
|
|
428
468
|
<FiltProductsContainer
|
|
429
469
|
style={{
|
|
430
|
-
height: Dimensions.get('window').height - filtProductsHeight,
|
|
431
|
-
top: Platform.OS === 'ios' ? (searchBarHeight - 10) + insets.top : searchBarHeight
|
|
470
|
+
height: Dimensions.get('window').height - filtProductsHeight - keyboardHeight - (keyboardHeight > 0 && viewOrderButtonVisible ? 55 : 0),
|
|
471
|
+
top: Platform.OS === 'ios' ? (searchBarHeight - 10) + insets.top : searchBarHeight,
|
|
432
472
|
}}
|
|
433
473
|
contentContainerStyle={{ flexGrow: 1 }}
|
|
434
474
|
>
|
|
@@ -593,7 +633,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
593
633
|
</>
|
|
594
634
|
)}
|
|
595
635
|
</IOScrollView>
|
|
596
|
-
{
|
|
636
|
+
{viewOrderButtonVisible && (
|
|
597
637
|
<View style={{ marginBottom: 0 }}>
|
|
598
638
|
<FloatingButton
|
|
599
639
|
btnText={
|
|
@@ -649,6 +689,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
649
689
|
professionalList={business?.professionals}
|
|
650
690
|
professionalSelected={professionalSelected}
|
|
651
691
|
handleChangeProfessional={handleChangeProfessionalSelected}
|
|
692
|
+
handleChangeProfessional={handleChangeProfessionalSelected}
|
|
652
693
|
handleUpdateProfessionals={handleUpdateProfessionals}
|
|
653
694
|
onSave={() => setOpenService(false)}
|
|
654
695
|
onClose={() => setOpenService(false)}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
|
-
import { useLanguage, useConfig } from 'ordering-components/native';
|
|
3
|
+
import { useLanguage, useConfig, useUtils } from 'ordering-components/native';
|
|
4
4
|
import { useTheme } from 'styled-components/native';
|
|
5
|
-
import { CCContainer, CCNotCarts, CCList, CheckoutAction } from './styles';
|
|
5
|
+
import { CCContainer, CCNotCarts, CCList, CheckoutAction, ChCartsTotal } from './styles';
|
|
6
6
|
|
|
7
7
|
import { Cart } from '../Cart';
|
|
8
8
|
import { OButton, OText } from '../shared';
|
|
@@ -19,12 +19,18 @@ export const CartContent = (props: any) => {
|
|
|
19
19
|
const theme = useTheme();
|
|
20
20
|
const [, t] = useLanguage()
|
|
21
21
|
const [{ configs }] = useConfig()
|
|
22
|
+
const [{ parsePrice }] = useUtils();
|
|
22
23
|
const [isCartsLoading, setIsCartsLoading] = useState(false)
|
|
23
24
|
|
|
24
25
|
const isChewLayout = theme?.header?.components?.layout?.type === 'chew'
|
|
25
26
|
const isMultiCheckout = configs?.checkout_multi_business_enabled?.value === '1'
|
|
26
27
|
const cartsAvailable: any = Object.values(carts)?.filter((cart: any) => cart?.valid && cart?.status !== 2)
|
|
27
28
|
|
|
29
|
+
const totalCartsPrice = cartsAvailable?.length && cartsAvailable.reduce((total: any, cart: any) => { return total + cart?.total }, 0)
|
|
30
|
+
const totalCartsFee = cartsAvailable?.length && cartsAvailable
|
|
31
|
+
?.filter((cart: any) => cart?.status !== 1 && cart?.valid && cart?.products?.length)
|
|
32
|
+
?.reduce((total: any, cart: any) => { return total + (cart?.delivery_price_with_discount) }, 0)
|
|
33
|
+
|
|
28
34
|
const handleCheckoutRedirect = () => {
|
|
29
35
|
if (cartsAvailable.length === 1) {
|
|
30
36
|
onNavigationRedirect('CheckoutNavigator', {
|
|
@@ -80,6 +86,9 @@ export const CartContent = (props: any) => {
|
|
|
80
86
|
isMultiCheckout={isMultiCheckout}
|
|
81
87
|
hideUpselling
|
|
82
88
|
businessConfigs={cart?.business?.configs}
|
|
89
|
+
hideCouponInput={configs?.multi_business_checkout_coupon_input_style?.value === 'group'}
|
|
90
|
+
hideDeliveryFee={configs?.multi_business_checkout_show_combined_delivery_fee?.value === '1'}
|
|
91
|
+
hideDriverTip={configs?.multi_business_checkout_show_combined_driver_tip?.value === '1'}
|
|
83
92
|
/>
|
|
84
93
|
<View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100, marginHorizontal: -40, marginTop: 20 }} />
|
|
85
94
|
</>
|
|
@@ -87,18 +96,51 @@ export const CartContent = (props: any) => {
|
|
|
87
96
|
</CCList>
|
|
88
97
|
))}
|
|
89
98
|
{isMultiCheckout && (
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
<>
|
|
100
|
+
{!!cartsAvailable.length && (
|
|
101
|
+
<ChCartsTotal>
|
|
102
|
+
{!!totalCartsFee && configs?.multi_business_checkout_show_combined_delivery_fee?.value === '1' && (
|
|
103
|
+
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
104
|
+
<OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>
|
|
105
|
+
{t('TOTAL_DELIVERY_FEE', 'Total delivery fee')}
|
|
106
|
+
</OText>
|
|
107
|
+
<OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>
|
|
108
|
+
{parsePrice(totalCartsFee)}
|
|
109
|
+
</OText>
|
|
110
|
+
</View>
|
|
111
|
+
)}
|
|
112
|
+
{cartsAvailable.reduce((sum: any, cart: any) => sum + cart?.driver_tip, 0) > 0 &&
|
|
113
|
+
configs?.multi_business_checkout_show_combined_driver_tip?.value === '1' && (
|
|
114
|
+
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
115
|
+
<OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>
|
|
116
|
+
{t('DRIVER_TIP', 'Driver tip')}
|
|
117
|
+
</OText>
|
|
118
|
+
<OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>
|
|
119
|
+
{parsePrice(cartsAvailable.reduce((sum: any, cart: any) => sum + cart?.driver_tip, 0))}
|
|
120
|
+
</OText>
|
|
121
|
+
</View>
|
|
122
|
+
)}
|
|
123
|
+
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
124
|
+
<OText size={16} lineHeight={24} color={theme.colors.textNormal} weight={'500'}>
|
|
125
|
+
{t('TOTAL_FOR_ALL_CARTS', 'Total for all Carts')}
|
|
126
|
+
</OText>
|
|
127
|
+
<OText size={16} lineHeight={24} color={theme.colors.textNormal} weight={'500'}>{parsePrice(totalCartsPrice)}</OText>
|
|
128
|
+
</View>
|
|
129
|
+
</ChCartsTotal>
|
|
130
|
+
)}
|
|
131
|
+
<CheckoutAction style={{ marginTop: 0 }}>
|
|
132
|
+
<OButton
|
|
133
|
+
text={t('CHECKOUT', 'Checkout')}
|
|
134
|
+
bgColor={!cartsAvailable.length ? theme.colors.secundary : theme.colors.primary}
|
|
135
|
+
isDisabled={!cartsAvailable.length}
|
|
136
|
+
borderColor={theme.colors.primary}
|
|
137
|
+
imgRightSrc={null}
|
|
138
|
+
textStyle={{ color: 'white', textAlign: 'center', flex: 1 }}
|
|
139
|
+
onClick={() => handleCheckoutRedirect()}
|
|
140
|
+
style={{ width: '100%', flexDirection: 'row', justifyContent: 'center', borderRadius: 7.6, shadowOpacity: 0 }}
|
|
141
|
+
/>
|
|
142
|
+
</CheckoutAction>
|
|
143
|
+
</>
|
|
102
144
|
)}
|
|
103
145
|
</>
|
|
104
146
|
)}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import { View, StyleSheet, TouchableOpacity, Platform, I18nManager,
|
|
2
|
+
import { View, StyleSheet, TouchableOpacity, Platform, I18nManager, ScrollView } from 'react-native';
|
|
3
3
|
import { initStripe, useConfirmPayment } from '@stripe/stripe-react-native';
|
|
4
4
|
import Picker from 'react-native-country-picker-modal';
|
|
5
5
|
import MaterialIcons from 'react-native-vector-icons/MaterialIcons'
|
|
@@ -52,7 +52,7 @@ import { FloatingButton } from '../FloatingButton';
|
|
|
52
52
|
import { Container } from '../../layouts/Container';
|
|
53
53
|
import NavBar from '../NavBar';
|
|
54
54
|
import { OrderSummary } from '../OrderSummary';
|
|
55
|
-
import { getTypesText } from '../../utils';
|
|
55
|
+
import { getTypesText, vibrateApp } from '../../utils';
|
|
56
56
|
import { CartStoresListing } from '../CartStoresListing';
|
|
57
57
|
import { PaymentOptionsWebView } from '../../../../../src/components/PaymentOptionsWebView';
|
|
58
58
|
|
|
@@ -222,7 +222,7 @@ const CheckoutUI = (props: any) => {
|
|
|
222
222
|
|
|
223
223
|
const handlePlaceOrder = (confirmPayment: any, forcePlace: boolean = false) => {
|
|
224
224
|
if (!userErrors.length && (!requiredFields?.length || allowedGuest) || forcePlace) {
|
|
225
|
-
|
|
225
|
+
vibrateApp()
|
|
226
226
|
handlerClickPlaceOrder && handlerClickPlaceOrder(null, null, confirmPayment)
|
|
227
227
|
return
|
|
228
228
|
}
|
|
@@ -351,6 +351,7 @@ const CheckoutUI = (props: any) => {
|
|
|
351
351
|
btnStyle={{ paddingLeft: 0, paddingTop: Platform.OS == 'ios' ? 0 : 2 }}
|
|
352
352
|
titleWrapStyle={{ paddingHorizontal: 0 }}
|
|
353
353
|
titleStyle={{ marginRight: 0, marginLeft: 0 }}
|
|
354
|
+
style={{ marginTop: 20 }}
|
|
354
355
|
/>
|
|
355
356
|
</View>
|
|
356
357
|
<ChContainer style={styles.pagePadding}>
|
|
@@ -755,7 +756,7 @@ const CheckoutUI = (props: any) => {
|
|
|
755
756
|
|
|
756
757
|
{!cartState.loading && cart && (
|
|
757
758
|
<View>
|
|
758
|
-
<ChErrors style={{ marginBottom:
|
|
759
|
+
<ChErrors style={{ marginBottom: Platform.OS === 'ios' ? 35 : 10 }}>
|
|
759
760
|
{!cart?.valid_address && cart?.status !== 2 && (
|
|
760
761
|
<OText
|
|
761
762
|
color={theme.colors.error}
|
|
@@ -882,7 +883,7 @@ const CheckoutUI = (props: any) => {
|
|
|
882
883
|
</Container>
|
|
883
884
|
{!cartState.loading && cart && cart?.status !== 2 && (
|
|
884
885
|
<FloatingButton
|
|
885
|
-
handleClick={isDisabledButtonPlace ? () =>
|
|
886
|
+
handleClick={isDisabledButtonPlace ? () => vibrateApp() : () => handlePlaceOrder(null)}
|
|
886
887
|
isSecondaryBtn={isDisabledButtonPlace}
|
|
887
888
|
disabled={isDisabledButtonPlace}
|
|
888
889
|
btnText={subtotalWithTaxes >= cart?.minimum
|
|
@@ -43,7 +43,7 @@ export const GoogleMap = (props: GoogleMapsParams) => {
|
|
|
43
43
|
ERROR_MAX_LIMIT_LOCATION: `Sorry, You can only set the position to ${maxLimitLocation}m`
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const geocodePosition = (pos: { latitude: number, longitude: number }) => {
|
|
46
|
+
const geocodePosition = (pos: { latitude: number, longitude: number }, isMovingRegion ?: boolean) => {
|
|
47
47
|
Geocoder.from({
|
|
48
48
|
latitude: pos.latitude,
|
|
49
49
|
longitude: pos.longitude
|
|
@@ -68,7 +68,9 @@ export const GoogleMap = (props: GoogleMapsParams) => {
|
|
|
68
68
|
}
|
|
69
69
|
handleChangeAddressMap && handleChangeAddressMap(address, details)
|
|
70
70
|
setSaveLocation && setSaveLocation(false)
|
|
71
|
-
|
|
71
|
+
if(!isMovingRegion){
|
|
72
|
+
handleToggleMap && handleToggleMap()
|
|
73
|
+
}
|
|
72
74
|
} else {
|
|
73
75
|
setMapErrors && setMapErrors('ERROR_NOT_FOUND_ADDRESS')
|
|
74
76
|
}
|
|
@@ -92,6 +94,9 @@ export const GoogleMap = (props: GoogleMapsParams) => {
|
|
|
92
94
|
const _maxLimitLocation = typeof maxLimitLocation === 'string' ? parseInt(maxLimitLocation, 10) : maxLimitLocation
|
|
93
95
|
|
|
94
96
|
if (distance <= _maxLimitLocation) {
|
|
97
|
+
if (!aproxEqual(curPos.latitude, center.lat) || !aproxEqual(curPos.longitude, center.lng)){
|
|
98
|
+
geocodePosition(curPos, true)
|
|
99
|
+
}
|
|
95
100
|
setMarkerPosition(curPos)
|
|
96
101
|
setRegion({ ...region, longitude: curPos.longitude, latitude: curPos.latitude })
|
|
97
102
|
} else {
|
|
@@ -100,6 +105,10 @@ export const GoogleMap = (props: GoogleMapsParams) => {
|
|
|
100
105
|
}
|
|
101
106
|
}
|
|
102
107
|
|
|
108
|
+
const aproxEqual = (n1 : number, n2 : number, epsilon = 0.000001) => {
|
|
109
|
+
return Math.abs(n1 - n2) < epsilon
|
|
110
|
+
}
|
|
111
|
+
|
|
103
112
|
const calculateDistance = (pointA: { lat: number, lng: number }, pointB: { latitude: number, longitude: number }) => {
|
|
104
113
|
|
|
105
114
|
const lat1 = pointA.lat;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useState, useRef } from 'react';
|
|
2
|
-
import { StyleSheet, View, Keyboard
|
|
2
|
+
import { StyleSheet, View, Keyboard } from 'react-native';
|
|
3
3
|
import Spinner from 'react-native-loading-spinner-overlay';
|
|
4
4
|
import { useForm, Controller } from 'react-hook-form';
|
|
5
5
|
import { PhoneInputNumber } from '../PhoneInputNumber';
|
|
@@ -45,6 +45,7 @@ import { AppleLogin } from '../AppleLogin';
|
|
|
45
45
|
import { Otp } from './Otp'
|
|
46
46
|
import { TouchableOpacity } from 'react-native-gesture-handler';
|
|
47
47
|
import Alert from '../../../../../src/providers/AlertProvider'
|
|
48
|
+
import { vibrateApp } from '../../utils';
|
|
48
49
|
|
|
49
50
|
const LoginFormUI = (props: LoginParams) => {
|
|
50
51
|
const {
|
|
@@ -166,7 +167,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
166
167
|
if (loginTab === 'otp') {
|
|
167
168
|
if (phoneInputData.error && (loginTab !== 'otp' || (otpType === 'cellphone' && loginTab === 'otp'))) {
|
|
168
169
|
showToast(ToastType.Error, t('INVALID_PHONE_NUMBER', 'Invalid phone number'));
|
|
169
|
-
|
|
170
|
+
vibrateApp()
|
|
170
171
|
return
|
|
171
172
|
}
|
|
172
173
|
if (loginTab === 'otp') {
|
|
@@ -179,7 +180,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
179
180
|
} else {
|
|
180
181
|
if (phoneInputData.error) {
|
|
181
182
|
showToast(ToastType.Error, phoneInputData.error);
|
|
182
|
-
|
|
183
|
+
vibrateApp()
|
|
183
184
|
return;
|
|
184
185
|
}
|
|
185
186
|
handleButtonLoginClick({
|
|
@@ -192,7 +193,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
192
193
|
const handleVerifyCodeClick = () => {
|
|
193
194
|
if (phoneInputData.error) {
|
|
194
195
|
showToast(ToastType.Error, phoneInputData.error);
|
|
195
|
-
|
|
196
|
+
vibrateApp()
|
|
196
197
|
return;
|
|
197
198
|
}
|
|
198
199
|
if (
|
|
@@ -207,7 +208,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
207
208
|
'The field Mobile phone is required.',
|
|
208
209
|
),
|
|
209
210
|
);
|
|
210
|
-
|
|
211
|
+
vibrateApp()
|
|
211
212
|
return;
|
|
212
213
|
}
|
|
213
214
|
handleSendVerifyCode && handleSendVerifyCode(phoneInputData.phone);
|
|
@@ -229,12 +230,12 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
229
230
|
setRecaptchaVerified(false)
|
|
230
231
|
if (!recaptchaConfig?.siteKey) {
|
|
231
232
|
showToast(ToastType.Error, t('NO_RECAPTCHA_SITE_KEY', 'The config doesn\'t have recaptcha site key'));
|
|
232
|
-
|
|
233
|
+
vibrateApp()
|
|
233
234
|
return
|
|
234
235
|
}
|
|
235
236
|
if (!recaptchaConfig?.baseUrl) {
|
|
236
237
|
showToast(ToastType.Error, t('NO_RECAPTCHA_BASE_URL', 'The config doesn\'t have recaptcha base url'));
|
|
237
|
-
|
|
238
|
+
vibrateApp()
|
|
238
239
|
return
|
|
239
240
|
}
|
|
240
241
|
|
|
@@ -311,7 +312,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
311
312
|
baseUrl: configs?.security_recaptcha_base_url?.value || null
|
|
312
313
|
})
|
|
313
314
|
showToast(ToastType.Info, t('TRY_AGAIN', 'Please try again'))
|
|
314
|
-
|
|
315
|
+
vibrateApp()
|
|
315
316
|
return
|
|
316
317
|
}
|
|
317
318
|
formState.result?.result &&
|
|
@@ -321,7 +322,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
321
322
|
? formState.result?.result
|
|
322
323
|
: formState.result?.result[0],
|
|
323
324
|
);
|
|
324
|
-
formState.result?.result &&
|
|
325
|
+
formState.result?.result && vibrateApp()
|
|
325
326
|
}
|
|
326
327
|
}, [formState]);
|
|
327
328
|
|
|
@@ -333,7 +334,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
333
334
|
? verifyPhoneState?.result?.result
|
|
334
335
|
: verifyPhoneState?.result?.result[0];
|
|
335
336
|
verifyPhoneState.result?.result && showToast(ToastType.Error, message);
|
|
336
|
-
verifyPhoneState.result?.result &&
|
|
337
|
+
verifyPhoneState.result?.result && vibrateApp();
|
|
337
338
|
setIsLoadingVerifyModal(false);
|
|
338
339
|
return;
|
|
339
340
|
}
|
|
@@ -374,7 +375,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
374
375
|
}, [checkPhoneCodeState])
|
|
375
376
|
|
|
376
377
|
useEffect(() => {
|
|
377
|
-
if (!!Object.values(errors)?.length)
|
|
378
|
+
if (!!Object.values(errors)?.length) vibrateApp()
|
|
378
379
|
}, [errors])
|
|
379
380
|
|
|
380
381
|
return (
|
|
@@ -766,7 +767,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
766
767
|
facebookLoginEnabled && (
|
|
767
768
|
<FacebookLogin
|
|
768
769
|
notificationState={notificationState}
|
|
769
|
-
handleErrors={(err: any) => { showToast(ToastType.Error, err),
|
|
770
|
+
handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
|
|
770
771
|
handleLoading={(val: boolean) => setIsFBLoading(val)}
|
|
771
772
|
handleSuccessFacebookLogin={handleSuccessFacebook}
|
|
772
773
|
/>
|
|
@@ -775,7 +776,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
775
776
|
<GoogleLogin
|
|
776
777
|
notificationState={notificationState}
|
|
777
778
|
webClientId={configs?.google_login_client_id?.value}
|
|
778
|
-
handleErrors={(err: any) => { showToast(ToastType.Error, err),
|
|
779
|
+
handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
|
|
779
780
|
handleLoading={(val: boolean) => setIsFBLoading(val)}
|
|
780
781
|
handleSuccessGoogleLogin={handleSuccessFacebook}
|
|
781
782
|
/>
|
|
@@ -783,7 +784,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
783
784
|
{(configs?.apple_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && appleLoginEnabled && (
|
|
784
785
|
<AppleLogin
|
|
785
786
|
notificationState={notificationState}
|
|
786
|
-
handleErrors={(err: any) => { showToast(ToastType.Error, err),
|
|
787
|
+
handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
|
|
787
788
|
handleLoading={(val: boolean) => setIsFBLoading(val)}
|
|
788
789
|
handleSuccessAppleLogin={handleSuccessFacebook}
|
|
789
790
|
/>
|
|
@@ -115,11 +115,12 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
)
|
|
118
|
+
const subtotalAmount = openCarts.reduce((sum: any, cart: any) => sum + (cart?.subtotal + getIncludedTaxes(cart)), 0) *
|
|
119
|
+
creditPointPlanOnBusiness?.accumulation_rate
|
|
120
|
+
|
|
121
|
+
const loyaltyRewardValue = (creditPointPlanOnBusiness?.accumulation_rate
|
|
122
|
+
? (Math.trunc(subtotalAmount * 100) / 100).toFixed(configs.format_number_decimal_length?.value ?? 2)
|
|
123
|
+
: 0)
|
|
123
124
|
|
|
124
125
|
const handleMomentClick = () => {
|
|
125
126
|
if (isPreOrder) {
|
|
@@ -25,11 +25,12 @@ export const MyOrders = (props: any) => {
|
|
|
25
25
|
const [ordersLength, setOrdersLength] = useState({
|
|
26
26
|
activeOrdersLength: null,
|
|
27
27
|
previousOrdersLength: 0,
|
|
28
|
+
preordersLength: 0
|
|
28
29
|
});
|
|
29
30
|
const [selectedOption, setSelectedOption] = useState(!hideOrders ? 'orders' : 'business')
|
|
30
31
|
|
|
31
32
|
const notOrderOptions = ['business', 'products']
|
|
32
|
-
const allEmpty = (ordersLength?.activeOrdersLength === 0 && ordersLength?.previousOrdersLength === 0) || ((isEmptyBusinesses || businessOrderIds?.length === 0) && hideOrders)
|
|
33
|
+
const allEmpty = (ordersLength?.activeOrdersLength === 0 && ordersLength?.previousOrdersLength === 0 && ordersLength?.preordersLength === 0) || ((isEmptyBusinesses || businessOrderIds?.length === 0) && hideOrders)
|
|
33
34
|
|
|
34
35
|
const isChewLayout = theme?.header?.components?.layout?.type?.toLowerCase() === 'chew'
|
|
35
36
|
const showNavbar = theme?.bar_menu?.components?.orders?.hidden
|
|
@@ -147,6 +148,18 @@ export const MyOrders = (props: any) => {
|
|
|
147
148
|
)}
|
|
148
149
|
{selectedOption === 'orders' && (
|
|
149
150
|
<>
|
|
151
|
+
{ordersLength?.preordersLength > 0 && (
|
|
152
|
+
<View style={{ paddingHorizontal: isChewLayout ? 20 : 40 }}>
|
|
153
|
+
<OrdersOption
|
|
154
|
+
{...props}
|
|
155
|
+
preOrders
|
|
156
|
+
ordersLength={ordersLength}
|
|
157
|
+
setOrdersLength={setOrdersLength}
|
|
158
|
+
setRefreshOrders={setRefreshOrders}
|
|
159
|
+
refreshOrders={refreshOrders}
|
|
160
|
+
/>
|
|
161
|
+
</View>
|
|
162
|
+
)}
|
|
150
163
|
<View style={{ paddingHorizontal: isChewLayout ? 20 : 40 }}>
|
|
151
164
|
<OrdersOption
|
|
152
165
|
{...props}
|
|
@@ -17,8 +17,10 @@ const TitleTopWrapper = styled.View`
|
|
|
17
17
|
const btnBackArrow = {
|
|
18
18
|
borderWidth: 0,
|
|
19
19
|
backgroundColor: '#FFF',
|
|
20
|
-
borderColor: '#
|
|
21
|
-
shadowColor: '#FFF'
|
|
20
|
+
borderColor: '#fff',
|
|
21
|
+
shadowColor: '#FFF',
|
|
22
|
+
paddingLeft: 30,
|
|
23
|
+
paddingRight: 30
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
interface Props {
|
|
@@ -63,8 +65,11 @@ const NavBar = (props: Props) => {
|
|
|
63
65
|
return (
|
|
64
66
|
<Wrapper style={{ paddingTop: props.paddingTop, ...{ flexDirection: props.isVertical ? 'column' : 'row', alignItems: props.isVertical ? 'flex-start' : 'center' }, ...props.style }}>
|
|
65
67
|
<OButton
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
iconProps={{
|
|
69
|
+
name: 'arrowleft',
|
|
70
|
+
size: 26
|
|
71
|
+
}}
|
|
72
|
+
icon={AntDesignIcon}
|
|
68
73
|
imgRightSrc={null}
|
|
69
74
|
style={{ ...btnBackArrow, ...props.btnStyle, ...props.isVertical ? (I18nManager.isRTL ? { paddingRight: 0 } : { paddingLeft: 0 }) : {} }}
|
|
70
75
|
onClick={props?.onActionLeft}
|
|
@@ -75,7 +75,7 @@ const OrderSummaryUI = (props: any) => {
|
|
|
75
75
|
|
|
76
76
|
const getIncludedTaxes = () => {
|
|
77
77
|
if (cart?.taxes === null || !cart?.taxes) {
|
|
78
|
-
return cart
|
|
78
|
+
return cart?.business?.tax_type === 1 ? cart?.tax : 0
|
|
79
79
|
} else {
|
|
80
80
|
return cart?.taxes.reduce((taxIncluded: number, tax: any) => {
|
|
81
81
|
return taxIncluded + (tax.type === 1 ? tax.summary?.tax : 0)
|
|
@@ -83,7 +83,9 @@ const OrderSummaryUI = (props: any) => {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
const loyaltyRewardValue =
|
|
86
|
+
const loyaltyRewardValue = ((
|
|
87
|
+
Math.trunc(((cart?.subtotal + getIncludedTaxes()) * loyaltyRewardRate) * 100) / 100
|
|
88
|
+
).toFixed(configs.format_number_decimal_length?.value ?? 2), 10)
|
|
87
89
|
|
|
88
90
|
const handleDeleteClick = (product: any) => {
|
|
89
91
|
removeProduct(product, cart)
|
|
@@ -99,7 +99,7 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
99
99
|
return false
|
|
100
100
|
})
|
|
101
101
|
setOrders(orders)
|
|
102
|
-
}, [_orders
|
|
102
|
+
}, [JSON.stringify(_orders)])
|
|
103
103
|
|
|
104
104
|
const onProductClick = (product: any) => {
|
|
105
105
|
if (product?.product_id && product?.category_id && product?.businessId &&
|
|
@@ -167,6 +167,8 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
167
167
|
setOrdersLength && setOrdersLength({ ...ordersLength, activeOrdersLength: updateOrders?.length })
|
|
168
168
|
} else if (!preOrders) {
|
|
169
169
|
setOrdersLength && setOrdersLength({ ...ordersLength, previousOrdersLength: updateOrders?.length })
|
|
170
|
+
} else {
|
|
171
|
+
setOrdersLength && setOrdersLength({ ...ordersLength, preordersLength: updateOrders?.length })
|
|
170
172
|
}
|
|
171
173
|
}, [_orders, activeOrders, preOrders])
|
|
172
174
|
|