ordering-ui-external 2.2.2 → 2.3.1
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/_bundles/{0.ordering-ui.da916a51373ae7f6cfcc.js → 0.ordering-ui.c46aca08b04b2755b967.js} +1 -1
- package/_bundles/{1.ordering-ui.da916a51373ae7f6cfcc.js → 1.ordering-ui.c46aca08b04b2755b967.js} +1 -1
- package/_bundles/{2.ordering-ui.da916a51373ae7f6cfcc.js → 2.ordering-ui.c46aca08b04b2755b967.js} +1 -1
- package/_bundles/{4.ordering-ui.da916a51373ae7f6cfcc.js → 4.ordering-ui.c46aca08b04b2755b967.js} +1 -1
- package/_bundles/{5.ordering-ui.da916a51373ae7f6cfcc.js → 5.ordering-ui.c46aca08b04b2755b967.js} +1 -1
- package/_bundles/{6.ordering-ui.da916a51373ae7f6cfcc.js → 6.ordering-ui.c46aca08b04b2755b967.js} +1 -1
- package/_bundles/{7.ordering-ui.da916a51373ae7f6cfcc.js → 7.ordering-ui.c46aca08b04b2755b967.js} +2 -2
- package/_bundles/{7.ordering-ui.da916a51373ae7f6cfcc.js.LICENSE.txt → 7.ordering-ui.c46aca08b04b2755b967.js.LICENSE.txt} +0 -0
- package/_bundles/{8.ordering-ui.da916a51373ae7f6cfcc.js → 8.ordering-ui.c46aca08b04b2755b967.js} +1 -1
- package/_bundles/{9.ordering-ui.da916a51373ae7f6cfcc.js → 9.ordering-ui.c46aca08b04b2755b967.js} +1 -1
- package/_bundles/ordering-ui.c46aca08b04b2755b967.js +2 -0
- package/_bundles/{ordering-ui.da916a51373ae7f6cfcc.js.LICENSE.txt → ordering-ui.c46aca08b04b2755b967.js.LICENSE.txt} +0 -0
- package/_modules/components/PaymentOptions/index.js +42 -2
- package/_modules/index.js +7 -0
- package/_modules/themes/five/index.js +7 -0
- package/_modules/themes/five/src/components/BusinessProductsListing/index.js +1 -4
- package/_modules/themes/five/src/components/Cart/index.js +6 -2
- package/_modules/themes/five/src/components/Cart/styles.js +1 -1
- package/_modules/themes/five/src/components/Checkout/index.js +142 -42
- package/_modules/themes/five/src/components/Checkout/styles.js +5 -3
- package/_modules/themes/five/src/components/InputPhoneNumber/index.js +10 -21
- package/_modules/themes/five/src/components/LoginForm/index.js +29 -13
- package/_modules/themes/five/src/components/MultiCheckout/index.js +5 -1
- package/_modules/themes/five/src/components/QueryLoginSpoonity/index.js +37 -0
- package/_modules/themes/five/src/components/SignUpForm/index.js +15 -7
- package/_modules/themes/five/src/components/Wallets/index.js +1 -1
- package/_modules/themes/five/src/styles/Buttons/index.js +32 -2
- package/package.json +2 -2
- package/src/components/PaymentOptions/index.js +35 -2
- package/src/index.js +2 -0
- package/src/themes/five/index.js +2 -1
- package/src/themes/five/src/components/BusinessProductsListing/index.js +3 -2
- package/src/themes/five/src/components/Cart/index.js +10 -1
- package/src/themes/five/src/components/Cart/styles.js +5 -0
- package/src/themes/five/src/components/Checkout/index.js +141 -54
- package/src/themes/five/src/components/Checkout/styles.js +15 -0
- package/src/themes/five/src/components/InputPhoneNumber/index.js +33 -38
- package/src/themes/five/src/components/LoginForm/index.js +27 -10
- package/src/themes/five/src/components/MultiCheckout/index.js +11 -2
- package/src/themes/five/src/components/QueryLoginSpoonity/index.js +19 -0
- package/src/themes/five/src/components/SignUpForm/index.js +9 -1
- package/src/themes/five/src/components/Wallets/index.js +1 -1
- package/src/themes/five/src/styles/Buttons/index.js +24 -0
- package/template/app.js +22 -7
- package/_bundles/ordering-ui.da916a51373ae7f6cfcc.js +0 -2
|
@@ -71,7 +71,8 @@ const CartUI = (props) => {
|
|
|
71
71
|
hideDeliveryFee,
|
|
72
72
|
hideDriverTip,
|
|
73
73
|
hideCouponInput,
|
|
74
|
-
businessConfigs
|
|
74
|
+
businessConfigs,
|
|
75
|
+
loyaltyRewardRate
|
|
75
76
|
} = props
|
|
76
77
|
|
|
77
78
|
const theme = useTheme()
|
|
@@ -128,6 +129,8 @@ const CartUI = (props) => {
|
|
|
128
129
|
}
|
|
129
130
|
}
|
|
130
131
|
|
|
132
|
+
const loyaltyRewardValue = Math.round(cart?.subtotal / loyaltyRewardRate)
|
|
133
|
+
|
|
131
134
|
const momentFormatted = !orderState?.option?.moment
|
|
132
135
|
? t('RIGHT_NOW', 'Right Now')
|
|
133
136
|
: parseDate(orderState?.option?.moment, { outputFormat: 'YYYY-MM-DD HH:mm' })
|
|
@@ -515,6 +518,12 @@ const CartUI = (props) => {
|
|
|
515
518
|
<td>{t('TOTAL', 'Total')}</td>
|
|
516
519
|
<td>{parsePrice(cart?.total >= 0 ? cart?.total : 0)}</td>
|
|
517
520
|
</tr>
|
|
521
|
+
{!!loyaltyRewardValue && isFinite(loyaltyRewardValue) && (
|
|
522
|
+
<tr>
|
|
523
|
+
<td> </td>
|
|
524
|
+
<td id='loyalty'>{t('REWARD_LOYALTY_POINT', 'Reward :amount: on loyalty points').replace(':amount:', loyaltyRewardValue)}</td>
|
|
525
|
+
</tr>
|
|
526
|
+
)}
|
|
518
527
|
</tbody>
|
|
519
528
|
</table>
|
|
520
529
|
{cart?.status !== 2 && !hideCartComments && (
|
|
@@ -46,7 +46,8 @@ import {
|
|
|
46
46
|
WrapperActionsInput,
|
|
47
47
|
MobileWrapperPlaceOrderButton,
|
|
48
48
|
OrderContextUIWrapper,
|
|
49
|
-
HeaderContent
|
|
49
|
+
HeaderContent,
|
|
50
|
+
AuthButtonList
|
|
50
51
|
} from './styles'
|
|
51
52
|
|
|
52
53
|
import { Button } from '../../styles/Buttons'
|
|
@@ -65,6 +66,8 @@ import { CartContent } from '../CartContent'
|
|
|
65
66
|
import { Select } from '../../styles/Select'
|
|
66
67
|
import { PlaceSpot } from '../PlaceSpot'
|
|
67
68
|
import { OrderContextUI } from '../OrderContextUI'
|
|
69
|
+
import { SignUpForm } from '../SignUpForm'
|
|
70
|
+
import { LoginForm } from '../LoginForm'
|
|
68
71
|
|
|
69
72
|
const mapConfigs = {
|
|
70
73
|
mapZoom: 16,
|
|
@@ -81,6 +84,7 @@ const CheckoutUI = (props) => {
|
|
|
81
84
|
placing,
|
|
82
85
|
cartState,
|
|
83
86
|
useKioskApp,
|
|
87
|
+
loyaltyPlansState,
|
|
84
88
|
businessDetails,
|
|
85
89
|
paymethodSelected,
|
|
86
90
|
handlePaymethodChange,
|
|
@@ -104,7 +108,7 @@ const CheckoutUI = (props) => {
|
|
|
104
108
|
const [{ options, loading }] = useOrder()
|
|
105
109
|
const [, t] = useLanguage()
|
|
106
110
|
const [{ parsePrice }] = useUtils()
|
|
107
|
-
const [{ user }] = useSession()
|
|
111
|
+
const [{ user }, { login }] = useSession()
|
|
108
112
|
const [{ configs }] = useConfig()
|
|
109
113
|
const [customerState] = useCustomer()
|
|
110
114
|
const [events] = useEvent()
|
|
@@ -120,6 +124,9 @@ const CheckoutUI = (props) => {
|
|
|
120
124
|
const [isOpen, setIsOpen] = useState(false)
|
|
121
125
|
const [requiredFields, setRequiredFields] = useState([])
|
|
122
126
|
const [isSuccess, setIsSuccess] = useState(false)
|
|
127
|
+
const [openModal, setOpenModal] = useState({ login: false, signup: false })
|
|
128
|
+
const [allowedGuest, setAllowedGuest] = useState(false)
|
|
129
|
+
const [cardList, setCardList] = useState([])
|
|
123
130
|
|
|
124
131
|
const businessConfigs = businessDetails?.business?.configs ?? []
|
|
125
132
|
const isTableNumberEnabled = configs?.table_numer_enabled?.value
|
|
@@ -135,6 +142,7 @@ const CheckoutUI = (props) => {
|
|
|
135
142
|
|
|
136
143
|
const isDisablePlaceOrderButton = !cart?.valid ||
|
|
137
144
|
(!paymethodSelected && cart?.balance > 0) ||
|
|
145
|
+
(paymethodSelected?.gateway === 'stripe' && cardList?.cards?.length === 0) ||
|
|
138
146
|
placing ||
|
|
139
147
|
errorCash ||
|
|
140
148
|
loading ||
|
|
@@ -164,7 +172,7 @@ const CheckoutUI = (props) => {
|
|
|
164
172
|
const driverTipsField = !cartState.loading && cart && cart?.business_id && options.type === 1 && cart?.status !== 2 && validationFields?.fields?.checkout?.driver_tip?.enabled && driverTipsOptions.length > 0 && !useKioskApp
|
|
165
173
|
|
|
166
174
|
const handlePlaceOrder = () => {
|
|
167
|
-
if (!userErrors.length && !requiredFields?.length) {
|
|
175
|
+
if (!userErrors.length && (!requiredFields?.length || allowedGuest)) {
|
|
168
176
|
const body = {}
|
|
169
177
|
if (behalfName) {
|
|
170
178
|
body.on_behalf_of = behalfName
|
|
@@ -183,6 +191,15 @@ const CheckoutUI = (props) => {
|
|
|
183
191
|
setIsUserDetailsEdit(true)
|
|
184
192
|
}
|
|
185
193
|
|
|
194
|
+
const handlePlaceOrderAsGuest = () => {
|
|
195
|
+
setIsOpen(false)
|
|
196
|
+
const body = {}
|
|
197
|
+
if (behalfName) {
|
|
198
|
+
body.on_behalf_of = behalfName
|
|
199
|
+
}
|
|
200
|
+
handlerClickPlaceOrder && handlerClickPlaceOrder(null, body)
|
|
201
|
+
}
|
|
202
|
+
|
|
186
203
|
const closeAlert = () => {
|
|
187
204
|
setAlertState({
|
|
188
205
|
open: false,
|
|
@@ -233,6 +250,18 @@ const CheckoutUI = (props) => {
|
|
|
233
250
|
setUserErrors(errors)
|
|
234
251
|
}
|
|
235
252
|
|
|
253
|
+
const handleSuccessSignup = (user) => {
|
|
254
|
+
login({
|
|
255
|
+
user,
|
|
256
|
+
token: user?.session?.access_token
|
|
257
|
+
})
|
|
258
|
+
setOpenModal({ ...openModal, signup: false })
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const handleSuccessLogin = (user) => {
|
|
262
|
+
if (user) setOpenModal({ ...openModal, login: false })
|
|
263
|
+
}
|
|
264
|
+
|
|
236
265
|
const handleScrollTo = () => {
|
|
237
266
|
if (!((!paymethodSelected && cart?.balance > 0) && cart?.status !== 2)) return
|
|
238
267
|
const scrollElement = document.querySelector('.paymentsContainer')
|
|
@@ -299,7 +328,7 @@ const CheckoutUI = (props) => {
|
|
|
299
328
|
|
|
300
329
|
{!useKioskApp ? (
|
|
301
330
|
<>
|
|
302
|
-
{cart?.business_id && (
|
|
331
|
+
{cart?.business_id && !hideBusinessMap && (
|
|
303
332
|
<>
|
|
304
333
|
{(businessDetails?.loading || cartState.loading) ? (
|
|
305
334
|
<div style={{ width: '100%', marginBottom: '20px' }}>
|
|
@@ -319,34 +348,51 @@ const CheckoutUI = (props) => {
|
|
|
319
348
|
)}
|
|
320
349
|
</>
|
|
321
350
|
)}
|
|
322
|
-
|
|
323
|
-
<
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
<
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
351
|
+
{!hideCustomerDetails && (
|
|
352
|
+
<UserDetailsContainer>
|
|
353
|
+
<WrapperUserDetails>
|
|
354
|
+
{cartState.loading || (isCustomerMode && !customerState?.user?.id) ? (
|
|
355
|
+
<div>
|
|
356
|
+
<Skeleton height={35} style={{ marginBottom: '10px' }} />
|
|
357
|
+
<Skeleton height={35} style={{ marginBottom: '10px' }} />
|
|
358
|
+
<Skeleton height={35} style={{ marginBottom: '10px' }} />
|
|
359
|
+
<Skeleton height={35} style={{ marginBottom: '10px' }} />
|
|
360
|
+
<Skeleton height={35} style={{ marginBottom: '10px' }} />
|
|
361
|
+
</div>
|
|
362
|
+
) : (
|
|
363
|
+
(user?.guest_id && !allowedGuest) ? (
|
|
364
|
+
<AuthButtonList>
|
|
365
|
+
<h2>{t('CUSTOMER_DETAILS', 'Customer details')}</h2>
|
|
366
|
+
<Button color='primary' onClick={() => setOpenModal({ ...openModal, signup: true })}>
|
|
367
|
+
{t('SIGN_UP', 'Sign up')}
|
|
368
|
+
</Button>
|
|
369
|
+
<Button color='primary' outline onClick={() => setOpenModal({ ...openModal, login: true })}>
|
|
370
|
+
{t('LOGIN', 'Login')}
|
|
371
|
+
</Button>
|
|
372
|
+
<Button color='black' outline onClick={() => setAllowedGuest(true)}>
|
|
373
|
+
{t('CONTINUE_AS_GUEST', 'Continue as guest')}
|
|
374
|
+
</Button>
|
|
375
|
+
</AuthButtonList>
|
|
376
|
+
) : (
|
|
377
|
+
<UserDetails
|
|
378
|
+
isUserDetailsEdit={isUserDetailsEdit}
|
|
379
|
+
cartStatus={cart?.status}
|
|
380
|
+
businessId={cart?.business_id}
|
|
381
|
+
useValidationFields
|
|
382
|
+
useDefualtSessionManager
|
|
383
|
+
useSessionUser={!isCustomerMode}
|
|
384
|
+
isCustomerMode={isCustomerMode}
|
|
385
|
+
userData={isCustomerMode && customerState.user}
|
|
386
|
+
userId={isCustomerMode && customerState?.user?.id}
|
|
387
|
+
isSuccess={isSuccess}
|
|
388
|
+
isCheckout
|
|
389
|
+
/>
|
|
390
|
+
)
|
|
391
|
+
)}
|
|
392
|
+
</WrapperUserDetails>
|
|
393
|
+
</UserDetailsContainer>
|
|
394
|
+
)}
|
|
395
|
+
{cart?.business_id && !hideBusinessDetails && (
|
|
350
396
|
<BusinessDetailsContainer>
|
|
351
397
|
{(businessDetails?.loading || cartState.loading) && !businessDetails?.error && (
|
|
352
398
|
<div>
|
|
@@ -363,7 +409,9 @@ const CheckoutUI = (props) => {
|
|
|
363
409
|
<div>
|
|
364
410
|
<h1>{t('BUSINESS_DETAILS', 'Business Details')}</h1>
|
|
365
411
|
<div>
|
|
366
|
-
|
|
412
|
+
{!hideBusinessAddress && (
|
|
413
|
+
<p>{businessDetails?.business?.address}</p>
|
|
414
|
+
)}
|
|
367
415
|
<p>{businessDetails?.business?.name}</p>
|
|
368
416
|
<p>{businessDetails?.business?.email}</p>
|
|
369
417
|
<p>{businessDetails?.business?.cellphone}</p>
|
|
@@ -446,6 +494,7 @@ const CheckoutUI = (props) => {
|
|
|
446
494
|
paySelected={paymethodSelected}
|
|
447
495
|
handlePlaceOrder={handlePlaceOrder}
|
|
448
496
|
onPlaceOrderClick={onPlaceOrderClick}
|
|
497
|
+
setCardList={setCardList}
|
|
449
498
|
/>
|
|
450
499
|
</PaymentMethodContainer>
|
|
451
500
|
)}
|
|
@@ -454,6 +503,7 @@ const CheckoutUI = (props) => {
|
|
|
454
503
|
<WalletPaymentOptionContainer>
|
|
455
504
|
<PaymentOptionWallet
|
|
456
505
|
cart={cart}
|
|
506
|
+
loyaltyPlansState={loyaltyPlansState}
|
|
457
507
|
businessConfigs={businessDetails?.business?.configs}
|
|
458
508
|
/>
|
|
459
509
|
</WalletPaymentOptionContainer>
|
|
@@ -464,24 +514,24 @@ const CheckoutUI = (props) => {
|
|
|
464
514
|
|
|
465
515
|
{
|
|
466
516
|
!!(!isMultiDriverTips && driverTipsField) &&
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
517
|
+
<>
|
|
518
|
+
<DriverTipContainer>
|
|
519
|
+
<h1>{t('DRIVER_TIPS', 'Driver Tips')}</h1>
|
|
520
|
+
<p>{t('100%_OF_THE_TIP_YOUR_DRIVER', '100% of the tip goes to your driver')}</p>
|
|
521
|
+
<DriverTips
|
|
522
|
+
businessId={cart?.business_id}
|
|
523
|
+
driverTipsOptions={driverTipsOptions}
|
|
524
|
+
isFixedPrice={parseInt(configs?.driver_tip_type?.value, 10) === 1}
|
|
525
|
+
isDriverTipUseCustom={!!parseInt(configs?.driver_tip_use_custom?.value, 10)}
|
|
526
|
+
driverTip={parseInt(configs?.driver_tip_type?.value, 10) === 1
|
|
527
|
+
? cart?.driver_tip
|
|
528
|
+
: cart?.driver_tip_rate}
|
|
529
|
+
cart={cart}
|
|
530
|
+
useOrderContext
|
|
531
|
+
/>
|
|
532
|
+
</DriverTipContainer>
|
|
533
|
+
<DriverTipDivider />
|
|
534
|
+
</>
|
|
485
535
|
}
|
|
486
536
|
{!cartState.loading && placeSpotsEnabled && cart?.business_id && (
|
|
487
537
|
<SelectSpotContainer>
|
|
@@ -510,6 +560,9 @@ const CheckoutUI = (props) => {
|
|
|
510
560
|
useKioskApp={useKioskApp}
|
|
511
561
|
isCheckout
|
|
512
562
|
isProducts={cart?.products?.length || 0}
|
|
563
|
+
viewString='checkout'
|
|
564
|
+
businessConfigs={businessConfigs}
|
|
565
|
+
loyaltyRewardRate={loyaltyPlansState?.result?.find(loyal => loyal.type === 'credit_point')?.accumulation_rate ?? 0}
|
|
513
566
|
/>
|
|
514
567
|
</CartContainer>
|
|
515
568
|
)}
|
|
@@ -578,9 +631,15 @@ const CheckoutUI = (props) => {
|
|
|
578
631
|
validationFields?.fields?.checkout?.driver_tip?.enabled &&
|
|
579
632
|
validationFields?.fields?.checkout?.driver_tip?.required &&
|
|
580
633
|
(Number(cart?.driver_tip) <= 0) &&
|
|
581
|
-
|
|
634
|
+
(
|
|
635
|
+
<WarningText>
|
|
636
|
+
{t('WARNING_INVALID_DRIVER_TIP', 'Driver Tip is required.')}
|
|
637
|
+
</WarningText>
|
|
638
|
+
)}
|
|
639
|
+
|
|
640
|
+
{!cart?.valid_preorder && (
|
|
582
641
|
<WarningText>
|
|
583
|
-
{t('
|
|
642
|
+
{t('INVALID_CART_MOMENT', 'Selected schedule time is invalid, please select a schedule into the business schedule interval.')}
|
|
584
643
|
</WarningText>
|
|
585
644
|
)}
|
|
586
645
|
</WrapperRightContainer>
|
|
@@ -630,12 +689,39 @@ const CheckoutUI = (props) => {
|
|
|
630
689
|
isCheckout
|
|
631
690
|
isEdit
|
|
632
691
|
isModal
|
|
692
|
+
handlePlaceOrderAsGuest={handlePlaceOrderAsGuest}
|
|
633
693
|
onClose={() => {
|
|
634
694
|
setIsOpen(false)
|
|
635
695
|
handlePlaceOrder()
|
|
636
696
|
}}
|
|
637
697
|
/>
|
|
638
698
|
</Modal>
|
|
699
|
+
<Modal
|
|
700
|
+
open={openModal.signup}
|
|
701
|
+
width='760px'
|
|
702
|
+
padding='30px'
|
|
703
|
+
onClose={() => setOpenModal({ ...openModal, signup: false })}
|
|
704
|
+
>
|
|
705
|
+
<SignUpForm
|
|
706
|
+
useLoginByCellphone
|
|
707
|
+
useChekoutFileds
|
|
708
|
+
handleSuccessSignup={handleSuccessSignup}
|
|
709
|
+
isPopup
|
|
710
|
+
isGuest
|
|
711
|
+
/>
|
|
712
|
+
</Modal>
|
|
713
|
+
<Modal
|
|
714
|
+
open={openModal.login}
|
|
715
|
+
width='760px'
|
|
716
|
+
padding='30px'
|
|
717
|
+
onClose={() => setOpenModal({ ...openModal, login: false })}
|
|
718
|
+
>
|
|
719
|
+
<LoginForm
|
|
720
|
+
handleSuccessLogin={handleSuccessLogin}
|
|
721
|
+
isPopup
|
|
722
|
+
isGuest
|
|
723
|
+
/>
|
|
724
|
+
</Modal>
|
|
639
725
|
</Container>
|
|
640
726
|
)
|
|
641
727
|
}
|
|
@@ -719,7 +805,8 @@ export const Checkout = (props) => {
|
|
|
719
805
|
method: 'GET',
|
|
720
806
|
headers: {
|
|
721
807
|
'Content-Type': 'application/json',
|
|
722
|
-
Authorization: `Bearer ${token}
|
|
808
|
+
Authorization: `Bearer ${token}`,
|
|
809
|
+
'X-App-X': ordering.appId
|
|
723
810
|
}
|
|
724
811
|
})
|
|
725
812
|
const content = await response.json()
|
|
@@ -334,3 +334,18 @@ export const HeaderContent = styled.div`
|
|
|
334
334
|
cursor: pointer;
|
|
335
335
|
}
|
|
336
336
|
`
|
|
337
|
+
|
|
338
|
+
export const AuthButtonList = styled.div`
|
|
339
|
+
display: flex;
|
|
340
|
+
flex-direction: column;
|
|
341
|
+
h2 {
|
|
342
|
+
font-weight: 600;
|
|
343
|
+
font-size: 20px;
|
|
344
|
+
margin-bottom: 3px;
|
|
345
|
+
}
|
|
346
|
+
button {
|
|
347
|
+
width: 100%;
|
|
348
|
+
height: 44px;
|
|
349
|
+
margin-top: 22px;
|
|
350
|
+
}
|
|
351
|
+
`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect } from 'react'
|
|
1
|
+
import React, { useEffect, useRef } from 'react'
|
|
2
2
|
import parsePhoneNumber from 'libphonenumber-js'
|
|
3
3
|
import PhoneInput from 'react-phone-number-input'
|
|
4
4
|
import BsPhone from '@meronex/icons/bs/BsPhone'
|
|
@@ -13,13 +13,17 @@ export const InputPhoneNumber = (props) => {
|
|
|
13
13
|
setValue,
|
|
14
14
|
handleIsValid,
|
|
15
15
|
disabled,
|
|
16
|
-
isError
|
|
16
|
+
isError,
|
|
17
|
+
currentCountryCode,
|
|
18
|
+
setCurrentPhoneNumber
|
|
17
19
|
} = props
|
|
18
20
|
|
|
19
21
|
const [, t] = useLanguage()
|
|
20
22
|
const [{ auth }] = useSession()
|
|
21
23
|
const [{ configs }] = useConfig()
|
|
22
24
|
|
|
25
|
+
const phoneRef = useRef(null)
|
|
26
|
+
|
|
23
27
|
const isValidPhoneNumber = (number) => {
|
|
24
28
|
if (!number) return
|
|
25
29
|
if (!parseInt(configs?.validation_phone_number_lib?.value ?? 1, 10)) {
|
|
@@ -31,49 +35,40 @@ export const InputPhoneNumber = (props) => {
|
|
|
31
35
|
|
|
32
36
|
useEffect(() => {
|
|
33
37
|
if (value) {
|
|
38
|
+
setCurrentPhoneNumber &&
|
|
39
|
+
setCurrentPhoneNumber(
|
|
40
|
+
`+${currentCountryCode} ${phoneRef?.current?.defaultValue?.replace(/ /g, '')}`
|
|
41
|
+
)
|
|
34
42
|
handleIsValid && handleIsValid(isValidPhoneNumber(value))
|
|
35
43
|
}
|
|
36
44
|
}, [value])
|
|
37
45
|
|
|
38
46
|
return (
|
|
39
47
|
<Container className='phone_number' disabled={disabled} isValid={value ? isValidPhoneNumber(value) : true} isError={isError}>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
{
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
/>
|
|
59
|
-
{value && !isValidPhoneNumber(value) && !disabled && (
|
|
60
|
-
<>
|
|
61
|
-
{((auth && user?.country_phone_code) || !auth || value.includes('+')) && (
|
|
62
|
-
<ErrorMsg>{t('INVALID_ERROR_PHONE_NUMBER', 'The Phone Number field is invalid')}</ErrorMsg>
|
|
63
|
-
)}
|
|
48
|
+
<InputBeforeIconWrapper>
|
|
49
|
+
<BsPhone />
|
|
50
|
+
</InputBeforeIconWrapper>
|
|
51
|
+
<PhoneInput
|
|
52
|
+
ref={phoneRef}
|
|
53
|
+
disabled={disabled}
|
|
54
|
+
placeholder={t('PHONE_NUMBER', 'Phone number')}
|
|
55
|
+
defaultCountry={configs?.default_country_code?.value}
|
|
56
|
+
value={value}
|
|
57
|
+
name='telefono'
|
|
58
|
+
displayInitialValueAsLocalNumber
|
|
59
|
+
onChange={(val) => setValue && setValue(val, isValidPhoneNumber(val))}
|
|
60
|
+
/>
|
|
61
|
+
{value && !isValidPhoneNumber(value) && !disabled && (
|
|
62
|
+
<>
|
|
63
|
+
{((auth && user?.country_phone_code) || !auth || value.includes('+')) && (
|
|
64
|
+
<ErrorMsg>{t('INVALID_ERROR_PHONE_NUMBER', 'The Phone Number field is invalid')}</ErrorMsg>
|
|
65
|
+
)}
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
{props.afterComponents?.map((AfterComponent, i) => (
|
|
71
|
-
<AfterComponent key={i} {...props} />))}
|
|
72
|
-
{props.afterElements?.map((AfterElement, i) => (
|
|
73
|
-
<React.Fragment key={i}>
|
|
74
|
-
{AfterElement}
|
|
75
|
-
</React.Fragment>))}
|
|
76
|
-
</>
|
|
67
|
+
{auth && !user?.country_phone_code && !value.includes('+') && (
|
|
68
|
+
<ErrorMsg>{t('INVALID_ERROR_COUNTRY_CODE_PHONE_NUMBER', 'The country code of the phone number is invalid')}</ErrorMsg>
|
|
69
|
+
)}
|
|
70
|
+
</>
|
|
71
|
+
)}
|
|
77
72
|
</Container>
|
|
78
73
|
)
|
|
79
74
|
}
|
|
@@ -86,7 +86,9 @@ const LoginFormUI = (props) => {
|
|
|
86
86
|
otpState,
|
|
87
87
|
setOtpState,
|
|
88
88
|
useLoginOtpEmail,
|
|
89
|
-
useLoginOtpCellphone
|
|
89
|
+
useLoginOtpCellphone,
|
|
90
|
+
handleLoginSpoonity,
|
|
91
|
+
useLoginSpoonity
|
|
90
92
|
} = props
|
|
91
93
|
const numOtpInputs = loginTab === 'otp' ? 6 : 4
|
|
92
94
|
const [ordering, { setOrdering }] = useApi()
|
|
@@ -120,6 +122,8 @@ const LoginFormUI = (props) => {
|
|
|
120
122
|
const facebookLoginEnabled = configs?.facebook_login_enabled?.value === '1' || !configs?.facebook_login_enabled?.enabled
|
|
121
123
|
const appleLoginEnabled = configs?.apple_login_enabled?.value === '1' || !configs?.apple_login_enabled?.enabled
|
|
122
124
|
|
|
125
|
+
const spoonityTitle = configs?.spoonity_title?.value
|
|
126
|
+
|
|
123
127
|
const hasSocialLogin = (
|
|
124
128
|
(configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') && configs?.facebook_id?.value) ||
|
|
125
129
|
(configs?.google_login_client_id?.value && configs?.google_login_auth_domain?.value && configs?.google_login_api_key?.value && googleLoginEnabled) ||
|
|
@@ -154,6 +158,10 @@ const LoginFormUI = (props) => {
|
|
|
154
158
|
setSubmitted(true)
|
|
155
159
|
return
|
|
156
160
|
}
|
|
161
|
+
if (loginTab === 'spoonity') {
|
|
162
|
+
handleLoginSpoonity()
|
|
163
|
+
return
|
|
164
|
+
}
|
|
157
165
|
handleButtonLoginClick()
|
|
158
166
|
}
|
|
159
167
|
}
|
|
@@ -243,6 +251,12 @@ const LoginFormUI = (props) => {
|
|
|
243
251
|
setOtpType(type)
|
|
244
252
|
}
|
|
245
253
|
|
|
254
|
+
const preventWhiteSpaceOnKeyDown = (e) => {
|
|
255
|
+
if (e.key === ' ') {
|
|
256
|
+
e.preventDefault()
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
246
260
|
useEffect(() => {
|
|
247
261
|
if (!formState.loading && formState.result?.error) {
|
|
248
262
|
if (formState.result?.result?.[0] === 'ERROR_AUTH_VERIFICATION_CODE') {
|
|
@@ -346,12 +360,6 @@ const LoginFormUI = (props) => {
|
|
|
346
360
|
}
|
|
347
361
|
}, [recaptchaConfig])
|
|
348
362
|
|
|
349
|
-
const preventWhiteSpaceOnKeyDown = (e) => {
|
|
350
|
-
if (e.key === " ") {
|
|
351
|
-
e.preventDefault()
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
363
|
return (
|
|
356
364
|
<>
|
|
357
365
|
{props.beforeElements?.map((BeforeElement, i) => (
|
|
@@ -375,7 +383,7 @@ const LoginFormUI = (props) => {
|
|
|
375
383
|
<Title>{t('LOGIN', 'Login')}</Title>
|
|
376
384
|
)}
|
|
377
385
|
|
|
378
|
-
{((Number(useLoginByEmail) + Number(useLoginByCellphone) + Number(useLoginOtpEmail) + Number(useLoginOtpCellphone) > 1) && !loginWithOtpState && !willVerifyOtpState) && (
|
|
386
|
+
{((Number(useLoginByEmail) + Number(useLoginByCellphone) + Number(useLoginOtpEmail) + Number(useLoginOtpCellphone) + Number(useLoginSpoonity) > 1) && !loginWithOtpState && !willVerifyOtpState) && (
|
|
379
387
|
<LoginWith isPopup={isPopup}>
|
|
380
388
|
<Tabs variant='primary'>
|
|
381
389
|
{useLoginByEmail && (
|
|
@@ -414,6 +422,15 @@ const LoginFormUI = (props) => {
|
|
|
414
422
|
{t('BY_OTP_CELLPHONE', 'by Otp Cellphone')}
|
|
415
423
|
</Tab>
|
|
416
424
|
)}
|
|
425
|
+
{useLoginSpoonity && (
|
|
426
|
+
<Tab
|
|
427
|
+
onClick={() => handleChangeTab('spoonity')}
|
|
428
|
+
active={loginTab === 'spoonity'}
|
|
429
|
+
borderBottom={loginTab === 'spoonity'}
|
|
430
|
+
>
|
|
431
|
+
{spoonityTitle || t('BY_SPOONITY', 'by Spoonity')}
|
|
432
|
+
</Tab>
|
|
433
|
+
)}
|
|
417
434
|
</Tabs>
|
|
418
435
|
</LoginWith>
|
|
419
436
|
)}
|
|
@@ -455,7 +472,7 @@ const LoginFormUI = (props) => {
|
|
|
455
472
|
</InputBeforeIcon>
|
|
456
473
|
</InputWrapper>
|
|
457
474
|
)}
|
|
458
|
-
{(((useLoginByEmail && loginTab === 'email') || (loginTab === 'otp' && otpType === 'email')) && !willVerifyOtpState) && (
|
|
475
|
+
{(((useLoginByEmail && loginTab === 'email') || (loginTab === 'otp' && otpType === 'email') || (useLoginSpoonity && loginTab === 'spoonity')) && !willVerifyOtpState) && (
|
|
459
476
|
<>
|
|
460
477
|
{formMethods?.errors?.email?.type === 'required' && (
|
|
461
478
|
<ValidationText>
|
|
@@ -474,7 +491,7 @@ const LoginFormUI = (props) => {
|
|
|
474
491
|
aria-label='email'
|
|
475
492
|
placeholder={t('EMAIL', 'Email')}
|
|
476
493
|
ref={formMethods.register({
|
|
477
|
-
required: loginTab === 'email'
|
|
494
|
+
required: loginTab === 'email' || loginTab === 'spoonity'
|
|
478
495
|
? t('VALIDATION_ERROR_EMAIL_REQUIRED', 'The field Email is required').replace('_attribute_', t('EMAIL', 'Email'))
|
|
479
496
|
: null,
|
|
480
497
|
pattern: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import React, { useState, useEffect } from 'react'
|
|
2
2
|
import { useHistory } from 'react-router-dom'
|
|
3
3
|
import {
|
|
4
|
+
MultiCheckout as MultiCheckoutController,
|
|
4
5
|
useLanguage,
|
|
5
6
|
useUtils,
|
|
6
7
|
useCustomer,
|
|
7
8
|
useConfig,
|
|
8
9
|
useSession,
|
|
9
10
|
useValidationFields,
|
|
10
|
-
useOrder
|
|
11
|
-
MultiCheckout as MultiCheckoutController
|
|
11
|
+
useOrder
|
|
12
12
|
} from 'ordering-components-external'
|
|
13
13
|
|
|
14
14
|
import parsePhoneNumber from 'libphonenumber-js'
|
|
@@ -54,6 +54,7 @@ const MultiCheckoutUI = (props) => {
|
|
|
54
54
|
placing,
|
|
55
55
|
isCustomerMode,
|
|
56
56
|
openCarts,
|
|
57
|
+
rewardRate,
|
|
57
58
|
totalCartsPrice,
|
|
58
59
|
handleGroupPlaceOrder,
|
|
59
60
|
paymethodSelected,
|
|
@@ -89,6 +90,8 @@ const MultiCheckoutUI = (props) => {
|
|
|
89
90
|
? JSON.parse(configs?.driver_tip_options?.value) || []
|
|
90
91
|
: configs?.driver_tip_options?.value || []
|
|
91
92
|
|
|
93
|
+
const loyaltyRewardValue = Math.round(openCarts.reduce((sum, cart) => sum + cart?.subtotal, 0) / rewardRate)
|
|
94
|
+
|
|
92
95
|
const handlePlaceOrder = () => {
|
|
93
96
|
if (!userErrors.length) {
|
|
94
97
|
handleGroupPlaceOrder && handleGroupPlaceOrder()
|
|
@@ -301,6 +304,12 @@ const MultiCheckoutUI = (props) => {
|
|
|
301
304
|
<h4>{t('TOTAL_FOR_ALL_CARTS', 'Total for all Carts')}</h4>
|
|
302
305
|
<h4>{parsePrice(totalCartsPrice)}</h4>
|
|
303
306
|
</div>
|
|
307
|
+
{!!loyaltyRewardValue && isFinite(loyaltyRewardValue) && (
|
|
308
|
+
<span>
|
|
309
|
+
<p> </p>
|
|
310
|
+
<p>{t('REWARD_LOYALTY_POINT', 'Reward :amount: on loyalty points').replace(':amount:', loyaltyRewardValue)}</p>
|
|
311
|
+
</span>
|
|
312
|
+
)}
|
|
304
313
|
<p>
|
|
305
314
|
{t('MULTI_CHECKOUT_DESCRIPTION', 'You will receive a receipt for each business. The payment is not combined between multiple stores. Each payment is processed by the store')}
|
|
306
315
|
</p>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { QueryLoginSpoonity as QueryLoginSpoonityController, useLanguage } from 'ordering-components-external'
|
|
3
|
+
import { SpinnerLoader } from '../../../../../components/SpinnerLoader'
|
|
4
|
+
|
|
5
|
+
const QueryLoginSpoonityUI = (props) => {
|
|
6
|
+
const [, t] = useLanguage()
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<SpinnerLoader content={t('LOADING_DELICIOUS_FOOD', 'Loading Ordering Dashboard...')} />
|
|
10
|
+
)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const QueryLoginSpoonity = (props) => {
|
|
14
|
+
const queryProps = {
|
|
15
|
+
...props,
|
|
16
|
+
UIComponent: QueryLoginSpoonityUI
|
|
17
|
+
}
|
|
18
|
+
return <QueryLoginSpoonityController {...queryProps} />
|
|
19
|
+
}
|