ordering-ui-react-native 0.18.38 → 0.18.40-test

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.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/themes/business/src/components/DriverMap/index.tsx +1 -1
  3. package/themes/business/src/components/OrderSummary/index.tsx +120 -124
  4. package/themes/original/src/components/AddressForm/index.tsx +7 -4
  5. package/themes/original/src/components/AddressList/index.tsx +1 -1
  6. package/themes/original/src/components/BusinessBasicInformation/index.tsx +18 -3
  7. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +0 -3
  8. package/themes/original/src/components/BusinessController/index.tsx +3 -3
  9. package/themes/original/src/components/BusinessListingSearch/index.tsx +331 -276
  10. package/themes/original/src/components/BusinessProductsList/index.tsx +3 -3
  11. package/themes/original/src/components/BusinessProductsListing/UpsellingRedirect.tsx +1 -1
  12. package/themes/original/src/components/BusinessProductsListing/index.tsx +49 -8
  13. package/themes/original/src/components/CartContent/index.tsx +56 -14
  14. package/themes/original/src/components/CartContent/styles.tsx +4 -0
  15. package/themes/original/src/components/Checkout/index.tsx +6 -5
  16. package/themes/original/src/components/GoogleMap/index.tsx +11 -2
  17. package/themes/original/src/components/LoginForm/index.tsx +15 -14
  18. package/themes/original/src/components/MultiCheckout/index.tsx +6 -5
  19. package/themes/original/src/components/MyOrders/index.tsx +14 -1
  20. package/themes/original/src/components/NavBar/index.tsx +9 -4
  21. package/themes/original/src/components/OrderSummary/index.tsx +4 -2
  22. package/themes/original/src/components/OrdersOption/index.tsx +3 -1
  23. package/themes/original/src/components/ProductForm/index.tsx +23 -11
  24. package/themes/original/src/components/ProductOptionSubOption/index.tsx +7 -5
  25. package/themes/original/src/components/ProductOptionSubOption/styles.tsx +2 -2
  26. package/themes/original/src/components/SignupForm/index.tsx +14 -14
  27. package/themes/original/src/components/SingleOrderCard/index.tsx +7 -1
  28. package/themes/original/src/components/StripeElementsForm/index.tsx +17 -16
  29. package/themes/original/src/components/UserFormDetails/index.tsx +34 -5
  30. package/themes/original/src/components/UserProfile/index.tsx +2 -20
  31. package/themes/original/src/components/UserProfileForm/index.tsx +7 -2
  32. package/themes/original/src/components/WalletTransactions/index.tsx +3 -3
  33. package/themes/original/src/components/Wallets/index.tsx +4 -4
  34. package/themes/original/src/types/index.tsx +2 -2
  35. 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 && categoryState.products?.length < 80}
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 && categoryState.products?.length < 80}
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 && categoryState.products?.length < 80}
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, Vibration, BackHandler } from 'react-native'
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
- Vibration.vibrate()
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
- <OIcon src={theme.images.general.arrow_left} color={theme.colors.textNormal} />
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
- {!loading && auth && currentCart?.products?.length > 0 && categoryState.products.length !== 0 && (
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
- <CheckoutAction style={{ marginTop: 0 }}>
91
- <OButton
92
- text={t('CHECKOUT', 'Checkout')}
93
- bgColor={!cartsAvailable.length ? theme.colors.secundary : theme.colors.primary}
94
- isDisabled={!cartsAvailable.length}
95
- borderColor={theme.colors.primary}
96
- imgRightSrc={null}
97
- textStyle={{ color: 'white', textAlign: 'center', flex: 1 }}
98
- onClick={() => handleCheckoutRedirect()}
99
- style={{ width: '100%', flexDirection: 'row', justifyContent: 'center', borderRadius: 7.6, shadowOpacity: 0 }}
100
- />
101
- </CheckoutAction>
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
  )}
@@ -23,3 +23,7 @@ export const CheckoutAction = styled.View`
23
23
  margin-top: 10px;
24
24
  margin-bottom: 10px;
25
25
  `
26
+
27
+ export const ChCartsTotal = styled.View`
28
+ margin-bottom: 16px;
29
+ `
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect } from 'react';
2
- import { View, StyleSheet, TouchableOpacity, Platform, I18nManager, Vibration, ScrollView } from 'react-native';
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
- Vibration.vibrate()
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: 30 }}>
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 ? () => Vibration.vibrate() : () => handlePlaceOrder(null)}
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
- handleToggleMap && handleToggleMap()
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, Vibration } from 'react-native';
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
- Vibration.vibrate()
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
- Vibration.vibrate()
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
- Vibration.vibrate()
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
- Vibration.vibrate()
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
- Vibration.vibrate()
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
- Vibration.vibrate()
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
- Vibration.vibrate()
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 && Vibration.vibrate()
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 && Vibration.vibrate();
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) Vibration.vibrate()
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), Vibration.vibrate() }}
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), Vibration.vibrate() }}
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), Vibration.vibrate() }}
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 loyaltyRewardValue = creditPointPlanOnBusiness?.accumulation_rate
119
- ? Math.round(
120
- openCarts.reduce((sum: any, cart: any) => sum + cart?.subtotal + getIncludedTaxes(cart), 0) /
121
- creditPointPlanOnBusiness?.accumulation_rate
122
- ) : 0
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: '#FFF',
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
- imgLeftSrc={theme.images.general.arrow_left}
67
- imgLeftStyle={{ width: 26 }}
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.business.tax_type === 1 ? cart?.tax : 0
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 = Math.round((cart?.subtotal + getIncludedTaxes()) / loyaltyRewardRate)
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?.length])
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