ordering-ui-external 14.1.80 → 14.1.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/_bundles/{0.ordering-ui.d155a03b9a727f188284.js → 0.ordering-ui.946f2a2986a6d1d2dcdf.js} +1 -1
  2. package/_bundles/{1.ordering-ui.d155a03b9a727f188284.js → 1.ordering-ui.946f2a2986a6d1d2dcdf.js} +1 -1
  3. package/_bundles/{2.ordering-ui.d155a03b9a727f188284.js → 2.ordering-ui.946f2a2986a6d1d2dcdf.js} +1 -1
  4. package/_bundles/{4.ordering-ui.d155a03b9a727f188284.js → 4.ordering-ui.946f2a2986a6d1d2dcdf.js} +1 -1
  5. package/_bundles/{5.ordering-ui.d155a03b9a727f188284.js → 5.ordering-ui.946f2a2986a6d1d2dcdf.js} +1 -1
  6. package/_bundles/{6.ordering-ui.d155a03b9a727f188284.js → 6.ordering-ui.946f2a2986a6d1d2dcdf.js} +1 -1
  7. package/_bundles/{7.ordering-ui.d155a03b9a727f188284.js → 7.ordering-ui.946f2a2986a6d1d2dcdf.js} +2 -2
  8. package/_bundles/{8.ordering-ui.d155a03b9a727f188284.js → 8.ordering-ui.946f2a2986a6d1d2dcdf.js} +1 -1
  9. package/_bundles/{9.ordering-ui.d155a03b9a727f188284.js → 9.ordering-ui.946f2a2986a6d1d2dcdf.js} +1 -1
  10. package/_bundles/ordering-ui.946f2a2986a6d1d2dcdf.js +2 -0
  11. package/_modules/styles/Toast/index.js +1 -1
  12. package/_modules/themes/five/index.js +7 -0
  13. package/_modules/themes/five/src/components/Checkout/index.js +34 -4
  14. package/_modules/themes/five/src/components/InputPhoneNumber/index.js +3 -1
  15. package/_modules/themes/five/src/components/Modal/index.js +2 -1
  16. package/_modules/themes/five/src/components/PaymentOptionStripeLink/index.js +293 -0
  17. package/_modules/themes/five/src/components/PaymentOptionStripeLink/styles.js +28 -0
  18. package/_modules/themes/five/src/components/PaymentOptions/index.js +1 -1
  19. package/_modules/utils/index.js +2 -1
  20. package/package.json +2 -2
  21. package/src/styles/Toast/index.js +1 -1
  22. package/src/themes/five/index.js +2 -0
  23. package/src/themes/five/src/components/Checkout/index.js +30 -2
  24. package/src/themes/five/src/components/InputPhoneNumber/index.js +1 -1
  25. package/src/themes/five/src/components/Modal/index.js +1 -1
  26. package/src/themes/five/src/components/PaymentOptionStripeLink/index.js +298 -0
  27. package/src/themes/five/src/components/PaymentOptionStripeLink/styles.js +139 -0
  28. package/src/themes/five/src/components/PaymentOptions/index.js +1 -1
  29. package/src/utils/index.js +2 -1
  30. package/_bundles/ordering-ui.d155a03b9a727f188284.js +0 -2
  31. /package/_bundles/{7.ordering-ui.d155a03b9a727f188284.js.LICENSE.txt → 7.ordering-ui.946f2a2986a6d1d2dcdf.js.LICENSE.txt} +0 -0
  32. /package/_bundles/{ordering-ui.d155a03b9a727f188284.js.LICENSE.txt → ordering-ui.946f2a2986a6d1d2dcdf.js.LICENSE.txt} +0 -0
