ordering-ui-external 1.5.4 → 1.6.0

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 (81) hide show
  1. package/_bundles/0.ordering-ui.ff76ec87ed271a678f9d.js +1 -0
  2. package/_bundles/{1.ordering-ui.5de718771fdf8a9bc402.js → 1.ordering-ui.ff76ec87ed271a678f9d.js} +0 -0
  3. package/_bundles/{2.ordering-ui.5de718771fdf8a9bc402.js → 2.ordering-ui.ff76ec87ed271a678f9d.js} +0 -0
  4. package/_bundles/{4.ordering-ui.5de718771fdf8a9bc402.js → 4.ordering-ui.ff76ec87ed271a678f9d.js} +0 -0
  5. package/_bundles/{5.ordering-ui.5de718771fdf8a9bc402.js → 5.ordering-ui.ff76ec87ed271a678f9d.js} +1 -1
  6. package/_bundles/{6.ordering-ui.5de718771fdf8a9bc402.js → 6.ordering-ui.ff76ec87ed271a678f9d.js} +0 -0
  7. package/_bundles/{7.ordering-ui.5de718771fdf8a9bc402.js → 7.ordering-ui.ff76ec87ed271a678f9d.js} +2 -2
  8. package/_bundles/{7.ordering-ui.5de718771fdf8a9bc402.js.LICENSE.txt → 7.ordering-ui.ff76ec87ed271a678f9d.js.LICENSE.txt} +0 -0
  9. package/_bundles/{8.ordering-ui.5de718771fdf8a9bc402.js → 8.ordering-ui.ff76ec87ed271a678f9d.js} +0 -0
  10. package/_bundles/{9.ordering-ui.5de718771fdf8a9bc402.js → 9.ordering-ui.ff76ec87ed271a678f9d.js} +0 -0
  11. package/_bundles/ordering-ui.ff76ec87ed271a678f9d.js +2 -0
  12. package/_bundles/{ordering-ui.5de718771fdf8a9bc402.js.LICENSE.txt → ordering-ui.ff76ec87ed271a678f9d.js.LICENSE.txt} +0 -0
  13. package/_modules/components/BusinessTypeFilter/index.js +6 -3
  14. package/_modules/components/CancellationComponent/index.js +58 -0
  15. package/_modules/components/CancellationComponent/styles.js +43 -0
  16. package/_modules/components/Header/index.js +1 -1
  17. package/_modules/index.js +7 -0
  18. package/_modules/themes/callcenterOriginal/src/components/Header/styles.js +1 -1
  19. package/_modules/themes/five/src/components/AddressForm/index.js +5 -5
  20. package/_modules/themes/five/src/components/AddressList/index.js +3 -1
  21. package/_modules/themes/five/src/components/AddressList/styles.js +1 -1
  22. package/_modules/themes/five/src/components/BusinessBasicInformation/index.js +4 -2
  23. package/_modules/themes/five/src/components/BusinessController/index.js +22 -13
  24. package/_modules/themes/five/src/components/BusinessReviews/index.js +4 -4
  25. package/_modules/themes/five/src/components/BusinessesListing/layouts/OriginalBusinessesListing/index.js +8 -5
  26. package/_modules/themes/five/src/components/Cart/index.js +13 -2
  27. package/_modules/themes/five/src/components/HomeHero/index.js +5 -3
  28. package/_modules/themes/five/src/components/MultiOrdersDetails/styles.js +1 -1
  29. package/_modules/themes/five/src/components/OrderDetails/OrderActionsSection.js +38 -0
  30. package/_modules/themes/five/src/components/OrderDetails/OrderHeaderInfoSection.js +27 -0
  31. package/_modules/themes/five/src/components/OrderDetails/index.js +64 -60
  32. package/_modules/themes/five/src/components/OrderDetails/styles.js +7 -5
  33. package/_modules/themes/five/src/components/OrderTypeSelectorContent/index.js +7 -2
  34. package/_modules/themes/five/src/components/OrdersOption/PreviousBusinessOrdered/index.js +2 -2
  35. package/_modules/themes/five/src/components/OrdersOption/index.js +4 -2
  36. package/_modules/themes/five/src/components/ProductItemAccordion/index.js +5 -3
  37. package/_modules/themes/five/src/components/ServiceForm/index.js +33 -7
  38. package/_modules/themes/five/src/components/ServiceForm/styles.js +8 -3
  39. package/_modules/themes/five/src/components/SignUpApproval/index.js +6 -6
  40. package/_modules/themes/five/src/components/SingleProductCard/index.js +4 -4
  41. package/_modules/themes/five/src/components/UserFormDetails/index.js +51 -26
  42. package/_modules/themes/five/src/components/UserFormDetails/styles.js +9 -3
  43. package/_modules/themes/five/src/components/UserVerification/index.js +7 -2
  44. package/index-template.js +7 -5
  45. package/package.json +2 -2
  46. package/src/components/BusinessTypeFilter/index.js +2 -2
  47. package/src/components/CancellationComponent/index.js +62 -0
  48. package/src/components/CancellationComponent/styles.js +162 -0
  49. package/src/components/Header/index.js +1 -1
  50. package/src/index.js +2 -0
  51. package/src/themes/callcenterOriginal/src/components/Header/styles.js +1 -0
  52. package/src/themes/five/src/components/AddressForm/index.js +2 -2
  53. package/src/themes/five/src/components/AddressList/index.js +2 -1
  54. package/src/themes/five/src/components/AddressList/styles.js +4 -1
  55. package/src/themes/five/src/components/BusinessBasicInformation/index.js +3 -2
  56. package/src/themes/five/src/components/BusinessController/index.js +68 -44
  57. package/src/themes/five/src/components/BusinessReviews/index.js +4 -4
  58. package/src/themes/five/src/components/BusinessesListing/layouts/OriginalBusinessesListing/index.js +15 -11
  59. package/src/themes/five/src/components/Cart/index.js +24 -9
  60. package/src/themes/five/src/components/HomeHero/index.js +4 -2
  61. package/src/themes/five/src/components/MultiOrdersDetails/styles.js +5 -1
  62. package/src/themes/five/src/components/OrderDetails/OrderActionsSection.js +33 -0
  63. package/src/themes/five/src/components/OrderDetails/OrderHeaderInfoSection.js +20 -0
  64. package/src/themes/five/src/components/OrderDetails/index.js +84 -100
  65. package/src/themes/five/src/components/OrderDetails/styles.js +4 -1
  66. package/src/themes/five/src/components/OrderTypeSelectorContent/index.js +4 -2
  67. package/src/themes/five/src/components/OrdersOption/PreviousBusinessOrdered/index.js +2 -2
  68. package/src/themes/five/src/components/OrdersOption/index.js +3 -1
  69. package/src/themes/five/src/components/ProductItemAccordion/index.js +4 -2
  70. package/src/themes/five/src/components/ServiceForm/index.js +162 -139
  71. package/src/themes/five/src/components/ServiceForm/styles.js +10 -0
  72. package/src/themes/five/src/components/SignUpApproval/index.js +6 -7
  73. package/src/themes/five/src/components/SingleProductCard/index.js +3 -3
  74. package/src/themes/five/src/components/UserFormDetails/index.js +59 -23
  75. package/src/themes/five/src/components/UserFormDetails/styles.js +26 -0
  76. package/src/themes/five/src/components/UserVerification/index.js +18 -11
  77. package/template/app.js +385 -367
  78. package/template/components/SubdomainComponent/index.js +54 -0
  79. package/template/config.json +4 -1
  80. package/_bundles/0.ordering-ui.5de718771fdf8a9bc402.js +0 -1
  81. package/_bundles/ordering-ui.5de718771fdf8a9bc402.js +0 -2
