ordering-ui-external 1.6.8 → 1.7.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.
Files changed (107) hide show
  1. package/_bundles/{0.ordering-ui.7635bd47ae9a481b3f59.js → 0.ordering-ui.8b7044a2b34939a44465.js} +0 -0
  2. package/_bundles/{1.ordering-ui.7635bd47ae9a481b3f59.js → 1.ordering-ui.8b7044a2b34939a44465.js} +0 -0
  3. package/_bundles/{2.ordering-ui.7635bd47ae9a481b3f59.js → 2.ordering-ui.8b7044a2b34939a44465.js} +0 -0
  4. package/_bundles/{4.ordering-ui.7635bd47ae9a481b3f59.js → 4.ordering-ui.8b7044a2b34939a44465.js} +0 -0
  5. package/_bundles/{5.ordering-ui.7635bd47ae9a481b3f59.js → 5.ordering-ui.8b7044a2b34939a44465.js} +0 -0
  6. package/_bundles/{6.ordering-ui.7635bd47ae9a481b3f59.js → 6.ordering-ui.8b7044a2b34939a44465.js} +0 -0
  7. package/_bundles/{7.ordering-ui.7635bd47ae9a481b3f59.js → 7.ordering-ui.8b7044a2b34939a44465.js} +1 -1
  8. package/_bundles/{7.ordering-ui.7635bd47ae9a481b3f59.js.LICENSE.txt → 7.ordering-ui.8b7044a2b34939a44465.js.LICENSE.txt} +0 -0
  9. package/_bundles/{8.ordering-ui.7635bd47ae9a481b3f59.js → 8.ordering-ui.8b7044a2b34939a44465.js} +0 -0
  10. package/_bundles/{9.ordering-ui.7635bd47ae9a481b3f59.js → 9.ordering-ui.8b7044a2b34939a44465.js} +0 -0
  11. package/_bundles/ordering-ui.8b7044a2b34939a44465.js +2 -0
  12. package/_bundles/{ordering-ui.7635bd47ae9a481b3f59.js.LICENSE.txt → ordering-ui.8b7044a2b34939a44465.js.LICENSE.txt} +0 -0
  13. package/_modules/components/BusinessInformation/index.js +8 -10
  14. package/_modules/components/LoginForm/index.js +58 -17
  15. package/_modules/components/SignUpForm/index.js +61 -20
  16. package/_modules/themes/callcenterOriginal/src/components/LoginForm/index.js +71 -25
  17. package/_modules/themes/callcenterOriginal/src/components/SignUpForm/index.js +60 -19
  18. package/_modules/themes/eight/src/components/LoginForm/index.js +63 -20
  19. package/_modules/themes/eight/src/components/SignUpForm/index.js +63 -22
  20. package/_modules/themes/five/src/components/BusinessController/index.js +2 -2
  21. package/_modules/themes/five/src/components/BusinessPreorder/index.js +6 -45
  22. package/_modules/themes/five/src/components/BusinessProductsListing/index.js +1 -1
  23. package/_modules/themes/five/src/components/Checkout/index.js +19 -3
  24. package/_modules/themes/five/src/components/Checkout/styles.js +5 -3
  25. package/_modules/themes/five/src/components/Footer/styles.js +1 -1
  26. package/_modules/themes/five/src/components/Header/index.js +3 -3
  27. package/_modules/themes/five/src/components/Header/styles.js +1 -1
  28. package/_modules/themes/five/src/components/HomeHero/layouts/OriginalHomeHero/index.js +1 -1
  29. package/_modules/themes/five/src/components/MomentControl/index.js +1 -41
  30. package/_modules/themes/five/src/components/OrderDetails/OrderBillSection.js +2 -2
  31. package/_modules/themes/five/src/components/OrderDetails/index.js +14 -16
  32. package/_modules/themes/five/src/components/OrderDetails/styles.js +7 -3
  33. package/_modules/themes/five/src/components/PaymentOptions/index.js +3 -6
  34. package/_modules/themes/five/src/components/PlaceSpot/styles.js +2 -2
  35. package/_modules/themes/five/src/components/ProductItemAccordion/index.js +7 -4
  36. package/_modules/themes/five/src/components/ProductOption/index.js +1 -1
  37. package/_modules/themes/five/src/components/ProductOptionSubOption/index.js +1 -1
  38. package/_modules/themes/five/src/components/ProfessionalProfile/index.js +1 -1
  39. package/_modules/themes/five/src/components/ServiceForm/index.js +136 -24
  40. package/_modules/themes/five/src/components/ServiceForm/styles.js +45 -3
  41. package/_modules/themes/four/src/components/LoginForm/index.js +64 -20
  42. package/_modules/themes/four/src/components/LoginForm/styles.js +5 -3
  43. package/_modules/themes/four/src/components/SignUpForm/index.js +67 -22
  44. package/_modules/themes/four/src/components/SignUpForm/styles.js +5 -3
  45. package/_modules/themes/franchise/src/components/LoginForm/index.js +61 -20
  46. package/_modules/themes/franchise/src/components/SignUpForm/index.js +57 -16
  47. package/_modules/themes/seven/src/components/LoginForm/index.js +60 -17
  48. package/_modules/themes/seven/src/components/SignUpForm/index.js +60 -19
  49. package/_modules/themes/six/src/components/LoginForm/index.js +62 -20
  50. package/_modules/themes/six/src/components/SignUpForm/index.js +58 -17
  51. package/_modules/themes/three/src/components/LoginForm/index.js +64 -20
  52. package/_modules/themes/three/src/components/LoginForm/styles.js +5 -3
  53. package/_modules/themes/three/src/components/SignUpForm/index.js +63 -18
  54. package/_modules/themes/three/src/components/SignUpForm/styles.js +5 -3
  55. package/_modules/themes/two/src/components/LoginForm/index.js +57 -17
  56. package/_modules/themes/two/src/components/SignUpForm/index.js +57 -17
  57. package/_modules/utils/index.js +56 -2
  58. package/package.json +2 -2
  59. package/src/components/BusinessInformation/index.js +8 -6
  60. package/src/components/LoginForm/index.js +32 -6
  61. package/src/components/SignUpForm/index.js +27 -2
  62. package/src/themes/callcenterOriginal/src/components/LoginForm/index.js +30 -2
  63. package/src/themes/callcenterOriginal/src/components/SignUpForm/index.js +27 -1
  64. package/src/themes/eight/src/components/LoginForm/index.js +30 -0
  65. package/src/themes/eight/src/components/SignUpForm/index.js +27 -1
  66. package/src/themes/five/src/components/BusinessController/index.js +2 -2
  67. package/src/themes/five/src/components/BusinessPreorder/index.js +6 -46
  68. package/src/themes/five/src/components/BusinessProductsListing/index.js +1 -1
  69. package/src/themes/five/src/components/Checkout/index.js +28 -3
  70. package/src/themes/five/src/components/Checkout/styles.js +30 -0
  71. package/src/themes/five/src/components/Footer/styles.js +1 -5
  72. package/src/themes/five/src/components/Header/index.js +7 -6
  73. package/src/themes/five/src/components/Header/styles.js +1 -3
  74. package/src/themes/five/src/components/HomeHero/layouts/OriginalHomeHero/index.js +1 -1
  75. package/src/themes/five/src/components/MomentControl/index.js +1 -42
  76. package/src/themes/five/src/components/OrderDetails/OrderBillSection.js +1 -1
  77. package/src/themes/five/src/components/OrderDetails/index.js +10 -8
  78. package/src/themes/five/src/components/OrderDetails/styles.js +21 -1
  79. package/src/themes/five/src/components/PaymentOptions/index.js +25 -26
  80. package/src/themes/five/src/components/PlaceSpot/styles.js +14 -4
  81. package/src/themes/five/src/components/ProductItemAccordion/index.js +7 -3
  82. package/src/themes/five/src/components/ProductOption/index.js +1 -1
  83. package/src/themes/five/src/components/ProductOptionSubOption/index.js +1 -1
  84. package/src/themes/five/src/components/ProfessionalProfile/index.js +1 -1
  85. package/src/themes/five/src/components/ServiceForm/index.js +151 -11
  86. package/src/themes/five/src/components/ServiceForm/styles.js +148 -0
  87. package/src/themes/four/src/components/LoginForm/index.js +37 -5
  88. package/src/themes/four/src/components/LoginForm/styles.js +4 -0
  89. package/src/themes/four/src/components/SignUpForm/index.js +39 -5
  90. package/src/themes/four/src/components/SignUpForm/styles.js +4 -0
  91. package/src/themes/franchise/src/components/LoginForm/index.js +26 -1
  92. package/src/themes/franchise/src/components/SignUpForm/index.js +27 -1
  93. package/src/themes/seven/src/components/LoginForm/index.js +31 -0
  94. package/src/themes/seven/src/components/SignUpForm/index.js +27 -1
  95. package/src/themes/six/src/components/LoginForm/index.js +28 -1
  96. package/src/themes/six/src/components/SignUpForm/index.js +27 -1
  97. package/src/themes/three/src/components/LoginForm/index.js +38 -6
  98. package/src/themes/three/src/components/LoginForm/styles.js +4 -0
  99. package/src/themes/three/src/components/SignUpForm/index.js +40 -4
  100. package/src/themes/three/src/components/SignUpForm/styles.js +4 -0
  101. package/src/themes/two/src/components/LoginForm/index.js +25 -1
  102. package/src/themes/two/src/components/SignUpForm/index.js +28 -3
  103. package/src/utils/index.js +53 -0
  104. package/template/app.js +15 -3
  105. package/template/config.json +1 -0
  106. package/template/pages/BusinessProductsList/index.js +2 -2
  107. package/_bundles/ordering-ui.7635bd47ae9a481b3f59.js +0 -2
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useRef, useState } from 'react'
2
2
  import { Swiper, SwiperSlide } from 'swiper/react'
