ordering-ui-react-native 0.18.38 → 0.18.39
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/original/src/components/AddressForm/index.tsx +7 -4
- package/themes/original/src/components/AddressList/index.tsx +1 -1
- package/themes/original/src/components/BusinessController/index.tsx +3 -3
- package/themes/original/src/components/BusinessListingSearch/index.tsx +330 -276
- package/themes/original/src/components/BusinessProductsList/index.tsx +3 -3
- package/themes/original/src/components/BusinessProductsListing/index.tsx +35 -8
- 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/MyOrders/index.tsx +14 -1
- package/themes/original/src/components/NavBar/index.tsx +9 -4
- package/themes/original/src/components/OrdersOption/index.tsx +3 -1
- package/themes/original/src/components/ProductForm/index.tsx +3 -4
- 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/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 +2 -1
- package/themes/original/src/components/Wallets/index.tsx +1 -1
- 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}
|
|
@@ -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,22 @@ 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)
|
|
139
142
|
|
|
140
143
|
const isCheckoutMultiBusinessEnabled: Boolean = configs?.checkout_multi_business_enabled?.value === '1'
|
|
141
144
|
const isQuickAddProduct = configs?.add_product_with_one_click?.value === '1'
|
|
142
145
|
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
146
|
const currentCart: any = Object.values(orderState.carts).find((cart: any) => cart?.business?.slug === business?.slug) ?? {}
|
|
145
147
|
const isOpenFiltProducts = isOpenSearchBar && !!searchValue
|
|
146
148
|
const filtProductsHeight = Platform.OS === 'ios' ? 165 : 100
|
|
149
|
+
const viewOrderButtonVisible = !loading && auth && currentCart?.products?.length > 0 && categoryState.products.length !== 0
|
|
150
|
+
|
|
147
151
|
const onRedirect = (route: string, params?: any) => {
|
|
148
152
|
navigation.navigate(route, params)
|
|
149
153
|
}
|
|
150
154
|
const onProductClick = async (product: any) => {
|
|
151
|
-
if (product.extras.length === 0 && !product.inventoried && auth && isQuickAddProduct) {
|
|
155
|
+
if (product.ingredients?.length === 0 && product.extras.length === 0 && !product.inventoried && auth && isQuickAddProduct) {
|
|
152
156
|
const isProductAddedToCart = currentCart?.products?.find((Cproduct: any) => Cproduct.id === product.id)
|
|
153
157
|
const productQuantity = isProductAddedToCart?.quantity
|
|
154
158
|
const addCurrentProduct = {
|
|
@@ -156,11 +160,12 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
156
160
|
quantity: 1
|
|
157
161
|
}
|
|
158
162
|
const updateCurrentProduct = {
|
|
163
|
+
name: product?.name,
|
|
159
164
|
id: product.id,
|
|
160
165
|
code: isProductAddedToCart?.code,
|
|
161
166
|
quantity: productQuantity + 1
|
|
162
167
|
}
|
|
163
|
-
|
|
168
|
+
vibrateApp()
|
|
164
169
|
const cartData = currentCart?.business_id ? currentCart : { business_id: business.id }
|
|
165
170
|
if (isProductAddedToCart) {
|
|
166
171
|
await updateProduct(updateCurrentProduct, cartData, isQuickAddProduct)
|
|
@@ -307,6 +312,24 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
307
312
|
}
|
|
308
313
|
}, [isFocused])
|
|
309
314
|
|
|
315
|
+
|
|
316
|
+
useEffect(() => {
|
|
317
|
+
function onKeyboardDidShow(e: KeyboardEvent) {
|
|
318
|
+
setKeyboardHeight(e?.endCoordinates?.height);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function onKeyboardDidHide() {
|
|
322
|
+
setKeyboardHeight(0);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const showSubscription = Keyboard.addListener('keyboardDidShow', onKeyboardDidShow);
|
|
326
|
+
const hideSubscription = Keyboard.addListener('keyboardDidHide', onKeyboardDidHide);
|
|
327
|
+
return () => {
|
|
328
|
+
showSubscription.remove();
|
|
329
|
+
hideSubscription.remove();
|
|
330
|
+
};
|
|
331
|
+
}, []);
|
|
332
|
+
|
|
310
333
|
const subtotalWithTaxes = currentCart?.taxes?.reduce((acc: any, item: any) => {
|
|
311
334
|
if (item?.type === 1)
|
|
312
335
|
return acc = acc + item?.summary?.tax
|
|
@@ -369,7 +392,10 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
369
392
|
<>
|
|
370
393
|
{!(businessSingleId && auth) && (
|
|
371
394
|
<TopActions onPress={() => handleBackNavigation()}>
|
|
372
|
-
<
|
|
395
|
+
<AntDesignIcon
|
|
396
|
+
name='arrowleft'
|
|
397
|
+
size={26}
|
|
398
|
+
/>
|
|
373
399
|
</TopActions>
|
|
374
400
|
)}
|
|
375
401
|
{!errorQuantityProducts && (
|
|
@@ -427,8 +453,8 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
427
453
|
{business?.categories?.length > 0 && isOpenFiltProducts && (
|
|
428
454
|
<FiltProductsContainer
|
|
429
455
|
style={{
|
|
430
|
-
height: Dimensions.get('window').height - filtProductsHeight,
|
|
431
|
-
top: Platform.OS === 'ios' ? (searchBarHeight - 10) + insets.top : searchBarHeight
|
|
456
|
+
height: Dimensions.get('window').height - filtProductsHeight - keyboardHeight - (keyboardHeight > 0 && viewOrderButtonVisible ? 55 : 0),
|
|
457
|
+
top: Platform.OS === 'ios' ? (searchBarHeight - 10) + insets.top : searchBarHeight,
|
|
432
458
|
}}
|
|
433
459
|
contentContainerStyle={{ flexGrow: 1 }}
|
|
434
460
|
>
|
|
@@ -593,7 +619,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
593
619
|
</>
|
|
594
620
|
)}
|
|
595
621
|
</IOScrollView>
|
|
596
|
-
{
|
|
622
|
+
{viewOrderButtonVisible && (
|
|
597
623
|
<View style={{ marginBottom: 0 }}>
|
|
598
624
|
<FloatingButton
|
|
599
625
|
btnText={
|
|
@@ -649,6 +675,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
649
675
|
professionalList={business?.professionals}
|
|
650
676
|
professionalSelected={professionalSelected}
|
|
651
677
|
handleChangeProfessional={handleChangeProfessionalSelected}
|
|
678
|
+
handleChangeProfessional={handleChangeProfessionalSelected}
|
|
652
679
|
handleUpdateProfessionals={handleUpdateProfessionals}
|
|
653
680
|
onSave={() => setOpenService(false)}
|
|
654
681
|
onClose={() => setOpenService(false)}
|
|
@@ -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
|
/>
|
|
@@ -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}
|
|
@@ -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
|
|
|
@@ -9,8 +9,7 @@ import {
|
|
|
9
9
|
I18nManager,
|
|
10
10
|
SafeAreaView,
|
|
11
11
|
Platform,
|
|
12
|
-
Button
|
|
13
|
-
Vibration
|
|
12
|
+
Button
|
|
14
13
|
} from 'react-native';
|
|
15
14
|
import {
|
|
16
15
|
ProductForm as ProductOptions,
|
|
@@ -55,7 +54,7 @@ import { ProductOptionSubOption } from '../ProductOptionSubOption';
|
|
|
55
54
|
import { NotFoundSource } from '../NotFoundSource';
|
|
56
55
|
import { Placeholder, PlaceholderLine, Fade } from 'rn-placeholder';
|
|
57
56
|
import NavBar from '../NavBar';
|
|
58
|
-
import { orderTypeList } from '../../utils';
|
|
57
|
+
import { orderTypeList, vibrateApp } from '../../utils';
|
|
59
58
|
const windowWidth = Dimensions.get('window').width;
|
|
60
59
|
|
|
61
60
|
export const ProductOptionsUI = (props: any) => {
|
|
@@ -225,7 +224,7 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
225
224
|
};
|
|
226
225
|
|
|
227
226
|
const handleSaveProduct = () => {
|
|
228
|
-
|
|
227
|
+
vibrateApp()
|
|
229
228
|
if (!productCart.quantity) {
|
|
230
229
|
showToast(ToastType.Error, t('VALIDATION_ERROR_REQUIRED', 'The quantity field is required').replace('_attribute_', t('PRODUCT_POTIONS_QUANTITY', 'Quantity')))
|
|
231
230
|
return
|
|
@@ -41,8 +41,7 @@ export const ProductOptionSubOptionUI = (props: any) => {
|
|
|
41
41
|
const [showMessage, setShowMessage] = useState(false)
|
|
42
42
|
const [isDirty, setIsDirty] = useState(false)
|
|
43
43
|
|
|
44
|
-
const
|
|
45
|
-
const iconsSize = isChewLayout ? 20 : 16
|
|
44
|
+
const iconsSize = 20
|
|
46
45
|
|
|
47
46
|
const handleSuboptionClick = () => {
|
|
48
47
|
toggleSelect()
|
|
@@ -117,7 +116,8 @@ export const ProductOptionSubOptionUI = (props: any) => {
|
|
|
117
116
|
<OIcon
|
|
118
117
|
src={theme.images.general.half_l}
|
|
119
118
|
color={state.selected && state.position === 'left' ? theme.colors.primary : '#cbcbcb'}
|
|
120
|
-
width={
|
|
119
|
+
width={20}
|
|
120
|
+
height={20}
|
|
121
121
|
style={styles.inverse}
|
|
122
122
|
/>
|
|
123
123
|
</Circle>
|
|
@@ -125,14 +125,16 @@ export const ProductOptionSubOptionUI = (props: any) => {
|
|
|
125
125
|
<OIcon
|
|
126
126
|
src={theme.images.general.half_f}
|
|
127
127
|
color={state.selected && state.position === 'whole' ? theme.colors.primary : '#cbcbcb'}
|
|
128
|
-
width={
|
|
128
|
+
width={20}
|
|
129
|
+
height={20}
|
|
129
130
|
/>
|
|
130
131
|
</Circle>
|
|
131
132
|
<Circle disabled={disabled} onPress={() => changePosition('right')}>
|
|
132
133
|
<OIcon
|
|
133
134
|
src={theme.images.general.half_r}
|
|
134
135
|
color={state.selected && state.position === 'right' ? theme.colors.primary : '#cbcbcb'}
|
|
135
|
-
width={
|
|
136
|
+
width={20}
|
|
137
|
+
height={20}
|
|
136
138
|
/>
|
|
137
139
|
</Circle>
|
|
138
140
|
</>
|
|
@@ -10,7 +10,7 @@ export const Container = styled.TouchableOpacity`
|
|
|
10
10
|
export const IconControl = styled.TouchableOpacity`
|
|
11
11
|
flex-direction: row;
|
|
12
12
|
padding: 10px;
|
|
13
|
-
width:
|
|
13
|
+
width: 38%;
|
|
14
14
|
align-items: center;
|
|
15
15
|
`
|
|
16
16
|
|
|
@@ -18,7 +18,7 @@ export const QuantityControl = styled.View`
|
|
|
18
18
|
flex-direction: row;
|
|
19
19
|
align-items: center;
|
|
20
20
|
justify-content: flex-start;
|
|
21
|
-
margin-
|
|
21
|
+
margin-right: 5px;
|
|
22
22
|
flex: 1;
|
|
23
23
|
width: 60px;
|
|
24
24
|
`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { View, Pressable, StyleSheet, Linking, Platform, TouchableOpacity
|
|
2
|
+
import { View, Pressable, StyleSheet, Linking, Platform, TouchableOpacity } from 'react-native';
|
|
3
3
|
import { useForm, Controller } from 'react-hook-form';
|
|
4
4
|
import Spinner from 'react-native-loading-spinner-overlay';
|
|
5
5
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
|
@@ -37,7 +37,7 @@ import Alert from '../../../../../src/providers/AlertProvider'
|
|
|
37
37
|
import { OText, OButton, OInput } from '../shared';
|
|
38
38
|
import { OModal } from '../../../../../src/components/shared';
|
|
39
39
|
import { SignupParams } from '../../types';
|
|
40
|
-
import { sortInputFields } from '../../utils';
|
|
40
|
+
import { sortInputFields, vibrateApp } from '../../utils';
|
|
41
41
|
import { GoogleLogin } from '../GoogleLogin';
|
|
42
42
|
import { AppleLogin } from '../AppleLogin';
|
|
43
43
|
|
|
@@ -246,7 +246,7 @@ const SignupFormUI = (props: SignupParams) => {
|
|
|
246
246
|
const onSubmit = (values?: any) => {
|
|
247
247
|
if (phoneInputData.error && signUpTab !== 'otpEmail') {
|
|
248
248
|
showToast(ToastType.Error, phoneInputData.error);
|
|
249
|
-
|
|
249
|
+
vibrateApp()
|
|
250
250
|
return;
|
|
251
251
|
}
|
|
252
252
|
if (
|
|
@@ -264,7 +264,7 @@ const SignupFormUI = (props: SignupParams) => {
|
|
|
264
264
|
'The field Mobile phone is required.',
|
|
265
265
|
),
|
|
266
266
|
);
|
|
267
|
-
|
|
267
|
+
vibrateApp()
|
|
268
268
|
return;
|
|
269
269
|
}
|
|
270
270
|
if (signUpTab === 'otpEmail' || signUpTab === 'otpCellphone') {
|
|
@@ -333,7 +333,7 @@ const SignupFormUI = (props: SignupParams) => {
|
|
|
333
333
|
await Linking.openURL(url);
|
|
334
334
|
} else {
|
|
335
335
|
showToast(ToastType.Error, t('VALIDATION_ERROR_ACTIVE_URL', 'The _attribute_ is not a valid URL.').replace('_attribute_', t('URL', 'URL')))
|
|
336
|
-
|
|
336
|
+
vibrateApp()
|
|
337
337
|
}
|
|
338
338
|
}
|
|
339
339
|
|
|
@@ -341,12 +341,12 @@ const SignupFormUI = (props: SignupParams) => {
|
|
|
341
341
|
setRecaptchaVerified(false)
|
|
342
342
|
if (!recaptchaConfig?.siteKey) {
|
|
343
343
|
showToast(ToastType.Error, t('NO_RECAPTCHA_SITE_KEY', 'The config doesn\'t have recaptcha site key'));
|
|
344
|
-
|
|
344
|
+
vibrateApp()
|
|
345
345
|
return
|
|
346
346
|
}
|
|
347
347
|
if (!recaptchaConfig?.baseUrl) {
|
|
348
348
|
showToast(ToastType.Error, t('NO_RECAPTCHA_BASE_URL', 'The config doesn\'t have recaptcha base url'));
|
|
349
|
-
|
|
349
|
+
vibrateApp()
|
|
350
350
|
return
|
|
351
351
|
}
|
|
352
352
|
recaptchaRef.current.open()
|
|
@@ -390,11 +390,11 @@ const SignupFormUI = (props: SignupParams) => {
|
|
|
390
390
|
baseUrl: configs?.security_recaptcha_base_url?.value || null
|
|
391
391
|
})
|
|
392
392
|
showToast(ToastType.Info, t('TRY_AGAIN', 'Please try again'))
|
|
393
|
-
|
|
393
|
+
vibrateApp()
|
|
394
394
|
return
|
|
395
395
|
}
|
|
396
396
|
formState.result?.result && showToast(ToastType.Error, formState.result?.result[0]);
|
|
397
|
-
formState.result?.result &&
|
|
397
|
+
formState.result?.result && vibrateApp()
|
|
398
398
|
setIsLoadingVerifyModal(false);
|
|
399
399
|
}
|
|
400
400
|
}, [formState]);
|
|
@@ -402,7 +402,7 @@ const SignupFormUI = (props: SignupParams) => {
|
|
|
402
402
|
useEffect(() => {
|
|
403
403
|
if (Object.keys(errors).length > 0) {
|
|
404
404
|
setIsLoadingVerifyModal(false);
|
|
405
|
-
|
|
405
|
+
vibrateApp()
|
|
406
406
|
}
|
|
407
407
|
}, [errors])
|
|
408
408
|
|
|
@@ -431,7 +431,7 @@ const SignupFormUI = (props: SignupParams) => {
|
|
|
431
431
|
? verifyPhoneState?.result?.result
|
|
432
432
|
: verifyPhoneState?.result?.result[0];
|
|
433
433
|
verifyPhoneState.result?.result && showToast(ToastType.Error, message);
|
|
434
|
-
verifyPhoneState.result?.result &&
|
|
434
|
+
verifyPhoneState.result?.result && vibrateApp()
|
|
435
435
|
setIsLoadingVerifyModal(false);
|
|
436
436
|
return;
|
|
437
437
|
}
|
|
@@ -930,7 +930,7 @@ const SignupFormUI = (props: SignupParams) => {
|
|
|
930
930
|
(
|
|
931
931
|
<FacebookLogin
|
|
932
932
|
notificationState={notificationState}
|
|
933
|
-
handleErrors={(err: any) => { showToast(ToastType.Error, err),
|
|
933
|
+
handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
|
|
934
934
|
handleLoading={(val: boolean) => setIsFBLoading(val)}
|
|
935
935
|
handleSuccessFacebookLogin={handleSuccessFacebook}
|
|
936
936
|
/>
|
|
@@ -939,7 +939,7 @@ const SignupFormUI = (props: SignupParams) => {
|
|
|
939
939
|
<GoogleLogin
|
|
940
940
|
notificationState={notificationState}
|
|
941
941
|
webClientId={configs?.google_login_client_id?.value}
|
|
942
|
-
handleErrors={(err: any) => { showToast(ToastType.Error, err),
|
|
942
|
+
handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
|
|
943
943
|
handleLoading={(val: boolean) => setIsFBLoading(val)}
|
|
944
944
|
handleSuccessGoogleLogin={handleSuccessFacebook}
|
|
945
945
|
/>
|
|
@@ -947,7 +947,7 @@ const SignupFormUI = (props: SignupParams) => {
|
|
|
947
947
|
{(configs?.apple_login_client_id?.value !== '' && configs?.apple_login_client_id?.value !== null) && appleLoginEnabled && (
|
|
948
948
|
<AppleLogin
|
|
949
949
|
notificationState={notificationState}
|
|
950
|
-
handleErrors={(err: any) => { showToast(ToastType.Error, err),
|
|
950
|
+
handleErrors={(err: any) => { showToast(ToastType.Error, err), vibrateApp() }}
|
|
951
951
|
handleLoading={(val: boolean) => setIsFBLoading(val)}
|
|
952
952
|
handleSuccessAppleLogin={handleSuccessFacebook}
|
|
953
953
|
/>
|