ordering-ui-react-native 0.21.77-release → 0.21.78-release
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/themes/original/src/components/Checkout/index.tsx +90 -52
- package/themes/original/src/components/MultiCheckout/index.tsx +55 -23
- package/themes/original/src/components/OrderSummary/index.tsx +5 -4
- package/themes/original/src/components/ProductForm/ActionButton.tsx +1 -1
- package/themes/original/src/components/UserDetails/index.tsx +3 -2
- package/themes/original/src/components/UserFormDetails/index.tsx +72 -59
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect, useCallback, useRef } from 'react';
|
|
1
|
+
import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
|
2
2
|
import { View, StyleSheet, TouchableOpacity, Platform, I18nManager, ScrollView, Keyboard, BackHandler, SafeAreaView } from 'react-native';
|
|
3
3
|
import { initStripe, useConfirmPayment } from '@stripe/stripe-react-native';
|
|
4
4
|
import NativeStripeSdk from '@stripe/stripe-react-native/src/NativeStripeSdk'
|
|
@@ -7,7 +7,7 @@ import MaterialIcons from 'react-native-vector-icons/MaterialIcons'
|
|
|
7
7
|
import IconAntDesign from 'react-native-vector-icons/AntDesign';
|
|
8
8
|
import { useIsFocused } from '@react-navigation/native';
|
|
9
9
|
|
|
10
|
-
import ReactNativeHapticFeedback from "react-native-haptic-feedback";
|
|
10
|
+
import ReactNativeHapticFeedback, { HapticFeedbackTypes } from "react-native-haptic-feedback";
|
|
11
11
|
import {
|
|
12
12
|
Checkout as CheckoutController,
|
|
13
13
|
useOrder,
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
useApi,
|
|
16
16
|
useLanguage,
|
|
17
17
|
useUtils,
|
|
18
|
-
useValidationFields,
|
|
19
18
|
useConfig,
|
|
20
19
|
useToast,
|
|
21
20
|
ToastType,
|
|
@@ -103,7 +102,8 @@ const CheckoutUI = (props: any) => {
|
|
|
103
102
|
setPlaceSpotNumber,
|
|
104
103
|
maxDate,
|
|
105
104
|
androidAppId,
|
|
106
|
-
urlscheme
|
|
105
|
+
urlscheme,
|
|
106
|
+
checkoutFieldsState
|
|
107
107
|
} = props
|
|
108
108
|
|
|
109
109
|
const theme = useTheme();
|
|
@@ -145,12 +145,11 @@ const CheckoutUI = (props: any) => {
|
|
|
145
145
|
|
|
146
146
|
const [, { showToast }] = useToast();
|
|
147
147
|
const [, t] = useLanguage();
|
|
148
|
-
const [{ user, token }, { login }] = useSession();
|
|
148
|
+
const [{ user, token, loading: userLoading }, { login }] = useSession();
|
|
149
149
|
const [ordering] = useApi()
|
|
150
150
|
const [{ configs }] = useConfig();
|
|
151
151
|
const [{ parsePrice, parseDate }] = useUtils();
|
|
152
152
|
const [{ options, carts, loading }, { confirmCart }] = useOrder();
|
|
153
|
-
const [validationFields] = useValidationFields();
|
|
154
153
|
const [events] = useEvent()
|
|
155
154
|
const [orientationState] = useDeviceOrientation();
|
|
156
155
|
const [isReadMore, setIsReadMore] = useState(false)
|
|
@@ -167,6 +166,7 @@ const CheckoutUI = (props: any) => {
|
|
|
167
166
|
const [webviewPaymethod, setWebviewPaymethod] = useState<any>(null)
|
|
168
167
|
const [isOpen, setIsOpen] = useState(false)
|
|
169
168
|
const [requiredFields, setRequiredFields] = useState<any>([])
|
|
169
|
+
const [orderTypeValidationFields, setOrderTypeValidationFields] = useState<any>([])
|
|
170
170
|
const [openModal, setOpenModal] = useState({ login: false, signup: false, isGuest: false })
|
|
171
171
|
const [allowedGuest, setAllowedGuest] = useState(false)
|
|
172
172
|
const [placeByMethodPay, setPlaceByMethodPay] = useState(false)
|
|
@@ -178,6 +178,14 @@ const CheckoutUI = (props: any) => {
|
|
|
178
178
|
const containerRef = useRef<any>()
|
|
179
179
|
const cardsMethods = ['credomatic']
|
|
180
180
|
const stripePaymethods: any = ['stripe', 'stripe_direct', 'stripe_connect', 'stripe_redirect']
|
|
181
|
+
const notFields = ['coupon', 'driver_tip', 'mobile_phone', 'address', 'zipcode', 'address_notes', 'comments']
|
|
182
|
+
|
|
183
|
+
const checkoutFields = useMemo(() => checkoutFieldsState?.fields?.filter((field : any) => field.order_type_id === options?.type), [checkoutFieldsState, options])
|
|
184
|
+
const guestCheckoutDriveTip = useMemo(() => checkoutFields?.find((field : any) => field.order_type_id === 1 && field?.validation_field?.code === 'driver_tip'), [JSON.stringify(checkoutFields), options])
|
|
185
|
+
const guestCheckoutComment = useMemo(() => checkoutFields?.find((field : any) => field.order_type_id === options?.type && field?.validation_field?.code === 'comments'), [JSON.stringify(checkoutFields), options])
|
|
186
|
+
const guestCheckoutCoupon = useMemo(() => checkoutFields?.find((field : any) => field.order_type_id === options?.type && field?.validation_field?.code === 'coupon'), [JSON.stringify(checkoutFields), options])
|
|
187
|
+
const guestCheckoutZipcode = useMemo(() => checkoutFields?.find((field : any) => field.order_type_id === options?.type && field?.validation_field?.code === 'zipcode'), [JSON.stringify(checkoutFields), options])
|
|
188
|
+
|
|
181
189
|
const placeSpotTypes = [3, 4, 5]
|
|
182
190
|
const placeSpotsEnabled = placeSpotTypes.includes(options?.type)
|
|
183
191
|
const businessConfigs = businessDetails?.business?.configs ?? []
|
|
@@ -202,27 +210,28 @@ const CheckoutUI = (props: any) => {
|
|
|
202
210
|
return acc = acc
|
|
203
211
|
}, cart?.subtotal)
|
|
204
212
|
|
|
205
|
-
const validateCommentsCartField =
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
!paymethodSelected?.data?.card?.zipcode &&
|
|
210
|
-
paymethodSelected?.gateway === 'stripe'
|
|
213
|
+
const validateCommentsCartField = (guestCheckoutComment?.enabled && (user?.guest_id ? guestCheckoutComment?.required_with_guest : guestCheckoutComment?.required)) && (cart?.comment === null || cart?.comment?.trim().length === 0)
|
|
214
|
+
const validateDriverTipField = options.type === 1 && (guestCheckoutDriveTip?.enabled && (user?.guest_id ? guestCheckoutDriveTip?.required_with_guest : guestCheckoutDriveTip?.required)) && (Number(cart?.driver_tip) <= 0)
|
|
215
|
+
const validateCouponField = (guestCheckoutCoupon?.enabled && (user?.guest_id ? guestCheckoutCoupon?.required_with_guest : guestCheckoutCoupon?.required)) && !cart?.offers?.some((offer : any) => offer?.type === 2)
|
|
216
|
+
const validateZipcodeCard = (guestCheckoutZipcode?.enabled && (user?.guest_id ? guestCheckoutZipcode?.required_with_guest : guestCheckoutZipcode?.required)) && paymethodSelected?.gateway === 'stripe' && paymethodSelected?.data?.card && !paymethodSelected?.data?.card?.zipcode
|
|
211
217
|
|
|
212
218
|
const isDisabledButtonPlace = loading || !cart?.valid || (!paymethodSelected && cart?.balance > 0) ||
|
|
213
219
|
placing || errorCash || subtotalWithTaxes < cart?.minimum ||
|
|
214
220
|
(cardsMethods.includes(paymethodSelected?.gateway) && cardList?.cards?.length === 0) ||
|
|
215
|
-
(options.type === 1 && !isGiftCardCart &&
|
|
216
|
-
validationFields?.fields?.checkout?.driver_tip?.enabled &&
|
|
217
|
-
validationFields?.fields?.checkout?.driver_tip?.required &&
|
|
218
|
-
(Number(cart?.driver_tip) <= 0)) ||
|
|
219
221
|
(validateCommentsCartField) ||
|
|
220
|
-
(
|
|
221
|
-
|
|
222
|
+
(validateDriverTipField && !isGiftCardCart) ||
|
|
223
|
+
(validateZipcodeCard) ||
|
|
224
|
+
(methodsPay.includes(paymethodSelected?.gateway) && (!methodPaySupported.enabled || methodPaySupported.loading)) ||
|
|
225
|
+
validateCommentsCartField ||
|
|
226
|
+
validateDriverTipField ||
|
|
227
|
+
validateCouponField ||
|
|
228
|
+
validateZipcodeCard
|
|
229
|
+
|
|
222
230
|
|
|
223
231
|
const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
|
|
224
232
|
? JSON.parse(configs?.driver_tip_options?.value) || []
|
|
225
233
|
: configs?.driver_tip_options?.value || []
|
|
234
|
+
const driverTipsField = !cartState.loading && cart && cart?.business_id && options.type === 1 && cart?.status !== 2 && (guestCheckoutDriveTip?.enabled) && driverTipsOptions.length > 0
|
|
226
235
|
|
|
227
236
|
const configTypes = configs?.order_types_allowed?.value.split('|').map((value: any) => Number(value)) || []
|
|
228
237
|
|
|
@@ -243,7 +252,7 @@ const CheckoutUI = (props: any) => {
|
|
|
243
252
|
}
|
|
244
253
|
}
|
|
245
254
|
|
|
246
|
-
const vibrateApp = (impact?:
|
|
255
|
+
const vibrateApp = (impact?: HapticFeedbackTypes) => {
|
|
247
256
|
const options = {
|
|
248
257
|
enableVibrateFallback: true,
|
|
249
258
|
ignoreAndroidSystemSettings: false
|
|
@@ -270,7 +279,7 @@ const CheckoutUI = (props: any) => {
|
|
|
270
279
|
return
|
|
271
280
|
}
|
|
272
281
|
|
|
273
|
-
if (!userErrors.length && (!requiredFields?.length
|
|
282
|
+
if (!userErrors.length && (!requiredFields?.length) || forcePlace) {
|
|
274
283
|
vibrateApp()
|
|
275
284
|
handlerClickPlaceOrder && handlerClickPlaceOrder(null, { isNative: true }, confirmPayment, NativeStripeSdk?.dismissPlatformPay)
|
|
276
285
|
return
|
|
@@ -309,35 +318,55 @@ const CheckoutUI = (props: any) => {
|
|
|
309
318
|
|
|
310
319
|
const checkValidationFields = () => {
|
|
311
320
|
setUserErrors([])
|
|
312
|
-
const errors = []
|
|
313
|
-
const
|
|
314
|
-
const _requiredFields:
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
321
|
+
const errors: Array<string> = []
|
|
322
|
+
const userSelected = user
|
|
323
|
+
const _requiredFields: Array<string> = []
|
|
324
|
+
Object.values(checkoutFieldsState?.fields).map((field: any) => {
|
|
325
|
+
if (options?.type === field?.order_type_id &&
|
|
326
|
+
field?.enabled &&
|
|
327
|
+
field?.required &&
|
|
328
|
+
!notFields.includes(field?.validation_field?.code)
|
|
329
|
+
) {
|
|
330
|
+
if (userSelected && !userSelected[field?.validation_field?.code]) {
|
|
331
|
+
_requiredFields.push(field?.validation_field?.code)
|
|
320
332
|
}
|
|
321
333
|
}
|
|
322
334
|
})
|
|
323
|
-
|
|
335
|
+
const mobilePhoneField: any = Object.values(checkoutFieldsState?.fields)?.find((field: any) => field?.order_type_id === options?.type && field?.validation_field?.code === 'mobile_phone')
|
|
324
336
|
if (
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
337
|
+
userSelected &&
|
|
338
|
+
!userSelected?.cellphone &&
|
|
339
|
+
((mobilePhoneField?.enabled &&
|
|
340
|
+
mobilePhoneField?.required) ||
|
|
328
341
|
configs?.verification_phone_required?.value === '1')
|
|
329
342
|
) {
|
|
330
343
|
_requiredFields.push('cellphone')
|
|
331
344
|
}
|
|
332
345
|
setRequiredFields(_requiredFields)
|
|
333
346
|
|
|
334
|
-
if (phoneUpdate) {
|
|
335
|
-
errors.push(t('NECESSARY_UPDATE_COUNTRY_PHONE_CODE', 'It is necessary to update your phone number'))
|
|
336
|
-
}
|
|
337
|
-
|
|
338
347
|
setUserErrors(errors)
|
|
339
348
|
}
|
|
340
349
|
|
|
350
|
+
const checkGuestValidationFields = () => {
|
|
351
|
+
const userSelected = user
|
|
352
|
+
const _requiredFields = checkoutFieldsState?.fields
|
|
353
|
+
.filter((field) => (field?.order_type_id === options?.type) && field?.enabled && field?.required_with_guest &&
|
|
354
|
+
!notFields.includes(field?.validation_field?.code) &&
|
|
355
|
+
userSelected && !userSelected[field?.validation_field?.code])
|
|
356
|
+
const requiredFieldsCode = _requiredFields.map((item) => item?.validation_field?.code)
|
|
357
|
+
const guestCheckoutCellPhone = checkoutFieldsState?.fields?.find((field) => field.order_type_id === options?.type && field?.validation_field?.code === 'mobile_phone')
|
|
358
|
+
if (
|
|
359
|
+
userSelected &&
|
|
360
|
+
!userSelected?.cellphone &&
|
|
361
|
+
((guestCheckoutCellPhone?.enabled &&
|
|
362
|
+
guestCheckoutCellPhone?.required_with_guest) ||
|
|
363
|
+
configs?.verification_phone_required?.value === '1')
|
|
364
|
+
) {
|
|
365
|
+
requiredFieldsCode.push('cellphone')
|
|
366
|
+
}
|
|
367
|
+
setRequiredFields(requiredFieldsCode)
|
|
368
|
+
}
|
|
369
|
+
|
|
341
370
|
const togglePhoneUpdate = (val: boolean) => {
|
|
342
371
|
setPhoneUpdate(val)
|
|
343
372
|
}
|
|
@@ -353,10 +382,13 @@ const CheckoutUI = (props: any) => {
|
|
|
353
382
|
}
|
|
354
383
|
|
|
355
384
|
useEffect(() => {
|
|
356
|
-
if (
|
|
385
|
+
if (checkoutFieldsState?.loading || userLoading) return
|
|
386
|
+
if (user?.guest_id) {
|
|
387
|
+
checkGuestValidationFields()
|
|
388
|
+
} else {
|
|
357
389
|
checkValidationFields()
|
|
358
390
|
}
|
|
359
|
-
}, [
|
|
391
|
+
}, [checkoutFieldsState, user, options?.type])
|
|
360
392
|
|
|
361
393
|
useEffect(() => {
|
|
362
394
|
if (errors) {
|
|
@@ -654,6 +686,9 @@ const CheckoutUI = (props: any) => {
|
|
|
654
686
|
isCheckout
|
|
655
687
|
phoneUpdate={phoneUpdate}
|
|
656
688
|
togglePhoneUpdate={togglePhoneUpdate}
|
|
689
|
+
isOrderTypeValidationField
|
|
690
|
+
requiredFields={requiredFields}
|
|
691
|
+
checkoutFields={checkoutFields}
|
|
657
692
|
/>
|
|
658
693
|
)
|
|
659
694
|
)}
|
|
@@ -767,14 +802,7 @@ const CheckoutUI = (props: any) => {
|
|
|
767
802
|
</ChSection>
|
|
768
803
|
)}
|
|
769
804
|
|
|
770
|
-
{
|
|
771
|
-
cart &&
|
|
772
|
-
cart?.valid &&
|
|
773
|
-
options.type === 1 &&
|
|
774
|
-
cart?.status !== 2 &&
|
|
775
|
-
validationFields?.fields?.checkout?.driver_tip?.enabled &&
|
|
776
|
-
driverTipsOptions && driverTipsOptions?.length > 0 &&
|
|
777
|
-
cart?.business_id &&
|
|
805
|
+
{driverTipsField &&
|
|
778
806
|
(
|
|
779
807
|
<ChSection>
|
|
780
808
|
<ChDriverTips>
|
|
@@ -919,6 +947,8 @@ const CheckoutUI = (props: any) => {
|
|
|
919
947
|
creditPointPlanOnBusiness?.accumulation_rate ??
|
|
920
948
|
(!!creditPointPlanOnBusiness && creditPointPlan?.accumulation_rate) ?? 0
|
|
921
949
|
}
|
|
950
|
+
hideCommentsByValidationCheckout={!guestCheckoutComment?.enabled}
|
|
951
|
+
hideCouponByValidationCheckout={!guestCheckoutCoupon?.enabled}
|
|
922
952
|
/>
|
|
923
953
|
</>
|
|
924
954
|
)}
|
|
@@ -965,10 +995,8 @@ const CheckoutUI = (props: any) => {
|
|
|
965
995
|
{t('INVALID_CART_MOMENT', 'Selected schedule time is invalid, please select a schedule into the business schedule interval.')}
|
|
966
996
|
</OText>
|
|
967
997
|
)}
|
|
968
|
-
{
|
|
969
|
-
|
|
970
|
-
validationFields?.fields?.checkout?.driver_tip?.required &&
|
|
971
|
-
(Number(cart?.driver_tip) <= 0) && (
|
|
998
|
+
{validateDriverTipField && !isGiftCardCart &&
|
|
999
|
+
(
|
|
972
1000
|
<OText
|
|
973
1001
|
color={theme.colors.error}
|
|
974
1002
|
size={12}
|
|
@@ -976,7 +1004,6 @@ const CheckoutUI = (props: any) => {
|
|
|
976
1004
|
{t('WARNING_INVALID_DRIVER_TIP', 'Driver Tip is required.')}
|
|
977
1005
|
</OText>
|
|
978
1006
|
)}
|
|
979
|
-
|
|
980
1007
|
{validateCommentsCartField && (
|
|
981
1008
|
<OText
|
|
982
1009
|
color={theme.colors.error}
|
|
@@ -994,6 +1021,15 @@ const CheckoutUI = (props: any) => {
|
|
|
994
1021
|
{t('WARNING_CARD_ZIPCODE_REQUIRED', 'Your card selected has not zipcode')}
|
|
995
1022
|
</OText>
|
|
996
1023
|
)}
|
|
1024
|
+
{validateCouponField &&
|
|
1025
|
+
(
|
|
1026
|
+
<OText
|
|
1027
|
+
color={theme.colors.error}
|
|
1028
|
+
size={12}
|
|
1029
|
+
>
|
|
1030
|
+
{t('WARNING_INVALID_COUPON_FIELD', 'Coupon is required.')}
|
|
1031
|
+
</OText>
|
|
1032
|
+
)}
|
|
997
1033
|
</ChErrors>
|
|
998
1034
|
</View>
|
|
999
1035
|
)}
|
|
@@ -1017,14 +1053,16 @@ const CheckoutUI = (props: any) => {
|
|
|
1017
1053
|
isUserDetailsEdit
|
|
1018
1054
|
cartStatus={cart?.status}
|
|
1019
1055
|
businessId={cart?.business_id}
|
|
1020
|
-
useValidationFields
|
|
1021
1056
|
useDefualtSessionManager
|
|
1022
1057
|
useSessionUser
|
|
1023
1058
|
isCheckout
|
|
1024
1059
|
isEdit
|
|
1025
1060
|
phoneUpdate={phoneUpdate}
|
|
1026
1061
|
togglePhoneUpdate={togglePhoneUpdate}
|
|
1062
|
+
isOrderTypeValidationField
|
|
1027
1063
|
requiredFields={requiredFields}
|
|
1064
|
+
checkoutFields={checkoutFields}
|
|
1065
|
+
isCheckoutPlace
|
|
1028
1066
|
hideUpdateButton
|
|
1029
1067
|
handlePlaceOrderAsGuest={handlePlaceOrderAsGuest}
|
|
1030
1068
|
onClose={() => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect, useCallback } from 'react'
|
|
1
|
+
import React, { useState, useEffect, useCallback, useMemo } from 'react'
|
|
2
2
|
import {
|
|
3
3
|
useLanguage,
|
|
4
4
|
useConfig,
|
|
@@ -70,7 +70,8 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
70
70
|
walletState,
|
|
71
71
|
onNavigationRedirectReplace,
|
|
72
72
|
merchantId,
|
|
73
|
-
cartsInvalid
|
|
73
|
+
cartsInvalid,
|
|
74
|
+
checkoutFieldsState
|
|
74
75
|
} = props
|
|
75
76
|
|
|
76
77
|
const theme = useTheme();
|
|
@@ -96,8 +97,9 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
96
97
|
const [{ parsePrice, parseDate }] = useUtils();
|
|
97
98
|
const [{ options, carts, loading }, { confirmCart }] = useOrder();
|
|
98
99
|
const [validationFields] = useValidationFields();
|
|
99
|
-
const [{ user }, { login }] = useSession()
|
|
100
|
+
const [{ user, loading: userLoading }, { login }] = useSession()
|
|
100
101
|
|
|
102
|
+
const notFields = ['coupon', 'driver_tip', 'mobile_phone', 'address', 'zipcode', 'address_notes', 'comments']
|
|
101
103
|
const configTypes = configs?.order_types_allowed?.value.split('|').map((value: any) => Number(value)) || []
|
|
102
104
|
const isPreOrder = configs?.preorder_status_enabled?.value === '1'
|
|
103
105
|
const isMultiDriverTips = configs?.checkout_multi_business_enabled?.value === '1'
|
|
@@ -121,6 +123,7 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
121
123
|
|
|
122
124
|
const creditPointGeneralPlan = loyaltyPlansState?.result?.find((loyal: any) => loyal.type === 'credit_point')
|
|
123
125
|
const loyalBusinessAvailable = creditPointGeneralPlan?.businesses?.filter((b: any) => b.accumulates) ?? []
|
|
126
|
+
const checkoutFields = useMemo(() => checkoutFieldsState?.fields?.filter((field : any) => field.order_type_id === options?.type), [checkoutFieldsState, options])
|
|
124
127
|
|
|
125
128
|
const accumulationRateBusiness = (businessId: number) => {
|
|
126
129
|
const value = loyalBusinessAvailable?.find((loyal: any) => loyal.business_id === businessId)?.accumulation_rate ?? 0
|
|
@@ -169,35 +172,55 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
169
172
|
|
|
170
173
|
const checkValidationFields = () => {
|
|
171
174
|
setUserErrors([])
|
|
172
|
-
const errors = []
|
|
173
|
-
const
|
|
174
|
-
const _requiredFields:
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
175
|
+
const errors: Array<string> = []
|
|
176
|
+
const userSelected = user
|
|
177
|
+
const _requiredFields: Array<string> = []
|
|
178
|
+
Object.values(checkoutFieldsState?.fields).map((field: any) => {
|
|
179
|
+
if (options?.type === field?.order_type_id &&
|
|
180
|
+
field?.enabled &&
|
|
181
|
+
field?.required &&
|
|
182
|
+
!notFields.includes(field?.validation_field?.code)
|
|
183
|
+
) {
|
|
184
|
+
if (userSelected && !userSelected[field?.validation_field?.code]) {
|
|
185
|
+
_requiredFields.push(field?.validation_field?.code)
|
|
180
186
|
}
|
|
181
187
|
}
|
|
182
188
|
})
|
|
183
|
-
|
|
189
|
+
const mobilePhoneField: any = Object.values(checkoutFieldsState?.fields)?.find((field: any) => field?.order_type_id === options?.type && field?.validation_field?.code === 'mobile_phone')
|
|
184
190
|
if (
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
191
|
+
userSelected &&
|
|
192
|
+
!userSelected?.cellphone &&
|
|
193
|
+
((mobilePhoneField?.enabled &&
|
|
194
|
+
mobilePhoneField?.required) ||
|
|
188
195
|
configs?.verification_phone_required?.value === '1')
|
|
189
196
|
) {
|
|
190
197
|
_requiredFields.push('cellphone')
|
|
191
198
|
}
|
|
192
199
|
setRequiredFields(_requiredFields)
|
|
193
200
|
|
|
194
|
-
if (phoneUpdate) {
|
|
195
|
-
errors.push(t('NECESSARY_UPDATE_COUNTRY_PHONE_CODE', 'It is necessary to update your phone number'))
|
|
196
|
-
}
|
|
197
|
-
|
|
198
201
|
setUserErrors(errors)
|
|
199
202
|
}
|
|
200
203
|
|
|
204
|
+
const checkGuestValidationFields = () => {
|
|
205
|
+
const userSelected = user
|
|
206
|
+
const _requiredFields = checkoutFieldsState?.fields
|
|
207
|
+
.filter((field) => (field?.order_type_id === options?.type) && field?.enabled && field?.required_with_guest &&
|
|
208
|
+
!notFields.includes(field?.validation_field?.code) &&
|
|
209
|
+
userSelected && !userSelected[field?.validation_field?.code])
|
|
210
|
+
const requiredFieldsCode = _requiredFields.map((item) => item?.validation_field?.code)
|
|
211
|
+
const guestCheckoutCellPhone = checkoutFieldsState?.fields?.find((field) => field.order_type_id === options?.type && field?.validation_field?.code === 'mobile_phone')
|
|
212
|
+
if (
|
|
213
|
+
userSelected &&
|
|
214
|
+
!userSelected?.cellphone &&
|
|
215
|
+
((guestCheckoutCellPhone?.enabled &&
|
|
216
|
+
guestCheckoutCellPhone?.required_with_guest) ||
|
|
217
|
+
configs?.verification_phone_required?.value === '1')
|
|
218
|
+
) {
|
|
219
|
+
requiredFieldsCode.push('cellphone')
|
|
220
|
+
}
|
|
221
|
+
setRequiredFields(requiredFieldsCode)
|
|
222
|
+
}
|
|
223
|
+
|
|
201
224
|
const togglePhoneUpdate = (val: boolean) => {
|
|
202
225
|
setPhoneUpdate(val)
|
|
203
226
|
}
|
|
@@ -208,7 +231,7 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
208
231
|
return
|
|
209
232
|
}
|
|
210
233
|
|
|
211
|
-
if (!userErrors.length &&
|
|
234
|
+
if (!userErrors.length && !requiredFields?.length) {
|
|
212
235
|
handleGroupPlaceOrder && handleGroupPlaceOrder(confirmPayment)
|
|
213
236
|
return
|
|
214
237
|
}
|
|
@@ -255,10 +278,13 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
255
278
|
}
|
|
256
279
|
|
|
257
280
|
useEffect(() => {
|
|
258
|
-
if (
|
|
281
|
+
if (checkoutFieldsState?.loading || userLoading) return
|
|
282
|
+
if (user?.guest_id) {
|
|
283
|
+
checkGuestValidationFields()
|
|
284
|
+
} else {
|
|
259
285
|
checkValidationFields()
|
|
260
286
|
}
|
|
261
|
-
}, [
|
|
287
|
+
}, [checkoutFieldsState, user, options?.type])
|
|
262
288
|
|
|
263
289
|
useEffect(() => {
|
|
264
290
|
if (cartsToShow?.length === 1) {
|
|
@@ -420,6 +446,9 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
420
446
|
isCheckout
|
|
421
447
|
phoneUpdate={phoneUpdate}
|
|
422
448
|
togglePhoneUpdate={togglePhoneUpdate}
|
|
449
|
+
isOrderTypeValidationField
|
|
450
|
+
requiredFields={requiredFields}
|
|
451
|
+
checkoutFields={checkoutFields}
|
|
423
452
|
/>
|
|
424
453
|
)}
|
|
425
454
|
</ChUserDetails>
|
|
@@ -656,9 +685,12 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
656
685
|
isEdit
|
|
657
686
|
phoneUpdate={phoneUpdate}
|
|
658
687
|
togglePhoneUpdate={togglePhoneUpdate}
|
|
659
|
-
requiredFields={requiredFields}
|
|
660
688
|
hideUpdateButton
|
|
661
689
|
handlePlaceOrderAsGuest={handlePlaceOrderAsGuest}
|
|
690
|
+
isCheckoutPlace
|
|
691
|
+
isOrderTypeValidationField
|
|
692
|
+
requiredFields={requiredFields}
|
|
693
|
+
checkoutFields={checkoutFields}
|
|
662
694
|
onClose={() => {
|
|
663
695
|
setIsOpen(false)
|
|
664
696
|
handlePlaceOrder()
|
|
@@ -47,7 +47,9 @@ const OrderSummaryUI = (props: any) => {
|
|
|
47
47
|
cateringTypes,
|
|
48
48
|
hideDeliveryFee,
|
|
49
49
|
loyaltyRewardRate,
|
|
50
|
-
maxDate
|
|
50
|
+
maxDate,
|
|
51
|
+
hideCommentsByValidationCheckout,
|
|
52
|
+
hideCouponByValidationCheckout
|
|
51
53
|
} = props;
|
|
52
54
|
|
|
53
55
|
const theme = useTheme()
|
|
@@ -55,11 +57,10 @@ const OrderSummaryUI = (props: any) => {
|
|
|
55
57
|
const [{ configs }] = useConfig();
|
|
56
58
|
const [orderState] = useOrder();
|
|
57
59
|
const [{ parsePrice, parseNumber }] = useUtils();
|
|
58
|
-
const [validationFields] = useValidationFields();
|
|
59
60
|
const commentRef = useRef()
|
|
60
61
|
const [openTaxModal, setOpenTaxModal] = useState<any>({ open: false, data: null, type: '' })
|
|
61
|
-
const isCouponEnabled =
|
|
62
|
-
const hideCartComments =
|
|
62
|
+
const isCouponEnabled = hideCouponByValidationCheckout
|
|
63
|
+
const hideCartComments = hideCommentsByValidationCheckout
|
|
63
64
|
|
|
64
65
|
const cart = orderState?.carts?.[`businessId:${props.cart.business_id}`]
|
|
65
66
|
|
|
@@ -35,7 +35,8 @@ const UserDetailsUI = (props: any) => {
|
|
|
35
35
|
handleSendVerifyCode,
|
|
36
36
|
verifyPhoneState,
|
|
37
37
|
setFormState,
|
|
38
|
-
setIsOpen
|
|
38
|
+
setIsOpen,
|
|
39
|
+
isCheckoutPlace
|
|
39
40
|
} = props
|
|
40
41
|
|
|
41
42
|
const theme = useTheme();
|
|
@@ -158,7 +159,7 @@ const UserDetailsUI = (props: any) => {
|
|
|
158
159
|
{t('CUSTOMER_DETAILS', 'Customer Details')}
|
|
159
160
|
</OText>
|
|
160
161
|
)}
|
|
161
|
-
{cartStatus !== 2 && !
|
|
162
|
+
{cartStatus !== 2 && !isCheckoutPlace && (
|
|
162
163
|
!isEdit ? (
|
|
163
164
|
<EditBtn onPress={() => toggleIsEdit()} activeOpacity={0.7}>
|
|
164
165
|
<OIcon
|
|
@@ -38,7 +38,11 @@ export const UserFormDetailsUI = (props: any) => {
|
|
|
38
38
|
isCheckout,
|
|
39
39
|
setIsOpen,
|
|
40
40
|
handleRemoveAccount,
|
|
41
|
-
isProfile
|
|
41
|
+
isProfile,
|
|
42
|
+
isGuest,
|
|
43
|
+
isOrderTypeValidationField,
|
|
44
|
+
checkoutFields,
|
|
45
|
+
isCheckoutPlace
|
|
42
46
|
} = props;
|
|
43
47
|
|
|
44
48
|
const theme = useTheme();
|
|
@@ -97,8 +101,8 @@ export const UserFormDetailsUI = (props: any) => {
|
|
|
97
101
|
const [confirm, setConfirm] = useState<any>({ open: false, content: null, handleOnAccept: null, id: null, title: null })
|
|
98
102
|
|
|
99
103
|
const isAdmin = user?.level === 0
|
|
100
|
-
const showInputPhoneNumber = (validationFields?.fields?.checkout?.cellphone?.enabled ?? false)
|
|
101
|
-
const showInputBirthday = validationFields?.fields?.checkout?.birthdate?.enabled ?? false
|
|
104
|
+
const showInputPhoneNumber = isOrderTypeValidationField ? checkoutFields?.find(field => field?.validation_field?.code === 'mobile_phone')?.enabled : (validationFields?.fields?.checkout?.cellphone?.enabled ?? false)
|
|
105
|
+
const showInputBirthday = isOrderTypeValidationField ? checkoutFields?.find(field => field?.validation_field?.code === 'birthdate')?.enabled : (validationFields?.fields?.checkout?.birthdate?.enabled ?? false)
|
|
102
106
|
|
|
103
107
|
const handleSuccessSignup = (user: any) => {
|
|
104
108
|
login({
|
|
@@ -119,7 +123,7 @@ export const UserFormDetailsUI = (props: any) => {
|
|
|
119
123
|
};
|
|
120
124
|
if (field.code && field.code === 'email') {
|
|
121
125
|
rules.pattern = {
|
|
122
|
-
value:
|
|
126
|
+
value: /[&,()%";:ç?<>{}\\[\]\s]/g,
|
|
123
127
|
message: t('INVALID_ERROR_EMAIL', 'Invalid email address').replace(
|
|
124
128
|
'_attribute_',
|
|
125
129
|
t('EMAIL', 'Email'),
|
|
@@ -129,7 +133,7 @@ export const UserFormDetailsUI = (props: any) => {
|
|
|
129
133
|
return rules;
|
|
130
134
|
};
|
|
131
135
|
|
|
132
|
-
|
|
136
|
+
const cellphoneValue = () => {
|
|
133
137
|
let cellphone = user?.cellphone || null
|
|
134
138
|
if (cellphone && CONDITIONAL_CODES.includes(user?.country_code)) {
|
|
135
139
|
if (user?.country_code === 'PR') {
|
|
@@ -165,8 +169,13 @@ export const UserFormDetailsUI = (props: any) => {
|
|
|
165
169
|
};
|
|
166
170
|
|
|
167
171
|
const onSubmit = () => {
|
|
172
|
+
let content = ''
|
|
173
|
+
if (requiredFields?.includes?.('birthdate') && !birthdate) {
|
|
174
|
+
content = content + `${t('VALIDATION_ERROR_BIRTHDATE_REQUIRED', 'Birthdate is required')}\n`
|
|
175
|
+
}
|
|
168
176
|
if (phoneInputData.error) {
|
|
169
|
-
|
|
177
|
+
content = content + `${phoneInputData.error}\n`
|
|
178
|
+
showToast(ToastType.Error, content);
|
|
170
179
|
return;
|
|
171
180
|
}
|
|
172
181
|
if (Object.keys(formState.changes).length > 0) {
|
|
@@ -176,15 +185,14 @@ export const UserFormDetailsUI = (props: any) => {
|
|
|
176
185
|
validationFields?.fields?.checkout?.cellphone?.required) ||
|
|
177
186
|
configs?.verification_phone_required?.value === '1')
|
|
178
187
|
) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
t(
|
|
182
|
-
'VALIDATION_ERROR_MOBILE_PHONE_REQUIRED',
|
|
183
|
-
'The field Phone Number is required.',
|
|
184
|
-
),
|
|
185
|
-
);
|
|
188
|
+
content = content + `${t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Phone Number is required.',)}\n`
|
|
189
|
+
showToast(ToastType.Error, content);
|
|
186
190
|
return;
|
|
187
191
|
}
|
|
192
|
+
if (content.length > 0) {
|
|
193
|
+
showToast(ToastType.Error, content);
|
|
194
|
+
return
|
|
195
|
+
}
|
|
188
196
|
let changes = null;
|
|
189
197
|
if (user?.cellphone && !userPhoneNumber) {
|
|
190
198
|
changes = {
|
|
@@ -310,16 +318,16 @@ export const UserFormDetailsUI = (props: any) => {
|
|
|
310
318
|
<>
|
|
311
319
|
<UDForm>
|
|
312
320
|
{!validationFields?.loading &&
|
|
313
|
-
sortInputFields({ values: validationFields?.fields?.checkout })
|
|
321
|
+
sortInputFields({ values: isOrderTypeValidationField ? checkoutFields : validationFields?.fields?.checkout })
|
|
314
322
|
.length > 0 && (
|
|
315
323
|
<UDWrapper>
|
|
316
324
|
{sortInputFields({
|
|
317
|
-
values: validationFields
|
|
325
|
+
values: isOrderTypeValidationField ? checkoutFields : validationFields?.fields?.checkout,
|
|
318
326
|
}).map(
|
|
319
327
|
(item: any) => {
|
|
320
328
|
const field = item?.validation_field || item
|
|
321
|
-
return (
|
|
322
|
-
showField(field.code) && ((requiredFields && requiredFields?.includes?.(field.code)) || !requiredFields) && (
|
|
329
|
+
return (
|
|
330
|
+
((isOrderTypeValidationField ? item?.enabled : (showField && showField(field.code))) && ((requiredFields && requiredFields?.includes?.(field.code)) || !requiredFields || !isCheckoutPlace)) && (
|
|
323
331
|
<React.Fragment key={field.id}>
|
|
324
332
|
<Controller
|
|
325
333
|
key={field.id}
|
|
@@ -393,46 +401,51 @@ export const UserFormDetailsUI = (props: any) => {
|
|
|
393
401
|
))
|
|
394
402
|
},
|
|
395
403
|
)}
|
|
396
|
-
{
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
{birthdate ? moment(birthdate).format('YYYY-MM-DD') : ''}
|
|
404
|
+
{((!user?.guest_id && showInputBirthday) || (isOrderTypeValidationField || user?.guest_id)) &&
|
|
405
|
+
showInputBirthday &&
|
|
406
|
+
((requiredFields && requiredFields?.includes?.('birthdate')) || !requiredFields || !isCheckoutPlace) &&
|
|
407
|
+
(
|
|
408
|
+
<>
|
|
409
|
+
<WrapperBirthdate>
|
|
410
|
+
<OText size={14} lineHeight={21} color={theme.colors.textNormal} weight={'500'} style={{ textTransform: 'capitalize', alignSelf: 'flex-start' }}>
|
|
411
|
+
{t('BIRTHDATE', 'Birthdate')}
|
|
405
412
|
</OText>
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
413
|
+
<TouchableOpacity onPress={() => setShowDatePicker(!showDatePicker)}>
|
|
414
|
+
<OText size={14} lineHeight={21} color={theme.colors.textNormal} weight={'500'} style={{ marginTop: 6 }}>
|
|
415
|
+
{birthdate ? moment(birthdate).format('YYYY-MM-DD') : ''}
|
|
416
|
+
</OText>
|
|
417
|
+
</TouchableOpacity>
|
|
418
|
+
</WrapperBirthdate>
|
|
419
|
+
<DatePickerUI open={showDatePicker} birthdate={birthdate} onConfirm={_handleChangeDate} onCancel={() => setShowDatePicker(false)} />
|
|
420
|
+
</>
|
|
421
|
+
)}
|
|
422
|
+
{((!user?.guest_id && !!showInputPhoneNumber) || (isOrderTypeValidationField || user?.guest_id)) &&
|
|
423
|
+
((requiredFields && requiredFields?.includes?.('cellphone')) || !requiredFields || !isCheckoutPlace) &&
|
|
424
|
+
(
|
|
425
|
+
<WrapperPhone>
|
|
426
|
+
<OText size={14} lineHeight={21} weight={'500'} color={theme.colors.textNormal}>{t('PHONE', 'Phone')}</OText>
|
|
427
|
+
<PhoneInputNumber
|
|
428
|
+
data={phoneInputData}
|
|
429
|
+
handleData={(val: any) => handleChangePhoneNumber(val)}
|
|
430
|
+
changeCountry={(val: any) => changeCountry(val)}
|
|
431
|
+
defaultValue={phoneUpdate ? '' : cellphoneValue()}
|
|
432
|
+
defaultCode={user?.country_code ?? user?.country_phone_code ?? null}
|
|
433
|
+
boxStyle={styles.phoneSelect}
|
|
434
|
+
inputStyle={styles.phoneInputStyle}
|
|
435
|
+
textStyle={{ color: theme.colors.textNormal, fontSize: 12, padding: 0 }}
|
|
436
|
+
noDropIcon
|
|
437
|
+
/>
|
|
438
|
+
{phoneUpdate && (
|
|
439
|
+
<OText
|
|
440
|
+
size={10}
|
|
441
|
+
color={theme.colors.error}
|
|
442
|
+
style={{ marginHorizontal: 10, textAlign: 'center' }}>
|
|
443
|
+
{t('YOUR_PREVIOUS_CELLPHONE', 'Your previous cellphone')}:{' '}
|
|
444
|
+
{cellphoneValue()}
|
|
445
|
+
</OText>
|
|
446
|
+
)}
|
|
447
|
+
</WrapperPhone>
|
|
448
|
+
)}
|
|
436
449
|
{!requiredFields && (
|
|
437
450
|
<Controller
|
|
438
451
|
control={control}
|
|
@@ -505,7 +518,7 @@ export const UserFormDetailsUI = (props: any) => {
|
|
|
505
518
|
)}
|
|
506
519
|
</>
|
|
507
520
|
)}
|
|
508
|
-
{
|
|
521
|
+
{isCheckoutPlace && (
|
|
509
522
|
<OButton
|
|
510
523
|
text={
|
|
511
524
|
formState.loading
|
|
@@ -531,10 +544,10 @@ export const UserFormDetailsUI = (props: any) => {
|
|
|
531
544
|
borderColor: !user?.guest_id && (formState.loading || !isValid) ? theme.colors.white : theme.colors.primary,
|
|
532
545
|
opacity: !user?.guest_id && (formState.loading || !isValid) ? 0.3 : 1,
|
|
533
546
|
}}
|
|
534
|
-
onClick={
|
|
547
|
+
onClick={handleSubmit(onSubmit)}
|
|
535
548
|
/>
|
|
536
549
|
)}
|
|
537
|
-
{isCheckout && !!user?.guest_id && (
|
|
550
|
+
{isCheckout && !!user?.guest_id && !requiredFields && (
|
|
538
551
|
<TouchableOpacity style={{ marginTop: 10 }} onPress={() => handlePlaceOrderAsGuest()}>
|
|
539
552
|
<OText color={theme.colors.primary} style={{ textAlign: 'center' }}>{t('PLACE_ORDER_AS_GUEST', 'Place order as guest')}</OText>
|
|
540
553
|
</TouchableOpacity>
|