3
- import { useUtils, useLanguage, useSession, ProductForm as ProductFormController } from 'ordering-components-external'
3
+ import { useUtils, useLanguage, useSession, useConfig, ProductForm as ProductFormController } from 'ordering-components-external'
4
4
  import Skeleton from 'react-loading-skeleton'
5
5
  import { Alert } from '../Confirm'
6
6
  import { Modal } from '../Modal'
@@ -10,8 +10,10 @@ import { ForgotPasswordForm } from '../ForgotPasswordForm'
10
10
  import { useTheme } from 'styled-components'
11
11
  import FaUserAlt from '@meronex/icons/fa/FaUserAlt'
12
12
  import { ChevronLeft, ChevronRight, ChevronDown } from 'react-bootstrap-icons'
13
- import { BusinessPreorder } from '../BusinessPreorder'
13
+ import BsCaretLeftFill from '@meronex/icons/bs/BsCaretLeftFill'
14
14
  import { Button } from '../../styles/Buttons'
15
+ import moment from 'moment'
16
+ import { getTimes } from '../../../../../utils'
15
17
  import SwiperCore, { Navigation } from 'swiper'
16
18
  import 'swiper/swiper-bundle.min.css'
17
19
  import 'swiper/swiper.min.css'
@@ -36,11 +38,22 @@ import {
36
38
  DropDownWrapper,
37
39
  DropDownTitle,
38
40
  EmptyProfessional,
39
- SkeletonBlock
41
+ SkeletonBlock,
42
+ OrderTimeWrapper,
43
+ DateWrapper,
44
+ MonthYearLayer,
45
+ DaysSwiper,
46
+ Day,
47
+ DayName,
48
+ DayNumber,
49
+ TimeListWrapper,
50
+ TimeItem,
51
+ ClosedBusinessMsg
40
52
  } from './styles'
