ordering-ui-admin-external 1.19.3 → 1.20.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 (59) hide show
  1. package/_bundles/{ordering-ui-admin.16d845eec6ea6c18a073.js → ordering-ui-admin.9e032c80734b4e623988.js} +2 -2
  2. package/_modules/components/Delivery/DriversGroupPaymethods/index.js +2 -1
  3. package/_modules/components/Marketing/EnterprisePromotionPaymethods/index.js +2 -2
  4. package/_modules/components/MyProducts/AdvancedSettings/ImageBox.js +4 -1
  5. package/_modules/components/MyProducts/AdvancedSettings/SettingComponent.js +3 -1
  6. package/_modules/components/MyProducts/AdvancedSettings/index.js +43 -19
  7. package/_modules/components/MyProducts/CallCenterApp/index.js +1 -1
  8. package/_modules/components/MyProducts/OrderingWebsite/index.js +3 -1
  9. package/_modules/components/Orders/OrderBill/index.js +5 -5
  10. package/_modules/components/Orders/OrderDelete/index.js +25 -57
  11. package/_modules/components/Orders/OrderDetails/index.js +1 -1
  12. package/_modules/components/Orders/OrderDetailsHeader/index.js +2 -2
  13. package/_modules/components/Orders/OrderToPrint/index.js +4 -4
  14. package/_modules/components/Orders/OrdersManager/index.js +4 -5
  15. package/_modules/components/Orders/PaymethodTypeSelector/index.js +5 -2
  16. package/_modules/components/Shared/ConfirmAdmin/index.js +218 -26
  17. package/_modules/components/Shared/ConfirmAdmin/styles.js +47 -9
  18. package/_modules/components/Shared/ImageCrop/index.js +90 -10
  19. package/_modules/components/SidebarMenu/index.js +25 -22
  20. package/_modules/components/Stores/BusinessDelete/index.js +25 -57
  21. package/_modules/components/Stores/BusinessPaymentMethods/index.js +2 -1
  22. package/_modules/components/Stores/BusinessSummary/index.js +6 -4
  23. package/_modules/components/Stores/PaymentOption/index.js +2 -2
  24. package/_modules/components/Stores/PaymentOptionSquare/index.js +2 -2
  25. package/_modules/components/Stores/SeoOptions/index.js +5 -3
  26. package/_modules/components/Users/UsersDeleteButton/index.js +54 -66
  27. package/package.json +2 -2
  28. package/src/components/Delivery/DriversGroupPaymethods/index.js +1 -1
  29. package/src/components/Marketing/EnterprisePromotionPaymethods/index.js +1 -1
  30. package/src/components/MyProducts/AdvancedSettings/ImageBox.js +3 -1
  31. package/src/components/MyProducts/AdvancedSettings/SettingComponent.js +2 -1
  32. package/src/components/MyProducts/AdvancedSettings/index.js +24 -1
  33. package/src/components/MyProducts/CallCenterApp/index.js +1 -1
  34. package/src/components/MyProducts/OrderingWebsite/index.js +2 -0
  35. package/src/components/Orders/OrderBill/index.js +4 -4
  36. package/src/components/Orders/OrderDelete/index.js +17 -71
  37. package/src/components/Orders/OrderDetails/index.js +1 -1
  38. package/src/components/Orders/OrderDetailsHeader/index.js +1 -1
  39. package/src/components/Orders/OrderToPrint/index.js +2 -2
  40. package/src/components/Orders/OrdersManager/index.js +4 -5
  41. package/src/components/Orders/PaymethodTypeSelector/index.js +10 -8
  42. package/src/components/Shared/ConfirmAdmin/index.js +257 -35
  43. package/src/components/Shared/ConfirmAdmin/styles.js +95 -19
  44. package/src/components/Shared/ImageCrop/index.js +34 -5
  45. package/src/components/SidebarMenu/index.js +14 -14
  46. package/src/components/Stores/BusinessDelete/index.js +17 -71
  47. package/src/components/Stores/BusinessPaymentMethods/index.js +1 -1
  48. package/src/components/Stores/BusinessSummary/index.js +4 -3
  49. package/src/components/Stores/PaymentOption/index.js +1 -1
  50. package/src/components/Stores/PaymentOptionSquare/index.js +1 -1
  51. package/src/components/Stores/SeoOptions/index.js +9 -3
  52. package/src/components/Users/UsersDeleteButton/index.js +31 -85
  53. package/_modules/components/Orders/OrderDelete/styles.js +0 -19
  54. package/_modules/components/Stores/BusinessDelete/styles.js +0 -19
  55. package/_modules/components/Users/UsersDeleteButton/styles.js +0 -21
  56. package/src/components/Orders/OrderDelete/styles.js +0 -40
  57. package/src/components/Stores/BusinessDelete/styles.js +0 -40
  58. package/src/components/Users/UsersDeleteButton/styles.js +0 -56
  59. /package/_bundles/{ordering-ui-admin.16d845eec6ea6c18a073.js.LICENSE.txt → ordering-ui-admin.9e032c80734b4e623988.js.LICENSE.txt} +0 -0