@@ -81,7 +81,7 @@ export const InputPhoneNumber = (props) => {
81
81
  return (
82
82
  <ContainerStyled className='phone_number' disabled={disabled} isValid={value ? isValidPhoneNumber(value) : true} isError={isError}>
83
83
  {!useProfileFormStyle && (
84
- <InputBeforeIconWrapper>
84
+ <InputBeforeIconWrapper className='input-icon'>
85
85
  <BsPhone />
86
86
  </InputBeforeIconWrapper>
87
87
  )}
@@ -71,7 +71,7 @@ const ModalUI = (props) => {
71
71
  )}
72
72
  {!hideCloseDefault && (
73
73
  <ModalIconWrapper>
74
- <ModalIcon isProductForm={isProductForm}>
74
+ <ModalIcon isProductForm={isProductForm} style={props.modalIconStyle}>
75
75
  {
76
76
  (authModal && onRemove) ? <MdClose onClick={() => onRemove()} /> : <MdClose onClick={() => onClose()} />
77
77
  }
@@ -0,0 +1,298 @@
1
+ import React, { useState, useEffect } from 'react'
2
+ import parsePhoneNumber from 'libphonenumber-js'
3
+ import { formatPhoneNumber } from 'react-phone-number-input'
4
+ import { Person } from 'react-bootstrap-icons'
5
+ import {
6
+ PaymentOptionStripeLink as PaymentOptionStripeLinkController,
7
+ useLanguage,
8
+ useCustomer,
9
+ useConfig
10
+ } from 'ordering-components-external'
11
+
12
+ import { Alert } from '../Confirm'
13
+ import { InputPhoneNumber } from '../InputPhoneNumber'
14
+ import { Input } from '../../styles/Inputs'
15
+ import { Button } from '../../styles/Buttons'
16
+
17
+ import {
18
+ StripeLinkContainer,
19
+ InputPhoneNumberWrapper,
20
+ InputBeforeIconWrapper,
21
+ CodeSentContainer
22
+ } from './styles'
23
+
24
+ export const PaymentOptionStripeLinkUI = (props) => {
25
+ const {
26
+ userInfo,
27
+ businessConfigs,
28
+ stripeLinkState,
29
+ setStripeLinkState,
30
+ handleSendStripeLink,
31
+ handleChangeUserInfo
32
+ } = props
33
+
34
+ const [, t] = useLanguage()
35
+ const [{ user }] = useCustomer()
36
+ const [{ configs }] = useConfig()
37
+ const [alertState, setAlertState] = useState({ open: false, content: [] })
38
+ const [isValidPhoneNumber, setIsValidPhoneNumber] = useState(null)
39
+ const [userPhoneNumber, setUserPhoneNumber] = useState(null)
40
+ const [showCountdown, setShowCountdown] = useState(false)
41
+ const [countdown, setCountdown] = useState(59)
42
+
43
+ const isWhatappEnabled = businessConfigs?.find(config => config?.key === 'allow_text_messages_whatsapp')?.value === '1'
44
+ const isSmsEnabled = businessConfigs?.find(config => config?.key === 'allow_text_messages_sms')?.value === '1'
45
+
46
+ const setUserCellPhone = (_user) => {
47
+ if (userPhoneNumber && !userPhoneNumber.includes('null')) {
48
+ setUserPhoneNumber(userPhoneNumber)
49
+ return
50
+ }
51
+ const cellphone = _user?.guest_id ? _user?.guest_cellphone : _user?.cellphone
52
+ if (cellphone) {
53
+ let phone = null
54
+ if (_user?.country_phone_code) {
55
+ phone = `+${_user?.country_phone_code} ${cellphone}`
56
+ } else {
57
+ phone = cellphone
58
+ }
59
+ setUserPhoneNumber(phone)
60
+ handleChangeUserInfo({
61
+ name: user?.name,
62
+ lastname: user?.lastname,
63
+ country_phone_code: _user?.country_phone_code,
64
+ cellphone: cellphone
65
+ })
66
+ return
67
+ }
68
+ setUserPhoneNumber(cellphone || '')
69
+ }
70
+
71
+ const handleChangePhoneNumber = (number, isValid, rawNumber) => {
72
+ setUserPhoneNumber(number)
73
+
74
+ let phoneNumberParser = null
75
+ let phoneNumber = {
76
+ country_phone_code: '',
77
+ cellphone: ''
78
+ }
79
+ if (isValid) {
80
+ phoneNumberParser = parsePhoneNumber(number)
81
+ if (!parseInt(configs?.validation_phone_number_lib?.value ?? 1, 10)) {
82
+ if (phoneNumberParser?.nationalNumber) phoneNumberParser.nationalNumber = formatPhoneNumber(number)?.replace?.(/\s/g, '')
83
+ }
84
+ }
85
+ if (phoneNumberParser) {
86
+ phoneNumber = {
87
+ country_phone_code: phoneNumberParser?.countryCallingCode,
88
+ cellphone: phoneNumberParser?.nationalNumber
89
+ }
90
+ }
91
+ handleChangeUserInfo({ ...phoneNumber })
92
+ }
93
+
94
+ const closeAlert = () => {
95
+ setAlertState({
96
+ open: false,
97
+ content: []
98
+ })
99
+ setStripeLinkState({ ...stripeLinkState, error: null })
100
+ }
101
+
102
+ const onSubmit = (type) => {
103
+ const isPhoneNumberValid = userPhoneNumber ? isValidPhoneNumber : true
104
+ const content = []
105
+ if (!userPhoneNumber) {
106
+ content.push(t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Phone Number is required.'))
107
+ setAlertState({
108
+ open: true,
109
+ content: content
110
+ })
111
+ return
112
+ }
113
+ if (!isPhoneNumberValid && userPhoneNumber) {
114
+ if (user?.country_phone_code) {
115
+ content.push(t('INVALID_ERROR_PHONE_NUMBER', 'The Phone Number field is invalid'))
116
+ setAlertState({
117
+ open: true,
118
+ content: content
119
+ })
120
+ return
121
+ }
122
+ content.push(t('INVALID_ERROR_COUNTRY_CODE_PHONE_NUMBER', 'The country code of the phone number is invalid'))
123
+ setAlertState({
124
+ open: true,
125
+ content: content
126
+ })
127
+ return
128
+ }
129
+ if (Object.keys(userInfo).length > 0 && isPhoneNumberValid) {
130
+ if (content?.length > 0) {
131
+ setAlertState({
132
+ open: true,
133
+ content: content
134
+ })
135
+ return
136
+ }
137
+ if (!stripeLinkState?.paymentURL) {
138
+ setAlertState({
139
+ open: true,
140
+ content: [t('ERROR_LINK_NOT_AVAILABLE', 'The link is not available please reload the page')]
141
+ })
142
+ return
143
+ }
144
+ handleSendStripeLink(type, () => {
145
+ setShowCountdown(true)
146
+ })
147
+ }
148
+ }
149
+
150
+ useEffect(() => {
151
+ let timer
152
+ if (showCountdown && countdown > 0) {
153
+ timer = setTimeout(() => setCountdown(countdown - 1), 1000)
154
+ } else if (countdown === 0) {
155
+ setShowCountdown(false)
156
+ setCountdown(59)
157
+ }
158
+ return () => clearTimeout(timer)
159
+ }, [showCountdown, countdown])
160
+
161
+ useEffect(() => {
162
+ if (user) {
163
+ setUserCellPhone(user)
164
+ }
165
+ }, [user])
166
+
167
+ useEffect(() => {
168
+ if ((!stripeLinkState?.loading && stripeLinkState?.error)) {
169
+ setAlertState({
170
+ open: true,
171
+ content: stripeLinkState?.error || [t('ERROR', 'Error')]
172
+ })
173
+ }
174
+ }, [stripeLinkState?.loading])
175
+
176
+ return (
177
+ <>
178
+ {showCountdown ? (
179
+ <CodeSentContainer>
180
+ <h3>{t('CODE_HAS_BEEN_SENT_TO', 'Link has been sent to _phone_').replace('_phone_', userPhoneNumber)}</h3>
181
+ <div className='countdown'>
182
+ <div>
183
+ <p>{countdown}</p>
184
+ </div>
185
+ </div>
186
+ <Button
187
+ color='primary'
188
+ disabled
189
+ >
190
+ {t('RESEND_LINK', 'Resend link')}
191
+ </Button>
192
+ </CodeSentContainer>
193
+ ) : (
194
+ <StripeLinkContainer>
195
+ <p className='message'>{t('SEND_SMS_WHATSAPP_MESSAGE', 'The link will be send to the following number')}</p>
196
+ <div className='user-info'>
197
+ <div className='inputs-wrapper'>
198
+ <div className='first-input'>
199
+ <InputBeforeIconWrapper>
200
+ <Person />
201
+ </InputBeforeIconWrapper>
202
+ <Input
203
+ type='text'
204
+ name='name'
205
+ className='form'
206
+ placeholder={t('NAME', 'Name')}
207
+ defaultValue={userInfo?.name ?? user?.name ?? ''}
208
+ onChange={(e) => handleChangeUserInfo({ name: e.target.value })}
209
+ autoComplete='off'
210
+ />
211
+ </div>
212
+ <div>
213
+ <InputBeforeIconWrapper>
214
+ <Person />
215
+ </InputBeforeIconWrapper>
216
+ <Input
217
+ type='text'
218
+ name='lastname'
219
+ className='form'
220
+ placeholder={t('LAST_NAME', 'Last name')}
221
+ defaultValue={userInfo?.lastname ?? user?.lastname ?? ''}
222
+ onChange={(e) => handleChangeUserInfo({ lastname: e.target.value })}
223
+ autoComplete='off'
224
+ />
225
+ </div>
226
+ </div>
227
+ <InputPhoneNumberWrapper>
228
+ <InputPhoneNumber
229
+ user={user}
230
+ value={userPhoneNumber}
231
+ setValue={handleChangePhoneNumber}
232
+ handleIsValid={setIsValidPhoneNumber}
233
+ />
234
+ </InputPhoneNumberWrapper>
235
+ </div>
236
+ <div className='buttons-wrapper'>
237
+ {isSmsEnabled && (
238
+ <div>
239
+ <Button
240
+ color='primary'
241
+ onClick={() => onSubmit('sms')}
242
+ disabled={stripeLinkState.loading}
243
+ >
244
+ {t('SEND_SMS', 'Send SMS')}
245
+ </Button>
246
+ </div>
247
+ )}
248
+ {isWhatappEnabled && (
249
+ <div>
250
+ <Button
251
+ color='primary'
252
+ outline
253
+ onClick={() => onSubmit('whatsapp')}
254
+ disabled={stripeLinkState.loading}
255
+ >
256
+ {t('SEND_WHATSAPP', 'Send WhatsApp')}
257
+ </Button>
258
+ </div>
259
+ )}
260
+
261
+ {!isSmsEnabled && !isWhatappEnabled && (
262
+ <div className='url-link'>
263
+ {stripeLinkState?.loading ? (
264
+ <div className='loading'>
265
+ <p>{t('LOADING', 'Loading...')}</p>
266
+ </div>
267
+ ) : (
268
+ <div>
269
+ <a href={stripeLinkState?.paymentURL ?? ''} rel='noopener noreferrer' target='_blank'>{stripeLinkState?.paymentURL ?? ''}</a>
270
+ </div>
271
+ )}
272
+ </div>
273
+ )}
274
+ </div>
275
+ </StripeLinkContainer>
276
+ )}
277
+ <Alert
278
+ title={t('ERROR', 'Error')}
279
+ content={alertState.content}
280
+ acceptText={t('ACCEPT', 'Accept')}
281
+ open={alertState.open}
282
+ onClose={() => closeAlert()}
283
+ onAccept={() => closeAlert()}
284
+ closeOnBackdrop={false}
285
+ />
286
+ </>
287
+ )
288
+ }
289
+
290
+ export const PaymentOptionStripeLink = (props) => {
291
+ const paymentOptionStripeProps = {
292
+ ...props,
293
+ UIComponent: PaymentOptionStripeLinkUI
294
+ }
295
+ return (
296
+ <PaymentOptionStripeLinkController {...paymentOptionStripeProps} />
297
+ )
298
+ }
@@ -0,0 +1,139 @@
1
+ import styled, { css } from 'styled-components'
2
+
3
+ export const StripeLinkContainer = styled.div`
4
+ display: flex;
5
+ flex-direction: column;
6
+ padding: 20px;
7
+
8
+ .message {
9
+ font-size: 14px;
10
+ }
11
+
12
+ .user-info {
13
+ display: flex;
14
+ flex-direction: column;
15
+
16
+ .inputs-wrapper {
17
+ display: flex;
18
+ > div {
19
+ width: 50%
20
+ }
21
+ input {
22
+ width: 100%;
23
+ padding: 7px 15px 7px 34px;
24
+ }
25
+ .first-input {
26
+ margin-right: 25px;
27
+ }
28
+ }
29
+ }
30
+ .buttons-wrapper {
31
+ display: flex;
32
+ padding-top: 20px;
33
+ gap: 10px;
34
+
35
+ div {
36
+ flex: 1;
37
+
38
+ p {
39
+ text-align: center;
40
+ }
41
+ }
42
+
43
+ button {
44
+ width: 100%;
45
+ min-height: 45px;
46
+ }
47
+ }
48
+
49
+ .loading {
50
+ text-align: center;
51
+
52
+ p {
53
+ margin: 0;
54
+ }
55
+ }
56
+
57
+ .url-link {
58
+ text-align: center;
59
+ }
60
+ `
61
+
62
+ export const WarningMessage = styled.p`
63
+ color: #D81212;
64
+ font-size: 24px;
65
+ padding-left: 10px;
66
+ font-weight: bold;
67
+ opacity: 0.8;
68
+ ${props => props.theme?.rtl && css`
69
+ padding-right: 10px;
70
+ padding-left: 0;
71
+ `}
72
+ `
73
+
74
+ export const InputPhoneNumberWrapper = styled.div`
75
+ width: 100%;
76
+ padding-top: 10px;
77
+ p {
78
+ font-weight: 500;
79
+ font-size: 20px;
80
+ color: ${props => props.theme.colors.darkTextColor};
81
+ width: 100%;
82
+ text-align: left;
83
+ margin: 0 0 7px 0;
84
+ }
85
+
86
+ .input-icon {
87
+ top: 8px;
88
+ }
89
+ `
90
+
91
+ export const InputBeforeIconWrapper = styled.div`
92
+ position: absolute;
93
+ padding: 6px 6px 6px 10px;
94
+
95
+ ${props => props.theme.rtl && css`
96
+ right: 100px;
97
+ left: initial;
98
+ `}
99
+
100
+ svg {
101
+ color: #B1BCCC;
102
+ font-size: 16px;
103
+ }
104
+ `
105
+
106
+ export const CodeSentContainer = styled.div`
107
+ display: flex;
108
+ flex-direction: column;
109
+ align-items: center;
110
+ padding: 20px;
111
+
112
+ h3 {
113
+ font-size: 20px;
114
+ }
115
+
116
+ .countdown {
117
+ display: flex;
118
+ justify-content: center;
119
+ width: 100%;
120
+ padding: 20px 0;
121
+
122
+ div {
123
+ width: 30%;
124
+ background-color: ${props => props.theme.colors.grayDividerColor};
125
+ padding: 10px 10px;
126
+ p {
127
+ text-align: center;
128
+ font-size: 32px;
129
+ color: ${props => props.theme.colors.success500};
130
+ margin: 0;
131
+ }
132
+ }
133
+ }
134
+
135
+ button {
136
+ width: 100%;
137
+ min-height: 45px;
138
+ }
139
+ `
@@ -231,7 +231,7 @@ const PaymentOptionsUI = (props) => {
231
231
  supportedMethods.sort((a, b) => a.id - b.id).map(paymethod => (
232
232
  <React.Fragment key={paymethod.id}>
233
233
  {
234
- (((!isCustomerMode || (isAlsea && isCustomerMode)) && paymethod.gateway) || (isCustomerMode && (paymethod.gateway === 'card_delivery' || paymethod.gateway === 'cash'))) && (
234
+ (((!isCustomerMode || (isAlsea && isCustomerMode)) && paymethod.gateway) || (isCustomerMode && (['cash', 'card_delivery', 'stripe_link'].includes(paymethod?.gateway)))) && (
235
235
  <PayCard
236
236
  isDisabled={isDisabled}
237
237
  className={`${(paymethodSelected?.id || isOpenMethod?.paymethod?.id) === paymethod.id ? 'active' : ''}`}
@@ -118,7 +118,8 @@ export const getTraduction = key => {
118
118
  ERROR_PLACE_PAY_WITH_PAYPAL_CAPTURE: 'An error occurred while trying to pay by PayPal',
119
119
  ERROR_ADD_PRODUCT_VERY_FAR_FOR_DELIVERY: 'Error adding product, very far for delivery',
120
120
  ERROR_INVALID_OFFER: 'The offer doesn\'t exist',
121
- ERROR_CASH_WALLET_FEATURE_DISABLED: 'Cash wallet feature is disabled'
121
+ ERROR_CASH_WALLET_FEATURE_DISABLED: 'Cash wallet feature is disabled',
122
+ ERROR_TWILIO_SERVICE_BAD_SETTINGS: 'Twilio service bad settings'
122
123
  }
123
124
 
124
125
  return keyList[key] ? t(key, keyList[key]) : t(key)