@@ -1,6 +1,7 @@
1
1
  import React, { useEffect, useRef, useState } from 'react'
2
2
  import { Swiper, SwiperSlide } from 'swiper/react'
3
3
  import { useUtils, useLanguage, useSession, ProductForm as ProductFormController } from 'ordering-components-external'
4
+ import Skeleton from 'react-loading-skeleton'
4
5
  import { Alert } from '../Confirm'
5
6
  import { Modal } from '../Modal'
6
7
  import { LoginForm } from '../LoginForm'
@@ -34,22 +35,25 @@ import {
34
35
  StatusInfo,
35
36
  DropDownWrapper,
36
37
  DropDownTitle,
37
- EmptyProfessional
38
+ EmptyProfessional,
39
+ SkeletonBlock
38
40
  } from './styles'
39
41
  import moment from 'moment'
40
42
  SwiperCore.use([Navigation])
41
43
 
42
44
  const ServiceFormUI = (props) => {
43
45
  const {
44
- product,
46
+ productObject,
45
47
  professionalSelected,
46
48
  handleSave,
47
49
  isSoldOut,
48
50
  maxProductQuantity,
49
51
  productCart,
50
- professionalList
52
+ isCartProduct,
53
+ professionalListState
51
54
  } = props
52
55
 
56
+ const { product, loading, error } = productObject
53
57
  const theme = useTheme()
54
58
  const [, t] = useLanguage()
55
59
  const [{ parsePrice, parseDate }] = useUtils()
@@ -151,102 +155,84 @@ const ServiceFormUI = (props) => {
151
155
  }, [isDropDown])