@@ -1,55 +1,163 @@
1
1
  import React, { useEffect, useState } from 'react'
2
2
  import { useForm } from 'react-hook-form'
3
+ import parsePhoneNumber from 'libphonenumber-js'
4
+ import OtpInput from 'react-otp-input'
3
5
  import {
4
6
  useLanguage,
5
7
  CheckPassword as CheckPasswordController
6
8
  } from 'ordering-components-admin-external'
7
9
  import { Modal } from '../Modal'
8
- import { Button } from '../../../styles'
10
+ import { Alert } from '../Confirm'
11
+ import { InputPhoneNumber } from '../InputPhoneNumber'
12
+ import { Button, Input } from '../../../styles'
13
+ import { useCountdownTimer } from '../../../hooks/useCountdownTimer'
14
+ import { formatSeconds } from '../../../utils'
9
15
 
10
16
  import {
11
17
  WrapperCheckPassword,
12
- ErrorText
18
+ FormController,
19
+ Tabs,
20
+ Tab,
21
+ CountdownTimer,
22
+ OtpWrapper,
23
+ ResendCode
13
24
  } from './styles'
14
25
 
15
26
  const ConfirmAdminUI = (props) => {
16
27
  const {
17
28
  checkPasswordStatus,
18
- handleChangePassword,
19
29
  getCheckPassword,
20
-
21
30
  open,
22
31
  onClose,
23
- onConfirm
32
+ onConfirm,
33
+
34
+ confirmTab,
35
+ otpType,
36
+ setOtpType,
37
+ handleChangeTab,
38
+ setOtpState,
39
+ otpState,
40
+ generateOtpCode,
41
+
42
+ checkCodeState,
43
+ credentials,
44
+ handleChangeInput,
45
+ handleChangeCredentials
24
46
  } = props
25
47
 
26
48
  const [, t] = useLanguage()
27
- const { handleSubmit } = useForm()
49
+ const { handleSubmit, register, errors } = useForm()
50
+ const [alertState, setAlertState] = useState({ open: false, content: [] })
51
+ const [willVerifyOtpState, setWillVerifyOtpState] = useState(false)
52
+
53
+ const numOtpInputs = confirmTab === 'otp' ? 6 : 4
54
+ const otpPlaceholder = [...Array(numOtpInputs)].fill(0).join('')
55
+ const [otpLeftTime, , resetOtpLeftTime] = useCountdownTimer(600, !checkCodeState?.loading && willVerifyOtpState)
56
+ const isOtpEmail = confirmTab === 'otp' && otpType === 'email'
57
+ const isOptCellphone = confirmTab === 'otp' && otpType === 'cellphone'
58
+
59
+ const handleChangeOtpType = (type) => {
60
+ setWillVerifyOtpState(false)
61
+ handleChangeTab('otp')
62
+ setOtpType(type)
63
+ }
64
+
65
+ const closeAlert = () => {
66
+ setAlertState({
67
+ open: false,
68
+ content: []
69
+ })
70
+ setOtpState('')
71
+ }
28
72
 
29
- const [password, setPassword] = useState('')
73
+ const handleChangePhoneNumber = (number, isValid) => {
74
+ let phoneNumberParser = null
75
+ let values = { country_phone_code: '', cellphone: '' }
30
76
 
31
- const handlePassword = (e) => {
32
- setPassword(e.target.value)
77
+ if (isValid) {
78
+ phoneNumberParser = parsePhoneNumber(number)
79
+ }
80
+ if (phoneNumberParser) {
81
+ values = {
82
+ country_phone_code: phoneNumberParser.countryCallingCode,
83
+ cellphone: phoneNumberParser.nationalNumber
84
+ }
85
+ }
86
+ handleChangeCredentials(values)
87
+ }
88
+
89
+ const handleSendOtp = () => {
90
+ if (willVerifyOtpState) {
91
+ setOtpState('')
92
+ resetOtpLeftTime()
93
+ if (confirmTab === 'otp') {
94
+ generateOtpCode()
95
+ setWillVerifyOtpState(true)
96
+ }
97
+ }
33
98
  }
34
99
 
35
100
  const onSubmit = () => {
36
- getCheckPassword()
101
+ if (confirmTab === 'otp' && otpType === 'cellphone' && !credentials?.country_phone_code && !credentials?.cellphone) {
102
+ setAlertState({
103
+ open: true,
104
+ content: [t('PHONE_NUMBER_IS_NOT_VALID', 'Phone number is not valid')]
105
+ })
106
+ return
107
+ }
108
+ if (confirmTab === 'password') {
109
+ getCheckPassword()
110
+ }
111
+ if (confirmTab === 'otp') {
112
+ generateOtpCode()
113
+ setWillVerifyOtpState(true)
114
+ }
37
115
  }
38
116
 
39
117
  useEffect(() => {
40
- handleChangePassword(password)
41
- }, [password])
118
+ if (otpState?.length === numOtpInputs) {
119
+ if (confirmTab === 'otp') {
120
+ onConfirm(otpState)
121
+ }
122
+ }
123
+ }, [otpState])
42
124
 