41
- import moment from 'moment'
42
53
  SwiperCore.use([Navigation])
43
54
 
55
+ const maxDate = 40
56
+
44
57
  const ServiceFormUI = (props) => {
45
58
  const {
46
59
  productObject,
@@ -56,14 +69,21 @@ const ServiceFormUI = (props) => {
56
69
  const { product, loading, error } = productObject
57
70
  const theme = useTheme()
58
71
  const [, t] = useLanguage()
72
+ const [{ configs }] = useConfig()
59
73
  const [{ parsePrice, parseDate }] = useUtils()
60
74
  const [{ auth }, { login }] = useSession()
61
75
  const [modalPageToShow, setModalPageToShow] = useState('login')
62
76
  const [modalIsOpen, setModalIsOpen] = useState(false)
63
77
  const [isDropDown, setIsDropDown] = useState(false)
64
78
  const [currentProfessional, setCurrentProfessional] = useState(null)
79
+ const [timeList, setTimeList] = useState([])
80
+ const [timeSelected, setTimeSelected] = useState(null)
81
+ const [selectDate, setSelectedDate] = useState(new Date())
82
+ const [isEnabled, setIsEnabled] = useState(false)
83
+ const [datesList, setDatesList] = useState([])
65
84
 
66
85
  const dropDownRef = useRef()
86
+ const is12Hours = configs?.format_time?.value === '12'
67
87
 
68
88
  const closeModal = () => {
69
89
  setModalIsOpen(false)
@@ -115,6 +135,13 @@ const ServiceFormUI = (props) => {
115
135
  handleSave(values)
116
136
  }
117
137
 
138
+ const handleChangeTime = (time) => {
139
+ if (!time || time === timeSelected) return
140
+ const _moment = moment(`${moment(selectDate).format('YYYY-MM-DD')} ${time}`, 'YYYY-MM-DD HH:mm').toDate()
141
+ setTimeSelected(time)
142
+ setDateSelected(_moment)
143
+ }
144
+
118
145
  const isBusyTime = (professional) => {
119
146
  if (professional?.busy_times?.length === 0 || !dateSelected) return false
120
147
  const valid = professional?.busy_times.some(item => {
@@ -134,6 +161,31 @@ const ServiceFormUI = (props) => {
134
161
  setCurrentProfessional(professional)
135
162
  }
136
163
 
164
+ const validateSelectedDate = (curdate, menu) => {
165
+ const day = moment(curdate).format('d')
166
+ setIsEnabled(menu?.schedule?.[day]?.enabled || false)
167
+ }
168
+
169
+ const getTimeList = (curdate, menu) => {
170
+ validateSelectedDate(curdate, menu)
171
+ const selectedDate = new Date(curdate)
172
+ const times = getTimes(selectedDate, menu?.schedule, is12Hours)
173
+ return times
174
+ }
175
+
176
+ const validDate = (date) => {
177
+ if (!date) return
178
+ const _date = moment(date, 'YYYY-MM-DD HH:mm').isSameOrAfter(moment(), 'day')
179
+ ? moment(date).format('YYYY-MM-DD HH:mm')
180
+ : moment().format('YYYY-MM-DD HH:mm')
181
+ return _date
182
+ }
183
+
184
+ const handleChangeDate = (date) => {
185
+ setSelectedDate(date)
186
+ setTimeSelected(null)
187
+ }
188
+
137
189
  useEffect(() => {
138
190
  const imageList = []
139
191
  imageList.push(product?.images || theme.images?.dummies?.product)
@@ -166,6 +218,27 @@ const ServiceFormUI = (props) => {
166
218
  }
167
219
  }, [isCartProduct, professionalListState?.professionals])
168
220
 
221
+ useEffect(() => {
222
+ if (selectDate === null || currentProfessional === null) return
223
+ const _times = getTimeList(selectDate, currentProfessional)
224
+ setTimeList(_times)
225
+ }, [selectDate, currentProfessional])
226
+
227
+ useEffect(() => {
228
+ const _datesList = []
229
+
230
+ for (let i = 0; i < maxDate + 1; i++) {
231
+ _datesList.push(moment(validDate(new Date())).add(i, 'd').format('YYYY-MM-DD'))
232
+ }
233
+ setDatesList(_datesList)
234
+ }, [])
235
+
236
+ useEffect(() => {
237
+ if (!productCart?.calendar_event?.start) return
238
+ setSelectedDate(moment.utc(productCart?.calendar_event?.start).local())
239
+ setTimeSelected(moment.utc(productCart?.calendar_event?.start).local().format('HH:mm'))
240
+ }, [productCart])
241
+
169
242
  return (
170
243
  <>
171
244
  <Container>
@@ -289,13 +362,80 @@ const ServiceFormUI = (props) => {
289
362
  <span>{t('REQUIRED', 'Required')}</span>
290
363
  </SectionHeader>
291
364
  {currentProfessional ? (
292
- <BusinessPreorder
293
- business={currentProfessional}
294
- isProfessional
295
- maxDays={50}
296
- onChangeMoment={setDateSelected}
297
- useOrderContext={false}
298
- />
365
+ <OrderTimeWrapper>
366
+ <DateWrapper>
367
+ <MonthYearLayer>
368
+ <span>{moment(dateSelected).format('MMMM, yyyy')}</span>
369
+ </MonthYearLayer>
370
+ <DaysSwiper left={<BsCaretLeftFill />}>
371
+ <Swiper
372
+ spaceBetween={0}
373
+ navigation
374
+ breakpoints={{
375
+ 0: {
376
+ slidesPerView: 4,
377
+ spaceBetween: 0
378
+ },
379
+ 400: {
380
+ slidesPerView: 5,
381
+ spaceBetween: 0
382
+ },
383
+ 550: {
384
+ slidesPerView: 6,
385
+ spaceBetween: 0
386
+ },
387
+ 769: {
388
+ slidesPerView: 7,
389
+ spaceBetween: 0
390
+ }
391
+ }}
392
+ freeMode
393
+ watchSlidesProgress
394
+ className='swiper-datelist'
395
+ preventClicksPropagation={false}
396
+ >
397
+ {
398
+ datesList.slice(0, Number(maxDate - 1, 10)).map((date, i) => {
399
+ const dateParts = date.split('-')
400
+ const _date = new Date(dateParts[0], dateParts[1] - 1, dateParts[2])
401
+ const dayName = t('DAY' + (_date.getDay() >= 1 ? _date.getDay() : 7)).substring(0, 2)
402
+ const dayNumber = (_date.getDate() < 10 ? '0' : '') + _date.getDate()
403
+ return (
404
+ <SwiperSlide key={i}>
405
+ <Day
406
+ selected={moment(selectDate).format('YYYY-MM-DD') === date}
407
+ onClick={() => handleChangeDate(moment(date))}
408
+ >
409
+ <DayName>{dayName}</DayName>
410
+ <DayNumber>{dayNumber}</DayNumber>
411
+ </Day>
412
+ </SwiperSlide>
413
+ )
414
+ })
415
+ }
416
+ </Swiper>
417
+ </DaysSwiper>
418
+ </DateWrapper>
419
+ <TimeListWrapper>
420
+ {(isEnabled && timeList?.length > 0) ? (
421
+ <>
422
+ {timeList.map((time, i) => (
423
+ <TimeItem
424
+ key={i}
425
+ active={timeSelected === time.value}
426
+ onClick={() => handleChangeTime(time.value)}
427
+ >
428
+ <span>{time.text}</span>
429
+ </TimeItem>
430
+ ))}
431
+ </>
432
+ ) : (
433
+ <ClosedBusinessMsg>
434
+ {t('PROFESSIONAL_NOT_AVAILABLE', 'Professional is not available at the moment')}
435
+ </ClosedBusinessMsg>
436
+ )}
437
+ </TimeListWrapper>
438
+ </OrderTimeWrapper>
299
439
  ) : (
300
440
  <EmptyProfessional>
301
441
  {t('NO_SCHEDULE', 'No schedule')}
@@ -321,3 +321,151 @@ export const SkeletonBlock = styled.div`
321
321
  margin-bottom: 10px;
322
322
  }
323
323
  `
324
+
325
+ export const OrderTimeWrapper = styled.div``
326
+
327
+ export const DateWrapper = styled.div``
328
+
329
+ export const MonthYearLayer = styled.div`
330
+ margin-top: 0px;
331
+ margin-bottom: 13px;
332
+
333
+ span {
334
+ font-size: 16px;
335
+ line-height: 24px;
336
+ }
337
+ `
338
+
339
+ export const DaysSwiper = styled.div`
340
+ width: 100%;
341
+ position: relative;
342
+ border-top: 1px solid ${props => props.theme.colors.gray200};
343
+ border-bottom: 1px solid ${props => props.theme.colors.gray200};
344
+
345
+ .swiper-datelist {
346
+ padding: 0 20px;
347
+ .swiper-button-prev {
348
+ background-image: url("data:image/svg+xml,%3Csvg stroke='currentColor' fill='currentColor' stroke-width='0' viewBox='0 0 16 16' height='1em' width='1em' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M3.86 8.753l5.482 4.796c.646.566 1.658.106 1.658-.753V3.204a1 1 0 00-1.659-.753l-5.48 4.796a1 1 0 000 1.506z'%3E%3C/path%3E%3C/svg%3E");
349
+ background-repeat: no-repeat;
350
+ background-size: 100% auto;
351
+ background-position: center;
352
+ width: 20px;
353
+ }
354
+
355
+ .swiper-button-prev::after {
356
+ display: none;
357
+ }
358
+ .swiper-button-next {
359
+ background-image: url("data:image/svg+xml,%3Csvg stroke='currentColor' fill='currentColor' stroke-width='0' viewBox='0 0 16 16' height='1em' width='1em' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.14 8.753l-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 011.659-.753l5.48 4.796a1 1 0 010 1.506z'%3E%3C/path%3E%3C/svg%3E");
360
+ background-repeat: no-repeat;
361
+ background-size: 100% auto;
362
+ background-position: center;
363
+ width: 18px;
364
+ }
365
+
366
+ .swiper-button-next::after {
367
+ display: none;
368
+ }
369
+
370
+ .swiper-button-next, .swiper-container-rtl .swiper-button-prev {
371
+ right: 0px;
372
+ left: auto;
373
+ }
374
+ .swiper-button-prev, .swiper-container-rtl .swiper-button-next {
375
+ left: 0px;
376
+ right: auto;
377
+ }
378
+ }
379
+ `
380
+
381
+ export const Day = styled.div`
382
+ display: flex;
383
+ flex-grow: 1;
384
+ color: ${props => props.theme.colors.lightGray};
385
+ cursor: pointer;
386
+ padding: 14px 0 13px 0;
387
+ flex-direction: column;
388
+ align-items: center;
389
+ transition: background-color .16s ease -0.01s;
390
+
391
+ ${({ selected }) => selected && css`
392
+ color: ${props => props.theme.colors.headingColor};
393
+ `}
394
+
395
+ :hover {
396
+ background-color: ${props => props.theme.colors.gray200};
397
+ }
398
+ `
399
+
400
+ export const DayName = styled.div`
401
+ display: flex;
402
+ font-size: 14px;
403
+ line-height: 24px;
404
+ margin-bottom: 10px;
405
+ &:first-letter {
406
+ text-transform: uppercase;
407
+ }
408
+ `
409
+
410
+ export const DayNumber = styled.div`
411
+ display: flex;
412
+ font-weight: 500;
413
+ font-size: 20px;
414
+ line-height: 30px;
415
+ `
416
+
417
+ export const TimeListWrapper = styled.div`
418
+ display: flex;
419
+ flex-wrap: wrap;
420
+ margin-left: -12px;
421
+ width: calc(100% + 24px);
422
+ margin-top: 30px;
423
+ max-height: 250px;
424
+ overflow: auto;
425
+ `
426
+
427
+ export const TimeItem = styled.div`
428
+ cursor: pointer;
429
+ display: flex;
430
+ justify-content: center;
431
+ align-items: center;
432
+ background: ${props => props.theme.colors.gray200};
433
+ border-radius: 7.6px;
434
+ padding: 5px 15px;
435
+ margin: 12px;
436
+ width: calc(50% - 24px);
437
+ min-width: calc(50% - 24px);
438
+ box-sizing: border-box;
439
+ user-select: none;
440
+
441
+ ${({ active }) => active && css`
442
+ background: ${props => props.theme.colors.primaryContrast};
443
+ color: ${props => props.theme.colors.primary};
444
+ `}
445
+
446
+ span {
447
+ font-size: 14px;
448
+ white-space: nowrap;
449
+ }
450
+
451
+ @media (min-width: 400px) {
452
+ width: calc(33.33% - 24px);
453
+ min-width: calc(33.33% - 24px);
454
+ }
455
+
456
+ @media (min-width: 576px) {
457
+ width: calc(25% - 24px);
458
+ min-width: calc(25% - 24px);
459
+ }
460
+
461
+ @media (min-width: 769px) {
462
+ width: calc(16.66% - 24px);
463
+ min-width: calc(16.66% - 24px);
464
+ }
465
+ `
466
+
467
+ export const ClosedBusinessMsg = styled.div`
468
+ text-align: center;
469
+ font-size: 16px;
470
+ width: 100%;
471
+ `
@@ -6,6 +6,7 @@ import {
6
6
  useLanguage,
7
7
  useConfig,
8
8
  useSession,
9
+ ReCaptcha
9
10
  } from 'ordering-components-external'
10
11
  import RiPhoneLine from '@meronex/icons/ri/RiPhoneLine'
11
12
  import GoMail from '@meronex/icons/go/GoMail'
@@ -29,7 +30,8 @@ import {
29
30
  Slogan,
30
31
  LoginWithButton,
31
32
  OrContainer,
32
- Line
33
+ Line,
34
+ ReCaptchaWrapper
33
35
  } from './styles'
34
36
 
35
37
  // import { Tabs, Tab } from '../../styles/Tabs'
@@ -40,6 +42,7 @@ import { FacebookLoginButton } from '../FacebookLogin'
40
42
  import { AppleLogin } from '../AppleLogin'
41
43
  import { SmsLoginButton } from '../../../../../components/SmsLogin'
42
44
  import { useCountdownTimer } from '../../../../../hooks/useCountdownTimer'
45
+ import { useRecaptcha } from '../../../../../hooks/useRecaptcha'
43
46
  import { formatSeconds } from '../../../../../utils'
44
47
  import { useTheme } from 'styled-components'
45
48
  import parsePhoneNumber from 'libphonenumber-js'
@@ -52,6 +55,7 @@ const LoginFormUI = (props) => {
52
55
  useLoginByEmail,
53
56
  useLoginByCellphone,
54
57
  handleChangeInput,
58
+ handleReCaptcha,
55
59
  handleChangeTab,
56
60
  handleButtonLoginClick,
57
61
  handleSendVerifyCode,
@@ -63,13 +67,16 @@ const LoginFormUI = (props) => {
63
67
  checkPhoneCodeState,
64
68
  loginTab,
65
69
  isPopup,
66
- credentials
70
+ credentials,
71
+ enableReCaptcha
67
72
  } = props
68
73
  const numOtpInputs = 4
69
74
  const [, t] = useLanguage()
70
75
  const [{ configs }] = useConfig()
71
76
  const formMethods = useForm()
77
+ const [recaptchaConfig] = useRecaptcha(enableReCaptcha)
72
78
  const [alertState, setAlertState] = useState({ open: false, content: [] })
79
+ const [reCaptchaVersion, setRecaptchaVersion] = useState({ version: '', siteKey: '' })
73
80
  const [, { login }] = useSession()
74
81
  const theme = useTheme()
75
82
  const [passwordSee, setPasswordSee] = useState(false)
@@ -175,12 +182,25 @@ const LoginFormUI = (props) => {
175
182
 
176
183
  useEffect(() => {
177
184
  if (!formState.loading && formState.result?.error) {
185
+ if (formState.result?.result?.[0] === 'ERROR_AUTH_VERIFICATION_CODE') {
186
+ if (configs?.security_recaptcha_site_key?.value) {
187
+ setRecaptchaVersion({ version: 'v2', siteKey: configs?.security_recaptcha_site_key?.value })
188
+ setAlertState({
189
+ open: true,
190
+ content: [t('TRY_AGAIN', 'Please try again')]
191
+ })
192
+ return
193
+ }
194
+ setAlertState({
195
+ open: true,
196
+ content: [t('CONFIG_DOESNOT_RECAPTCHA_KEY', 'the config doesn\'t have recaptcha site key')]
197
+ })
198
+ return
199
+ }
178
200
  setAlertState({
179
201
  open: true,
180
202
  content: formState.result?.result || [t('ERROR', 'Error')]
181
203
  })
182
-
183
- return
184
204
  }
185
205
  }, [formState])
186
206
 
@@ -250,6 +270,12 @@ const LoginFormUI = (props) => {
250
270
 
251
271
  }, [verifyPhoneState])
252
272
 
273
+ useEffect(() => {
274
+ if (recaptchaConfig?.siteKey) {
275
+ setRecaptchaVersion({ version: recaptchaConfig?.version, siteKey: recaptchaConfig?.siteKey })
276
+ }
277
+ }, [recaptchaConfig])
278
+
253
279
  return (
254
280
  <>
255
281
  {props.beforeElements?.map((BeforeElement, i) => (
@@ -374,6 +400,11 @@ const LoginFormUI = (props) => {
374
400
  props.afterMidComponents?.map((MidComponent, i) => (
375
401
  <MidComponent key={i} {...props} />))
376
402
  }
403
+ {props.isRecaptchaEnable && enableReCaptcha && (
404
+ <ReCaptchaWrapper>
405
+ <ReCaptcha handleReCaptcha={handleReCaptcha} reCaptchaVersion={reCaptchaVersion} />
406
+ </ReCaptchaWrapper>
407
+ )}
377
408
  {(!willVerifyOtpState &&
378
409
  <Button
379
410
  color='primary'
@@ -499,7 +530,8 @@ const LoginFormUI = (props) => {
499
530
  export const LoginForm = (props) => {
500
531
  const loginControllerProps = {
501
532
  ...props,
502
- UIComponent: LoginFormUI
533
+ UIComponent: LoginFormUI,
534
+ isRecaptchaEnable: true
503
535
  }
504
536
  return <LoginFormController {...loginControllerProps} />
505
537
  }
@@ -350,3 +350,7 @@ export const Line = styled.div`
350
350
  border-bottom: 1px solid ${props => props.theme.colors?.grayColor};
351
351
  flex: 1;
352
352
  `
353
+
354
+ export const ReCaptchaWrapper = styled.div`
355
+ margin: 12px auto;
356
+ `
@@ -9,7 +9,8 @@ import {
9
9
  SignupForm as SignUpController,
10
10
  useLanguage,
11
11
  useConfig,
12
- useSession
12
+ useSession,
13
+ ReCaptcha
13
14
  } from 'ordering-components-external'
14
15
 
15
16
  import { Alert } from '../../../../../components/Confirm'
@@ -21,6 +22,7 @@ import { AppleLogin } from '../AppleLogin'
21
22
  import { Input } from '../../styles/Inputs'
22
23
  import { Button } from '../../styles/Buttons'
23
24
  import { Checkbox } from '../../../../../styles/Checkbox'
25
+ import { useRecaptcha } from '../../../../../hooks/useRecaptcha'
24
26
 
25
27
  import {
26
28
  HeroContainer,
@@ -38,7 +40,8 @@ import {
38
40
  Slogan,
39
41
  OrContainer,
40
42
  Line,
41
- TermsConditionWrapper
43
+ TermsConditionWrapper,
44
+ ReCaptchaWrapper
42
45
  } from './styles'
43
46
  const notValidationFields = ['coupon', 'driver_tip', 'mobile_phone', 'address', 'address_notes']
44
47
 
@@ -57,11 +60,15 @@ const SignUpFormUI = (props) => {
57
60
  externalPhoneNumber,
58
61
  saveCustomerUser,
59
62
  fieldsNotValid,
60
- signupData
63
+ signupData,
64
+ enableReCaptcha,
65
+ handleReCaptcha
61
66
  } = props
62
67
  const [, t] = useLanguage()
63
68
  const [{ configs }] = useConfig()
64
69
  const formMethods = useForm()
70
+ const [recaptchaConfig] = useRecaptcha(enableReCaptcha)
71
+ const [reCaptchaVersion, setRecaptchaVersion] = useState({ version: '', siteKey: '' })
65
72
  const [alertState, setAlertState] = useState({ open: false, content: [] })
66
73
  const [, { login }] = useSession()
67
74
 
@@ -167,6 +174,22 @@ const SignUpFormUI = (props) => {
167
174
 
168
175
  useEffect(() => {
169
176
  if (!formState.loading && formState.result?.error) {
177
+ if (formState.result?.result?.[0] === 'ERROR_AUTH_VERIFICATION_CODE') {
178
+ if (configs?.security_recaptcha_site_key?.value) {
179
+ setRecaptchaVersion({ version: 'v2', siteKey: configs?.security_recaptcha_site_key?.value })
180
+ setAlertState({
181
+ open: true,
182
+ content: [t('TRY_AGAIN', 'Please try again')]
183
+ })
184
+ return
185
+ }
186
+ setAlertState({
187
+ open: true,
188
+ content: [t('CONFIG_DOESNOT_RECAPTCHA_KEY', 'the config doesn\'t have recaptcha site key')]
189
+ })
190
+ return
191
+ }
192
+
170
193
  setAlertState({
171
194
  open: true,
172
195
  content: formState.result?.result || [t('ERROR', 'Error')]
@@ -222,6 +245,12 @@ const SignUpFormUI = (props) => {
222
245
  }
223
246
  }, [externalPhoneNumber])
224
247
 
248
+ useEffect(() => {
249
+ if (recaptchaConfig?.siteKey) {
250
+ setRecaptchaVersion({ version: recaptchaConfig?.version, siteKey: recaptchaConfig?.siteKey })
251
+ }
252
+ }, [recaptchaConfig])
253
+
225
254
  return (
226
255
  <>
227
256
  {props.beforeElements?.map((BeforeElement, i) => (
@@ -360,7 +389,11 @@ const SignUpFormUI = (props) => {
360
389
  </label>
361
390
  </TermsConditionWrapper>
362
391
  )}
363
-
392
+ {props.isRecaptchaEnable && enableReCaptcha && (
393
+ <ReCaptchaWrapper>
394
+ <ReCaptcha handleReCaptcha={handleReCaptcha} reCaptchaVersion={reCaptchaVersion} />
395
+ </ReCaptchaWrapper>
396
+ )}
364
397
  <Button
365
398
  color='primary'
366
399
  type='submit'
@@ -430,7 +463,8 @@ const SignUpFormUI = (props) => {
430
463
  export const SignUpForm = (props) => {
431
464
  const loginControllerProps = {
432
465
  ...props,
433
- UIComponent: SignUpFormUI
466
+ UIComponent: SignUpFormUI,
467
+ isRecaptchaEnable: true
434
468
  }
435
469
  return <SignUpController {...loginControllerProps} />
436
470
  }
@@ -317,3 +317,7 @@ export const TermsConditionWrapper = styled.div`
317
317
  }
318
318
  }
319
319
  `
320
+
321
+ export const ReCaptchaWrapper = styled.div`
322
+ margin: 12px auto;
323
+ `
@@ -39,6 +39,7 @@ import { FacebookLoginButton } from '../FacebookLogin'
39
39
  import { AppleLogin } from '../AppleLogin'
40
40
  import { SmsLoginButton } from '../../../../../components/SmsLogin'
41
41
  import { useCountdownTimer } from '../../../../../hooks/useCountdownTimer'
42
+ import { useRecaptcha } from '../../../../../hooks/useRecaptcha'
42
43
  import { formatSeconds } from '../../../../../utils'
43
44
  import parsePhoneNumber from 'libphonenumber-js'
44
45
  import OtpInput from 'react-otp-input'
@@ -73,6 +74,8 @@ const LoginFormUI = (props) => {
73
74
  const theme = useTheme()
74
75
  const [{ configs }] = useConfig()
75
76
  const formMethods = useForm()
77
+ const [recaptchaConfig] = useRecaptcha(enableReCaptcha)
78
+ const [reCaptchaVersion, setRecaptchaVersion] = useState({ version: '', siteKey: '' })
76
79
  const [alertState, setAlertState] = useState({ open: false, content: [] })
77
80
  const [, { login }] = useSession()
78
81
  const [passwordSee, setPasswordSee] = useState(false)
@@ -180,6 +183,21 @@ const LoginFormUI = (props) => {
180
183
 
181
184
  useEffect(() => {
182
185
  if (!formState.loading && formState.result?.error) {
186
+ if (formState.result?.result?.[0] === 'ERROR_AUTH_VERIFICATION_CODE') {
187
+ if (configs?.security_recaptcha_site_key?.value) {
188
+ setRecaptchaVersion({ version: 'v2', siteKey: configs?.security_recaptcha_site_key?.value })
189
+ setAlertState({
190
+ open: true,
191
+ content: [t('TRY_AGAIN', 'Please try again')]
192
+ })
193
+ return
194
+ }
195
+ setAlertState({
196
+ open: true,
197
+ content: [t('CONFIG_DOESNOT_RECAPTCHA_KEY', 'the config doesn\'t have recaptcha site key')]
198
+ })
199
+ return
200
+ }
183
201
  setAlertState({
184
202
  open: true,
185
203
  content: formState.result?.result || [t('ERROR', 'Error')]
@@ -247,6 +265,12 @@ const LoginFormUI = (props) => {
247
265
  } else resetOtpLeftTime()
248
266
  }, [verifyPhoneState])
249
267
 
268
+ useEffect(() => {
269
+ if (recaptchaConfig?.siteKey) {
270
+ setRecaptchaVersion({ version: recaptchaConfig?.version, siteKey: recaptchaConfig?.siteKey })
271
+ }
272
+ }, [recaptchaConfig])
273
+
250
274
  return (
251
275
  <>
252
276
  {props.beforeElements?.map((BeforeElement, i) => (
@@ -391,7 +415,7 @@ const LoginFormUI = (props) => {
391
415
  )}
392
416
  {props.isRecaptchaEnable && enableReCaptcha && (
393
417
  <ReCaptchaWrapper>
394
- <ReCaptcha handleReCaptcha={handleReCaptcha} />
418
+ <ReCaptcha handleReCaptcha={handleReCaptcha} reCaptchaVersion={reCaptchaVersion} />
395
419
  </ReCaptchaWrapper>
396
420
  )}
397
421
  {(!willVerifyOtpState &&
@@ -497,6 +521,7 @@ const LoginFormUI = (props) => {
497
521
  export const LoginForm = (props) => {
498
522
  const loginControllerProps = {
499
523
  ...props,
524
+ isRecaptchaEnable: true,
500
525
  UIComponent: LoginFormUI
501
526
  }
502
527
  return <LoginFormController {...loginControllerProps} />