152
156
 
153
157
  useEffect(() => {
154
- if (!professionalSelected) return
158
+ if (!professionalSelected?.schedule) return
155
159
  setCurrentProfessional(professionalSelected)
156
160
  }, [professionalSelected])
157
161
 
162
+ useEffect(() => {
163
+ if (isCartProduct && professionalListState?.professionals?.length > 0) {
164
+ const professional = professionalListState?.professionals?.find(item => item.id === professionalSelected?.id)
165
+ setCurrentProfessional(professional)
166
+ }
167
+ }, [isCartProduct, professionalListState?.professionals])
168
+
158
169
  return (
159
170
  <>
160
171
  <Container>
161
- <ImageWrapper>
162
- <SwiperWrapper>
163
- <ArrowButtonWrapper className='button-prev'>
164
- <ChevronLeft />
165
- </ArrowButtonWrapper>
166
- <Swiper
167
- spaceBetween={0}
168
- slidesPerView={1}
169
- watchSlidesProgress
170
- className='mySwiper2'
171
- preventClicksPropagation={false}
172
- navigation={{
173
- nextEl: '.button-next',
174
- prevEl: '.button-prev'
175
- }}
176
- >
177
- {gallery?.map((photo, i) => (
178
- <SwiperSlide key={i}>
179
- <img src={photo} alt='' />
180
- </SwiperSlide>
181
- ))}
182
- </Swiper>
183
- <ArrowButtonWrapper className='button-next'>
184
- <ChevronRight />
185
- </ArrowButtonWrapper>
186
- </SwiperWrapper>
187
- </ImageWrapper>
188
- <HeaderInfoWrapper>
189
- <h2>{product?.name}</h2>
190
- <PriceAndDuration>
191
- <span>{parsePrice(product?.price)}</span>
192
- <span className='dot'>•</span>
193
- <span>{product?.duration}min</span>
194
- </PriceAndDuration>
195
- <p>{product?.description}</p>
196
- </HeaderInfoWrapper>
197
- <Divider />
198
- <ProfessionalInfoWrapper>
199
- <SectionHeader>
200
- <h2>{t('PROFESSIONALS', 'Professionals')}</h2>
201
- <span>{t('REQUIRED', 'Required')}</span>
202
- </SectionHeader>
203
- <ProfessionalSelectWrapper ref={dropDownRef}>
204
- <SelectedItem onClick={() => setIsDropDown(prev => !prev)}>
205
- {currentProfessional ? (
206
- <InfoWrapper>
207
- {currentProfessional?.photo ? (
208
- <ProfessionalPhoto
209
- bgimage={currentProfessional?.photo}
210
- />
211
- ) : <FaUserAlt />}
212
- <NameWrapper>
213
- <p>{currentProfessional?.name} {currentProfessional?.lastname}</p>
214
- <StatusInfo available={!isBusyTime()}>
215
- {isBusyTime(currentProfessional) ? (
216
- <>
217
- <span className='status'>{t('BUSY_ON_SELECTED_TIME', 'Busy on selected time')}</span>
218
- </>
219
- ) : (
220
- <span className='status'>{t('AVAILABLE', 'Available')}</span>
221
- )}
222
- </StatusInfo>
223
- </NameWrapper>
224
- </InfoWrapper>
225
- ) : (
226
- <p>{t('SELECT_PROFESSIONAL', 'Select professional')}</p>
227
- )}
228
- <ChevronDown />
229
- </SelectedItem>
230
- {isDropDown && (
231
- <DropDownWrapper>
232
- <DropDownTitle>{t('ANY_PROFESSIONAL_MEMBER', 'Any professional member')}</DropDownTitle>
233
- {professionalList?.map((professional) => (
234
- <SelectedItem
235
- key={professional?.id}
236
- isDropDown
237
- active={professional?.id === currentProfessional?.id}
238
- onClick={() => handleChangeProfessional(professional)}
239
- >
172
+ {loading && !error && (
173
+ <SkeletonBlock width={90}>
174
+ <Skeleton variant='rect' height={50} />
175
+ <Skeleton variant='rect' height={50} />
176
+ <Skeleton variant='rect' height={200} />
177
+ </SkeletonBlock>
178
+ )}
179
+ {product && !loading && (
180
+ <>
181
+ <ImageWrapper>
182
+ <SwiperWrapper>
183
+ <ArrowButtonWrapper className='button-prev'>
184
+ <ChevronLeft />
185
+ </ArrowButtonWrapper>
186
+ <Swiper
187
+ spaceBetween={0}
188
+ slidesPerView={1}
189
+ watchSlidesProgress
190
+ className='mySwiper2'
191
+ preventClicksPropagation={false}
192
+ navigation={{
193
+ nextEl: '.button-next',
194
+ prevEl: '.button-prev'
195
+ }}
196
+ >
197
+ {gallery?.map((photo, i) => (
198
+ <SwiperSlide key={i}>
199
+ <img src={photo} alt='' />
200
+ </SwiperSlide>
201
+ ))}
202
+ </Swiper>
203
+ <ArrowButtonWrapper className='button-next'>
204
+ <ChevronRight />
205
+ </ArrowButtonWrapper>
206
+ </SwiperWrapper>
207
+ </ImageWrapper>
208
+ <HeaderInfoWrapper>
209
+ <h2>{product?.name}</h2>
210
+ <PriceAndDuration>
211
+ <span>{parsePrice(product?.price)}</span>
212
+ <span className='dot'>•</span>
213
+ <span>{product?.duration}min</span>
214
+ </PriceAndDuration>
215
+ <p>{product?.description}</p>
216
+ </HeaderInfoWrapper>
217
+ <Divider />
218
+ <ProfessionalInfoWrapper>
219
+ <SectionHeader>
220
+ <h2>{t('PROFESSIONALS', 'Professionals')}</h2>
221
+ <span>{t('REQUIRED', 'Required')}</span>
222
+ </SectionHeader>
223
+ <ProfessionalSelectWrapper ref={dropDownRef}>
224
+ <SelectedItem onClick={() => setIsDropDown(prev => !prev)}>
225
+ {currentProfessional ? (
240
226
  <InfoWrapper>
241
- {professional?.photo ? (
227
+ {currentProfessional?.photo ? (
242
228
  <ProfessionalPhoto
243
- bgimage={professional?.photo}
229
+ bgimage={currentProfessional?.photo}
244
230
  />
245
231
  ) : <FaUserAlt />}
246
232
  <NameWrapper>
247
- <p>{professional?.name} {professional?.lastname}</p>
248
- <StatusInfo available={!isBusyTime(professional)}>
249
- {isBusyTime(professional) ? (
233
+ <p>{currentProfessional?.name} {currentProfessional?.lastname}</p>
234
+ <StatusInfo available={!isBusyTime()}>
235
+ {isBusyTime(currentProfessional) ? (
250
236
  <>
251
237
  <span className='status'>{t('BUSY_ON_SELECTED_TIME', 'Busy on selected time')}</span>
252
238
  </>
@@ -256,58 +242,95 @@ const ServiceFormUI = (props) => {
256
242
  </StatusInfo>
257
243
  </NameWrapper>
258
244
  </InfoWrapper>
259
- </SelectedItem>
260
- ))}
261
- </DropDownWrapper>
262
- )}
245
+ ) : (
246
+ <p>{t('SELECT_PROFESSIONAL', 'Select professional')}</p>
247
+ )}
248
+ <ChevronDown />
249
+ </SelectedItem>
250
+ {isDropDown && (
251
+ <DropDownWrapper>
252
+ <DropDownTitle>{t('ANY_PROFESSIONAL_MEMBER', 'Any professional member')}</DropDownTitle>
253
+ {professionalListState?.professionals?.map((professional) => (
254
+ <SelectedItem
255
+ key={professional?.id}
256
+ isDropDown
257
+ active={professional?.id === currentProfessional?.id}
258
+ onClick={() => handleChangeProfessional(professional)}
259
+ >
260
+ <InfoWrapper>
261
+ {professional?.photo ? (
262
+ <ProfessionalPhoto
263
+ bgimage={professional?.photo}
264
+ />
265
+ ) : <FaUserAlt />}
266
+ <NameWrapper>
267
+ <p>{professional?.name} {professional?.lastname}</p>
268
+ <StatusInfo available={!isBusyTime(professional)}>
269
+ {isBusyTime(professional) ? (
270
+ <>
271
+ <span className='status'>{t('BUSY_ON_SELECTED_TIME', 'Busy on selected time')}</span>
272
+ </>
273
+ ) : (
274
+ <span className='status'>{t('AVAILABLE', 'Available')}</span>
275
+ )}
276
+ </StatusInfo>
277
+ </NameWrapper>
278
+ </InfoWrapper>
279
+ </SelectedItem>
280
+ ))}
281
+ </DropDownWrapper>
282
+ )}
283
+
284
+ </ProfessionalSelectWrapper>
285
+ </ProfessionalInfoWrapper>
286
+ <ScheduleWrapper>
287
+ <SectionHeader>
288
+ <h2>{t('SCHEDULE', 'Schedule')}</h2>
289
+ <span>{t('REQUIRED', 'Required')}</span>
290
+ </SectionHeader>
291
+ {currentProfessional ? (
292
+ <BusinessPreorder
293
+ business={currentProfessional}
294
+ isProfessional
295
+ maxDays={50}
296
+ onChangeMoment={setDateSelected}
297
+ useOrderContext={false}
298
+ />
299
+ ) : (
300
+ <EmptyProfessional>
301
+ {t('NO_SCHEDULE', 'No schedule')}
302
+ </EmptyProfessional>
303
+ )}
304
+ </ScheduleWrapper>
305
+ <ButtonWrapper>
306
+ <span>{dateSelected
307
+ ? parseDate(dateSelected, { outputFormat: 'hh:mm a' })
308
+ : t('ASAP_ABBREVIATION', 'ASAP')}
309
+ </span>
310
+ {!isSoldOut && maxProductQuantity > 0 && auth && (
311
+ <Button
312
+ onClick={() => handleAddProduct()}
313
+ color='primary'
314
+ disabled={isBusyTime(currentProfessional)}
315
+ >
316
+ {t('BOOK', 'Book')}
317
+ </Button>
318
+ )}
319
+ {(!auth || isSoldOut || maxProductQuantity <= 0) && (
320
+ <Button
321
+ className={`add ${!(productCart && !isSoldOut && maxProductQuantity > 0) ? 'soldout' : ''}`}
322
+ color='primary'
323
+ outline
324
+ disabled={isSoldOut || maxProductQuantity <= 0}
325
+ onClick={() => setModalIsOpen(true)}
326
+ >
327
+ {isSoldOut || maxProductQuantity <= 0 ? t('SOLD_OUT', theme?.defaultLanguages?.SOLD_OUT || 'Sold out') : t('LOGIN_SIGNUP', theme?.defaultLanguages?.LOGIN_SIGNUP || 'Login / Sign Up')}
328
+ </Button>
329
+ )}
330
+ </ButtonWrapper>
331
+ </>
332
+ )}
263
333
 
264
- </ProfessionalSelectWrapper>
265
- </ProfessionalInfoWrapper>
266
- <ScheduleWrapper>
267
- <SectionHeader>
268
- <h2>{t('SCHEDULE', 'Schedule')}</h2>
269
- <span>{t('REQUIRED', 'Required')}</span>
270
- </SectionHeader>
271
- {currentProfessional ? (
272
- <BusinessPreorder
273
- business={currentProfessional}
274
- isProfessional
275
- maxDays={50}
276
- onChangeMoment={setDateSelected}
277
- useOrderContext={false}
278
- />
279
- ) : (
280
- <EmptyProfessional>
281
- {t('NO_SCHEDULE', 'No schedule')}
282
- </EmptyProfessional>
283
- )}
284
- </ScheduleWrapper>
285
- <ButtonWrapper>
286
- <span>{dateSelected
287
- ? parseDate(dateSelected, { outputFormat: 'hh:mm a' })
288
- : t('ASAP_ABBREVIATION', 'ASAP')}
289
- </span>
290
- {!isSoldOut && maxProductQuantity > 0 && auth && (
291
- <Button
292
- onClick={() => handleAddProduct()}
293
- color='primary'
294
- disabled={isBusyTime(currentProfessional)}
295
- >
296
- {t('BOOK', 'Book')}
297
- </Button>
298
- )}
299
- {(!auth || isSoldOut || maxProductQuantity <= 0) && (
300
- <Button
301
- className={`add ${!(productCart && !isSoldOut && maxProductQuantity > 0) ? 'soldout' : ''}`}
302
- color='primary'
303
- outline
304
- disabled={isSoldOut || maxProductQuantity <= 0}
305
- onClick={() => setModalIsOpen(true)}
306
- >
307
- {isSoldOut || maxProductQuantity <= 0 ? t('SOLD_OUT', theme?.defaultLanguages?.SOLD_OUT || 'Sold out') : t('LOGIN_SIGNUP', theme?.defaultLanguages?.LOGIN_SIGNUP || 'Login / Sign Up')}
308
- </Button>
309
- )}
310
- </ButtonWrapper>
311
334
  {modalIsOpen && !auth && (
312
335
  <Modal
313
336
  open={modalIsOpen}
@@ -311,3 +311,13 @@ export const EmptyProfessional = styled.div`
311
311
  align-items: center;
312
312
  justify-content: center;
313
313
  `
314
+
315
+ export const SkeletonBlock = styled.div`
316
+ width: ${({ width }) => width && `${width}%`};
317
+ border-radius: 16px;
318
+ margin: 50px auto 20px auto;
319
+
320
+ span {
321
+ margin-bottom: 10px;
322
+ }
323
+ `
@@ -21,8 +21,7 @@ import {
21
21
  export const SignUpApproval = (props) => {
22
22
  const theme = useTheme()
23
23
  const [, t] = useLanguage()
24
- const { content: { project, dashboardUrl, dashboardLoginUrl, approvalType, businessType }, onAccept, onCancel } = props
25
- const contactEmail = 'support@ordering.co'
24
+ const { content: { project, dashboardUrl, dashboardLoginUrl, approvalType, businessType, contactEmail }, onAccept, onCancel } = props
26
25
  const showDomain = false
27
26
 
28
27
  const logoImgUrl = businessType === 2
@@ -60,9 +59,9 @@ export const SignUpApproval = (props) => {
60
59
  </tr>
61
60
  <tr>
62
61
  <td className='bigger td-text-right'>{t('DASHBOARD_WEBPAGE', 'Dashboard webpage')}: </td>
63
- <td className='td-text-left'><a className='green-text' href={dashboardLoginUrl} target='_blank' rel='noopener noreferrer'>{dashboardUrl}</a></td>
62
+ <td className='td-text-left'><a className='green-text' href={t('SIGNUP_DASHBOARD_LOGIN_URL', dashboardLoginUrl)} target='_blank' rel='noopener noreferrer'>{t('SIGNUP_DASHBOARD_URL', dashboardUrl)}</a></td>
64
63
  </tr>
65
- </tbody>
64
+ </tbody>
66
65
  </ProjectInfoContainer>
67
66
  </BodySection>
68
67
  ) : (
@@ -71,13 +70,13 @@ export const SignUpApproval = (props) => {
71
70
  <DescriptionContainer>
72
71
  <Description><span className='bigger'>{t('YOUR_STORE_UNDER_APPROVAL', 'Your store is under approval')}</span></Description>
73
72
  <Description>{t('BUSINESS_SIGNUP_MESSAGE', 'We will contact you as soon as possible')}</Description>
74
- <Description>{t('FEEL_FREE_CONTACT_US', 'feel free to contact us at ')} <a className='green-text' href={`mailto:${t('SIGNUP_DRIVER_EMAIL', contactEmail)}`}>{contactEmail}</a></Description>
73
+ <Description>{t('FEEL_FREE_CONTACT_US', 'feel free to contact us at ')} <a className='green-text' href={`mailto:${t('SIGNUP_DRIVER_EMAIL', contactEmail)}`}>{t('SIGNUP_DRIVER_EMAIL', contactEmail)}</a></Description>
75
74
  </DescriptionContainer>
76
75
  ) : (
77
76
  <DescriptionContainer>
78
77
  <Description><span className='bigger'>{t('REQUEST_TO_START_UNDER_APPROVAL', 'Your request to start as a driver is under approval.')}</span></Description>
79
78
  <Description>{t('BUSINESS_SIGNUP_MESSAGE', 'We will contact you as soon as possible')}</Description>
80
- <Description>{t('FEEL_FREE_CONTACT_US', 'feel free to contact us at ')} <a className='green-text' href={`mailto:${t('SIGNUP_DRIVER_EMAIL', contactEmail)}`}>{contactEmail}</a></Description>
79
+ <Description>{t('FEEL_FREE_CONTACT_US', 'feel free to contact us at ')} <a className='green-text' href={`mailto:${t('SIGNUP_DRIVER_EMAIL', contactEmail)}`}>{t('SIGNUP_DRIVER_EMAIL', contactEmail)}</a></Description>
81
80
  </DescriptionContainer>
82
81
  )}
83
82
  </BodySection>
@@ -101,7 +100,7 @@ export const SignUpApproval = (props) => {
101
100
  </Button>
102
101
  </ActionGroup>
103
102
  {(approvalType === 'automatic' && userType === 'business') && (
104
- <ContactSection>{t('CONTACT_US_QUESTIONS', 'If you have some questions do no hestitate to contact us at ')} <a className='green-text' href={`mailto:${t('SIGNUP_DRIVER_EMAIL', contactEmail)}`}>{contactEmail}</a></ContactSection>
103
+ <ContactSection>{t('CONTACT_US_QUESTIONS', 'If you have some questions do no hestitate to contact us at ')} <a className='green-text' href={`mailto:${t('SIGNUP_DRIVER_EMAIL', contactEmail)}`}>{t('SIGNUP_DRIVER_EMAIL', contactEmail)}</a></ContactSection>
105
104
  )}
106
105
  </FooterSection>
107
106
  </Container>
@@ -157,7 +157,7 @@ const SingleProductCardUI = (props) => {
157
157
  <span>{productAddedToCartLength}</span>
158
158
  </QuantityContainer>
159
159
  )}
160
- <CardInfo soldOut={isSoldOut || maxProductQuantity <= 0} isBgimage={optimizeImage(product?.images, 'h_86,c_limit')} oneLine={isPreviously}>
160
+ <CardInfo soldOut={isSoldOut || maxProductQuantity <= 0} isBgimage={optimizeImage(product?.images || theme?.images?.dummies?.product, 'h_86,c_limit')} oneLine={isPreviously}>
161
161
  <TitleWrapper>
162
162
  {!isSkeleton ? (<h1>{product?.name}</h1>) : (<Skeleton width={100} />)}
163
163
  {!useKioskApp && !isPreviously && (
@@ -182,7 +182,7 @@ const SingleProductCardUI = (props) => {
182
182
  {isPreviously && (!isSkeleton ? (<LastOrder>{t('LAST_ORDERED_ON', 'Last ordered on')} {parseDate(product?.last_ordered_date, { outputFormat: 'MMM DD, YYYY' })}</LastOrder>) : (<Skeleton width={80} />))}
183
183
  </CardInfo>
184
184
  {!isSkeleton ? (
185
- <WrapLogo isBgimage={optimizeImage(product?.images, 'h_86,c_limit')}>
185
+ <WrapLogo isBgimage={optimizeImage(product?.images || theme?.images?.dummies?.product, 'h_86,c_limit')}>
186
186
  {product?.ribbon?.enabled && (
187
187
  <RibbonBox
188
188
  bgColor={product?.ribbon?.color}
@@ -195,7 +195,7 @@ const SingleProductCardUI = (props) => {
195
195
  <CardLogo
196
196
  className='image'
197
197
  soldOut={isSoldOut || maxProductQuantity <= 0}
198
- bgimage={optimizeImage(product?.images, 'h_86,c_limit')}
198
+ bgimage={optimizeImage(product?.images || theme?.images?.dummies?.product, 'h_86,c_limit')}
199
199
  />
200
200
  </WrapLogo>
201
201
  ) : (
@@ -13,9 +13,12 @@ import {
13
13
  Divider,
14
14
  InputPhoneNumberWrapper,
15
15
  LanguageSelectorWrapper,
16
- PromotionsWrapper
16
+ SwitchWrapper,
17
+ NotificationsGroupSwitchWrapper
17
18
  } from './styles'
18
19
 
20
+ import { Switch } from '../../../../../styles/Switch'
21
+
19
22
  import { Input } from '../../styles/Inputs'
20
23
  import { Button } from '../../styles/Buttons'
21
24
  import { InputPhoneNumber } from '../../../../../components/InputPhoneNumber'
@@ -42,7 +45,8 @@ export const UserFormDetailsUI = (props) => {
42
45
  setWillVerifyOtpState,
43
46
  handleChangePromotions,
44
47
  isOldLayout,
45
- requiredFields
48
+ requiredFields,
49
+ handleChangeNotifications
46
50
  } = props
47
51
 
48
52
  const formMethods = useForm()
@@ -57,13 +61,26 @@ export const UserFormDetailsUI = (props) => {
57
61
  const [, { setUserCustomer }] = useCustomer()
58
62
  const [isChanged, setIsChanged] = useState(false)
59
63
  const emailInput = useRef(null)
60
-
64
+
61
65
  const user = userData || userSession
62
-
66
+
67
+ const [notificationList, setNotificationList] = useState({
68
+ email: formState?.result?.result
69
+ ? !!formState?.result?.result?.settings?.email?.newsletter
70
+ : !!(formState?.changes?.settings?.email?.newsletter ?? (user && user?.settings?.email?.newsletter)),
71
+ sms: formState?.result?.result
72
+ ? !!formState?.result?.result?.settings?.sms?.newsletter
73
+ : !!(formState?.changes?.settings?.sms?.newsletter ?? (user && user?.settings?.sms?.newsletter)),
74
+ notification: formState?.result?.result
75
+ ? !!formState?.result?.result?.settings?.notification?.newsletter
76
+ : !!(formState?.changes?.settings?.notification?.newsletter ?? (user && user?.settings?.notification?.newsletter))
77
+ })
78
+
63
79
  const showCustomerCellphone = !orderingTheme?.theme?.profile?.components?.cellphone?.hidden
64
80
  const showCustomerPassword = !orderingTheme?.theme?.profile?.components?.password?.hidden
65
81
  const showCustomerPromotions = !orderingTheme?.theme?.profile?.components?.promotions?.hidden
66
82
  const showLangauges = !orderingTheme?.theme?.profile?.components?.languages?.hidden
83
+ const showNotifications = !orderingTheme?.theme?.profile?.components?.notification_settings?.hidden
67
84
 
68
85
  const closeAlert = () => {
69
86
  setAlertState({
@@ -251,6 +268,17 @@ export const UserFormDetailsUI = (props) => {
251
268
  if (requiredFields && !requiredFields.includes('cellphone')) setIsValidPhoneNumber(true)
252
269
  }, [requiredFields])
253
270
 
271
+ const handleEditNotifications = (key, value) => {
272
+ setNotificationList({
273
+ ...notificationList,
274
+ [key]: value
275
+ })
276
+ }
277
+
278
+ useEffect(()=> {
279
+ isEdit && handleChangeNotifications(notificationList)
280
+ },[notificationList])
281
+
254
282
  return (
255
283
  <>
256
284
  {props.beforeElements?.map((BeforeElement, i) => (
@@ -359,28 +387,36 @@ export const UserFormDetailsUI = (props) => {
359
387
  />
360
388
  </InputGroup>
361
389
  )}
362
- {!isCheckout && showCustomerPromotions && (
363
- <PromotionsWrapper>
364
- <Checkbox
365
- name='promotions'
366
- id='promotions'
367
- onChange={() => handleChangePromotions(!(formState?.result?.result
368
- ? !!formState?.result?.result?.settings?.notification?.newsletter
369
- : formState?.changes?.settings?.notification?.newsletter ?? (user && user?.settings?.notification?.newsletter)))}
370
- defaultChecked={formState?.result?.result
371
- ? !!formState?.result?.result?.settings?.notification?.newsletter
372
- : !!(formState?.changes?.settings?.notification?.newsletter ?? (user && user?.settings?.notification?.newsletter))}
373
- />
374
- <label
375
- htmlFor='promotions'
376
- >
377
- <span>{t('RECEIVE_NEWS_EXCLUSIVE_PROMOTIONS', 'Receive newsletters and exclusive promotions')}</span>
378
- </label>
379
- </PromotionsWrapper>
390
+ {showNotifications && showCustomerPromotions && !requiredFields && (
391
+ <>
392
+ <NotificationsGroupSwitchWrapper>
393
+ <p>{t('MARKETING_NOTIFICATIONS', 'Marketing Notifications')}</p>
394
+ <SwitchWrapper>
395
+ <p>{t('EMAILS', 'Emails')}</p>
396
+ <Switch
397
+ onChange={value => handleEditNotifications('email', value)}
398
+ defaultChecked={notificationList?.email}
399
+ />
400
+ </SwitchWrapper>
401
+ <SwitchWrapper>
402
+ <p>{t('SMS', 'Sms')}</p>
403
+ <Switch
404
+ onChange={value => handleEditNotifications('sms', value)}
405
+ defaultChecked={notificationList?.sms}
406
+ />
407
+ </SwitchWrapper>
408
+ <SwitchWrapper>
409
+ <p>{t('PUSH_NOTIFICATIONS', 'Push Notifications')}</p>
410
+ <Switch
411
+ onChange={value => handleEditNotifications('notification', value)}
412
+ defaultChecked={notificationList?.notification}
413
+ />
414
+ </SwitchWrapper>
415
+ </NotificationsGroupSwitchWrapper>
416
+ </>
380
417
  )}
381
418
  {showLangauges && !requiredFields && (
382
419
  <>
383
- <Divider />
384
420
  <LanguageSelectorWrapper>
385
421
  <p>{t('LANGUAGE', 'Language')}</p>
386
422
  <LanguageSelector />
@@ -182,3 +182,29 @@ export const PromotionsWrapper = styled.div`
182
182
  }
183
183
  }
184
184
  `
185
+
186
+ export const NotificationsGroupSwitchWrapper = styled.div`
187
+ display: flex;
188
+ align-items: center;
189
+ flex-direction: column;
190
+ width: 100%;
191
+ padding: 15px 0;
192
+ margin-bottom: 20px;
193
+ border-bottom: 1px solid #E9ECEF;
194
+
195
+ > p {
196
+ margin: 0;
197
+ font-weight: 500;
198
+ font-size: 20px;
199
+ color: ${props => props.theme.colors.darkTextColor};
200
+ width: 100%;
201
+ text-align: left;
202
+ }
203
+ `
204
+
205
+ export const SwitchWrapper = styled.div`
206
+ display: flex;
207
+ align-items: center;
208
+ justify-content: space-between;
209
+ width: 100%;
210
+ `