43
125
  useEffect(() => {
44
- if (checkPasswordStatus.loading || checkPasswordStatus.error !== null) return
126
+ if (checkPasswordStatus.error) {
127
+ setAlertState({
128
+ open: true,
129
+ content: checkPasswordStatus.error
130
+ })
131
+ return
132
+ }
45
133
  if (checkPasswordStatus.result === 'OK') {
46
134
  onConfirm()
47
135
  }
48
- }, [checkPasswordStatus])
136
+ }, [checkPasswordStatus.error, checkPasswordStatus.result])
137
+
138
+ useEffect(() => {
139
+ if (checkCodeState?.result?.error) {
140
+ setAlertState({
141
+ open: true,
142
+ content: checkCodeState?.result?.error || [t('ERROR', 'Error')]
143
+ })
144
+ } else if (checkCodeState?.result?.result) {
145
+ setAlertState({
146
+ open: true,
147
+ content: t('CODE_SENT', 'The code has been sent')
148
+ })
149
+ resetOtpLeftTime()
150
+ }
151
+ }, [checkCodeState])
49
152
 
50
153
  useEffect(() => {
51
- setPassword('')
52
- }, [open])
154
+ if (Object.keys(errors).length > 0) {
155
+ setAlertState({
156
+ open: true,
157
+ content: Object.values(errors).map((error) => error.message)
158
+ })
159
+ }
160
+ }, [errors])
53
161
 
54
162
  return (
55
163
  <Modal
@@ -61,28 +169,142 @@ const ConfirmAdminUI = (props) => {
61
169
  onSubmit={handleSubmit(onSubmit)}
62
170
  >
63
171
  <h3>{t('CONFIRM_PASSWORD', 'Confirm password')}</h3>
64
- <p>{t('TYPE_YOUR_PASSWORD_TO_CONFIRM_DELETE', 'Type your password to confirm delete.')}</p>
65
- <input
66
- autoComplete='off'
67
- type='password'
68
- value={password}
69
- placeholder={t('PASSWORD', 'password')}
70
- onChange={(e) => handlePassword(e)}
71
- />
72
- {checkPasswordStatus?.error && (
73
- <ErrorText
74
- className='text-danger'
172
+ <Tabs>
173
+ <Tab
174
+ active={confirmTab === 'password'}
175
+ onClick={() => {
176
+ setWillVerifyOtpState(false)
177
+ handleChangeTab('password')
178
+ }}
179
+ >
180
+ {t('BY_PASSWORD', 'by Password')}
181
+ </Tab>
182
+ <Tab
183
+ active={isOtpEmail}
184
+ onClick={() => handleChangeOtpType('email')}
185
+ >
186
+ {t('BY_OTP_EMAIL', 'by Otp Email')}
187
+ </Tab>
188
+ <Tab
189
+ active={isOptCellphone}
190
+ onClick={() => handleChangeOtpType('cellphone')}
75
191
  >
76
- {checkPasswordStatus.error}
77
- </ErrorText>
192
+ {t('BY_OTP_PHONE', 'by Otp Phone')}
193
+ </Tab>
194
+ </Tabs>
195
+ {confirmTab === 'password' && (
196
+ <FormController>
197
+ <Input
198
+ type='password'
199
+ name='password'
200
+ placeholder={t('TYPE_YOUR_PASSWORD_TO_CONFIRM_DELETE', 'Type your password to confirm delete.')}
201
+ ref={register({
202
+ required: t(
203
+ 'VALIDATION_ERROR_REQUIRED',
204
+ 'Password is required'
205
+ ).replace('_attribute_', t('PASSWORD', 'Password'))
206
+ })}
207
+ onChange={(e) => handleChangeInput(e)}
208
+ autoComplete='off'
209
+ autoCapitalize='off'
210
+ />
211
+ </FormController>
78
212
  )}
79
- <Button
80
- color='primary'
81
- borderRadius='7.6px'
82
- >
83
- {checkPasswordStatus.loading ? t('LOADING', 'Loading') : t('CONFIRM', 'Confirm')}
84
- </Button>
213
+ {!willVerifyOtpState && confirmTab === 'otp' && otpType === 'email' && (
214
+ <FormController>
215
+ <Input
216
+ type='email'
217
+ name='email'
218
+ placeholder={t('EMAIL', 'Email')}
219
+ ref={register({
220
+ required: t(
221
+ 'VALIDATION_ERROR_REQUIRED',
222
+ 'Email is required'
223
+ ).replace('_attribute_', t('EMAIL', 'Email')),
224
+ pattern: {
225
+ value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
226
+ message: t(
227
+ 'VALIDATION_ERROR_EMAIL',
228
+ 'Invalid email address'
229
+ ).replace('_attribute_', t('EMAIL', 'Email'))
230
+ }
231
+ })}
232
+ onChange={(e) => handleChangeInput(e)}
233
+ autoComplete='off'
234
+ autoCapitalize='off'
235
+ />
236
+ </FormController>
237
+ )}
238
+ {!willVerifyOtpState && confirmTab === 'otp' && otpType === 'cellphone' && (
239
+ <FormController>
240
+ <InputPhoneNumber
241
+ setValue={handleChangePhoneNumber}
242
+ />
243
+ </FormController>
244
+ )}
245
+ {(!willVerifyOtpState &&
246
+ <Button
247
+ borderRadius='8px'
248
+ color='primary'
249
+ type='submit'
250
+ disabled={checkPasswordStatus.loading}
251
+ >
252
+ {checkPasswordStatus.loading
253
+ ? t('LOADING', 'Loading')
254
+ : confirmTab === 'otp'
255
+ ? t('GET_VERIFY_CODE', 'Get verify code')
256
+ : t('CONFIRM', 'Confirm')}
257
+ </Button>
258
+ )}
259
+ {willVerifyOtpState && !checkCodeState?.loading && (
260
+ <>
261
+ <CountdownTimer>
262
+ <span>{formatSeconds(otpLeftTime)}</span>
263
+ </CountdownTimer>
264
+
265
+ <OtpWrapper>
266
+ <OtpInput
267
+ value={otpState}
268
+ onChange={otp => setOtpState(otp)}
269
+ numInputs={numOtpInputs}
270
+ containerStyle='otp-container'
271
+ inputStyle='otp-input'
272
+ placeholder={otpPlaceholder}
273
+ isInputNum
274
+ shouldAutoFocus
275
+ isDisabled={otpLeftTime === 0}
276
+ />
277
+ </OtpWrapper>
278
+ <ResendCode
279
+ disabled={otpLeftTime > 520}
280
+ onClick={handleSendOtp}
281
+ >
282
+ {t('RESEND_AGAIN', 'Resend again')}?
283
+ </ResendCode>
284
+ <Button
285
+ borderRadius='8px'
286
+ type='button'
287
+ color='primary'
288
+ onClick={() => {
289
+ setWillVerifyOtpState(false)
290
+ }}
291
+ >
292
+ {t('CANCEL', 'Cancel')}
293
+ </Button>
294
+ </>
295
+ )}
296
+
85
297
  </WrapperCheckPassword>
298
+
299
+ <Alert
300
+ title={t('WEB_APPNAME', 'Ordering')}
301
+ content={alertState.content}
302
+ acceptText={t('ACCEPT')}
303
+ open={alertState.open}
304
+ onClose={() => closeAlert()}
305
+ onAccept={() => closeAlert()}
306
+ closeOnBackdrop={false}
307
+ />
86
308
  </Modal>
87
309
  )
88
310
  }
@@ -1,6 +1,9 @@
1
- import styled from 'styled-components'
1
+ import styled, { css } from 'styled-components'
2
+ import { darken } from 'polished'
2
3
 
3
4
  export const WrapperCheckPassword = styled.form`
5
+ display: flex;
6
+ flex-direction: column;
4
7
  padding: 10px;
5
8
  color: ${props => props.theme.colors?.headingColor};
6
9
 
@@ -10,31 +13,104 @@ export const WrapperCheckPassword = styled.form`
10
13
  font-weight: 600;
11
14
  }
12
15
 
13
- p {
14
- margin-top: 25px;
16
+ button {
17
+ margin-top: 40px;
18
+ width: 100%;
19
+ padding-top: 5px;
20
+ padding-bottom: 5px;
21
+ }
22
+ `
23
+ export const FormController = styled.div`
24
+ display: flex;
25
+ flex-direction: column;
26
+
27
+ label {
15
28
  margin-bottom: 10px;
29
+ font-size: 14px;
16
30
  }
17
31
 
18
- input {
19
- outline: none;
32
+ .PhoneInputInput {
33
+ height: 43px;
34
+ border-radius: 8px !important;
35
+ }
36
+ .PhoneInputCountry {
37
+ height: 43px;
38
+ padding: 8px;
20
39
  border-radius: 8px;
21
- font-size: 16px;
22
- border: 1px solid rgba(20, 20, 20, 0.2);
23
- width: 100%;
24
- padding: 10px 15px;
25
- &:focus {
26
- border: 1px solid ${props => props.theme.colors.primary};
40
+ background-color: ${props => props.theme.colors.backgroundPage};
41
+ * {
42
+ padding: 0px;
27
43
  }
28
44
  }
45
+ `
46
+ export const Tabs = styled.div`
47
+ display: flex;
48
+ border-bottom: 1px solid ${props => props.theme.colors.borderColor};
49
+ margin: 30px 0 15px 0;
50
+ `
29
51
 
30
- button {
31
- margin-top: 40px;
32
- width: 150px;
33
- padding-top: 5px;
34
- padding-bottom: 5px;
52
+ export const Tab = styled.div`
53
+ padding: 10px 0;
54
+ font-size: 14px;
55
+ cursor: pointer;
56
+ ${props => props.theme?.rtl ? css`
57
+ margin-left: 15px;
58
+ ` : css`
59
+ margin-right: 15px;
60
+ `}
61
+ ${({ active }) => active && css`
62
+ color: ${props => props.theme.colors.headingColor};
63
+ border-bottom: 1px solid;
64
+ `}
65
+
66
+ ${({ active }) => !active && css`
67
+ color: ${props => props.theme.colors.lightGray};
68
+ `}
69
+ `
70
+ export const CountdownTimer = styled.div`
71
+ margin: 15px;
72
+ display: flex;
73
+ justify-content: center;
74
+
75
+ span {
76
+ font-size: 30px;
77
+ font-weight: 700;
78
+ }
79
+ `
80
+ export const OtpWrapper = styled.div`
81
+ width: 100%;
82
+ .otp-container{
83
+ display: flex;
84
+ justify-content: space-evenly;
85
+ margin: 20px;
86
+
87
+ .otp-input{
88
+ width: 50px !important;
89
+ height: 45px;
90
+ border-radius: 8px;
91
+ background-color: ${props => props.theme.colors.backgroundPage};
92
+ outline: none;
93
+ border: 1px solid ${props => props.theme.colors.borderColor};
94
+ font-size: 20px;
95
+ font-weight: bold;
96
+
97
+ &:focus{
98
+ border-color: ${() => darken(0.07, '#CCC')} !important;
99
+ }
100
+
101
+ &::placeholder,
102
+ &::-webkit-input-placeholder {
103
+ color: #DBDCDB;
104
+ }
105
+ &:-ms-input-placeholder {
106
+ color: #DBDCDB;
107
+ }
108
+ }
35
109
  }
36
110
  `
37
- export const ErrorText = styled.div`
38
- text-align: center;
39
- margin: 10px 0;
111
+ export const ResendCode = styled.span`
112
+ color: ${props => props.disabled ? props.theme.colors.disabled : props.theme.colors.primary};
113
+ font-size: 20px;
114
+ align-self: center;
115
+ cursor: ${props => props.disabled ? 'not-allowed' : 'pointer'};
40
116
  `
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useState, useRef } from 'react'
2
2
  import Cropper from 'cropperjs'
3
- import { useLanguage } from 'ordering-components-admin-external'
3
+ import { useApi, useLanguage, useSession, useUtils } from 'ordering-components-admin-external'
4
4
  import { Button, IconButton } from '../../../styles'
5
5
  import { ArrowClockwise } from 'react-bootstrap-icons'
6
6
  import { useTheme } from 'styled-components'
@@ -19,14 +19,20 @@ export const ImageCrop = (props) => {
19
19
  photo,
20
20
  handleChangePhoto,
21
21
  onClose,
22
- aspectRatio
22
+ aspectRatio,
23
+ showAspectRatioBox,
24
+ useCloudinaryUrl,
25
+ themeId
23
26
  } = props
24
27
 
25
28
  const [, t] = useLanguage()
26
29
  const theme = useTheme()
27
-
30
+ const [ordering] = useApi()
31
+ const [{ token }] = useSession()
32
+ const [{ optimizeImage }] = useUtils()
28
33
  const [cropper, setCropper] = useState()
29
34
  const [zoomValue, setZoomValue] = useState(50)
35
+ const [loading, setLoading] = useState(false)
30
36
  const cropperRef = useRef(null)
31
37
 
32
38
  const handleChangeZoom = (evt) => {
@@ -35,9 +41,31 @@ export const ImageCrop = (props) => {
35
41
  setZoomValue(value)
36
42
  }
37
43
 
38
- const getCropData = () => {
44
+ const getCropData = async () => {
39
45
  if (typeof cropper !== 'undefined') {
40
- handleChangePhoto(cropper.getCroppedCanvas({ imageSmoothingQuality: 'high' }).toDataURL())
46
+ let photo
47
+ if (useCloudinaryUrl && themeId) {
48
+ console.log('entra')
49
+ setLoading(true)
50
+ const response = await fetch(`${ordering.root}/themes/${themeId}/gallery`, {
51
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
52
+ method: 'POST',
53
+ body: JSON.stringify({
54
+ type: 'image',
55
+ file: cropper.getCroppedCanvas({ imageSmoothingQuality: 'high' }).toDataURL()
56
+ })
57
+ })
58
+ const { result, error } = await response.json()
59
+ setLoading(false)
60
+ if (!error) {
61
+ photo = optimizeImage(result.image, 'f_auto,q_auto,w_2000,c_limit')
62
+ } else {
63
+ return
64
+ }
65
+ } else {
66
+ photo = cropper.getCroppedCanvas({ imageSmoothingQuality: 'high' }).toDataURL()
67
+ }
68
+ handleChangePhoto(photo)
41
69
  onClose && onClose()
42
70
  }
43
71
  }
@@ -99,6 +127,7 @@ export const ImageCrop = (props) => {
99
127
  borderRadius='7.6px'
100
128
  color='primary'
101
129
  onClick={getCropData}
130
+ disabled={loading}
102
131
  >
103
132
  {t('CROP', 'Crop')}
104
133
  </Button>
@@ -86,13 +86,13 @@ const SidebarMenuUI = (props) => {
86
86
  title: t('APPOINTMENTS', 'Appointments'),
87
87
  pageName: 'appointments',
88
88
  url: '/appointments'
89
+ },
90
+ {
91
+ id: 5,
92
+ title: t('GIFT_CARD_MANAGER', 'Gift card manager'),
93
+ pageName: 'giftCards',
94
+ url: '/gift-cards'
89
95
  }
90
- // {
91
- // id: 5,
92
- // title: t('GIFT_CARD_MANAGER', 'Gift card manager'),
93
- // pageName: 'giftCards',
94
- // url: '/gift-cards'
95
- // }
96
96
  ]
97
97
 
98
98
  const loyaltySubMenus = [
@@ -350,12 +350,12 @@ const SidebarMenuUI = (props) => {
350
350
  pageName: 'enterprise_promotions',
351
351
  url: '/marketing/promotions-enterprise'
352
352
  },
353
- // {
354
- // id: 2,
355
- // title: t('CAMPAIGN', 'Campaign'),
356
- // pageName: 'campaign',
357
- // url: '/marketing/campaign'
358
- // },
353
+ {
354
+ id: 2,
355
+ title: t('CAMPAIGN', 'Campaign'),
356
+ pageName: 'campaign',
357
+ url: '/marketing/campaign'
358
+ },
359
359
  {
360
360
  id: 3,
361
361
  title: t('AD_BANNERS', 'Ad banners'),
@@ -843,7 +843,7 @@ const SidebarMenuUI = (props) => {
843
843
  </MenuContainer>
844
844
  </Accordion>
845
845
  )}
846
- {/* {sessionState?.user?.level === 0 && (
846
+ {sessionState?.user?.level === 0 && (
847
847
  <Button
848
848
  className='d-flex align-items-center'
849
849
  variant={location.pathname === '/ordering-products' && 'primary'}
@@ -852,7 +852,7 @@ const SidebarMenuUI = (props) => {
852
852
  <WindowDock />
853
853
  <span>{t('ORDERING_PRODUCTS', 'Ordering products')}</span>
854
854
  </Button>
855
- )} */}
855
+ )}
856
856
  {sessionState?.user?.level === 0 && (
857
857
  <Button
858
858
  className='d-flex align-items-center'