@licklist/design 0.69.3 → 0.69.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/events/edit-event-modal/utils/getDefaultProductSet.d.ts.map +1 -1
- package/dist/events/edit-event-modal/utils/getDefaultProductSet.js +3 -1
- package/dist/iframe/activity-card/ActivityCard.d.ts +5 -4
- package/dist/iframe/activity-card/ActivityCard.d.ts.map +1 -1
- package/dist/iframe/activity-card/ActivityCard.js +52 -40
- package/dist/product-set/card/ProductSetCard.d.ts.map +1 -1
- package/dist/product-set/card/ProductSetCard.js +10 -0
- package/dist/product-set/control/ProductSetControl.d.ts +4 -0
- package/dist/product-set/control/ProductSetControl.d.ts.map +1 -1
- package/dist/product-set/control/ProductSetControl.js +30 -3
- package/dist/product-set/control/ProductSetImageControl.d.ts +2 -0
- package/dist/product-set/control/ProductSetImageControl.d.ts.map +1 -0
- package/dist/product-set/control/ProductSetImageControl.js +279 -0
- package/dist/product-set/form/MobileFooter.d.ts.map +1 -1
- package/dist/styles/activity-card/{GridActivitiesCard.scss → ActivitiesCard.scss} +19 -5
- package/dist/styles/activity-card/ListActivitiesCard.scss +12 -42
- package/dist/styles/activity-card/_index.scss +1 -1
- package/package.json +2 -2
- package/src/events/edit-event-modal/utils/getDefaultProductSet.ts +2 -0
- package/src/iframe/activity-card/ActivityCard.tsx +35 -24
- package/src/product-set/card/ProductSetCard.tsx +15 -2
- package/src/product-set/control/ProductSetControl.tsx +52 -52
- package/src/product-set/control/ProductSetImageControl.tsx +97 -0
- package/src/product-set/form/MobileFooter.tsx +1 -3
- package/src/styles/activity-card/{GridActivitiesCard.scss → ActivitiesCard.scss} +19 -5
- package/src/styles/activity-card/ListActivitiesCard.scss +12 -42
- package/src/styles/activity-card/_index.scss +1 -1
- package/yarn.lock +57 -31
|
@@ -3,56 +3,26 @@
|
|
|
3
3
|
.list-activity-card {
|
|
4
4
|
display: flex;
|
|
5
5
|
justify-content: space-between;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
height: 6rem;
|
|
9
|
-
padding: 0.375rem;
|
|
10
|
-
border: 2px solid transparent;
|
|
11
|
-
border-radius: 0.5rem;
|
|
12
|
-
background-color: $snippet-product-set-background-color;
|
|
13
|
-
color: $snippet-product-set-font-color;
|
|
14
|
-
transition: $color-transition;
|
|
6
|
+
gap: 0.5rem;
|
|
7
|
+
width: 100%;
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
border: 2px solid #0e8be1;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
p {
|
|
21
|
-
margin-bottom: 0;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
.description {
|
|
9
|
+
&-info {
|
|
25
10
|
width: 70%;
|
|
26
11
|
font-size: 0.81rem;
|
|
27
12
|
display: flex;
|
|
28
13
|
flex-direction: column;
|
|
14
|
+
align-items: start;
|
|
29
15
|
}
|
|
30
16
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
font-size: 0.875rem;
|
|
34
|
-
line-height: 1.5rem;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.image-container {
|
|
38
|
-
display: flex;
|
|
39
|
-
justify-content: start;
|
|
17
|
+
img {
|
|
18
|
+
max-width: 120px;
|
|
40
19
|
height: 100%;
|
|
41
|
-
|
|
42
|
-
.
|
|
43
|
-
|
|
44
|
-
align-items: start;
|
|
45
|
-
width: 7rem;
|
|
46
|
-
height: 4rem;
|
|
47
|
-
margin-left: 3rem;
|
|
48
|
-
background-repeat: no-repeat;
|
|
49
|
-
background-size: cover;
|
|
50
|
-
background-position: center;
|
|
51
|
-
border-radius: 0.5rem;
|
|
52
|
-
}
|
|
20
|
+
object-fit: cover;
|
|
21
|
+
aspect-ratio: 1.2/1;
|
|
22
|
+
border-radius: 0.5rem;
|
|
53
23
|
}
|
|
54
|
-
}
|
|
55
24
|
|
|
56
|
-
|
|
57
|
-
|
|
25
|
+
&-hr {
|
|
26
|
+
margin-top: 0;
|
|
27
|
+
}
|
|
58
28
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
@import './
|
|
1
|
+
@import './ActivitiesCard.scss';
|
|
2
2
|
@import './ListActivitiesCard.scss';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@licklist/design",
|
|
3
|
-
"version": "0.69.
|
|
3
|
+
"version": "0.69.4",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+ssh://git@bitbucket.org/artelogicsoft/licklist_design.git"
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@dnd-kit/utilities": "2.0.0",
|
|
62
62
|
"@fortawesome/fontawesome-svg-core": "1.2.34",
|
|
63
63
|
"@fortawesome/free-solid-svg-icons": "5.15.2",
|
|
64
|
-
"@licklist/core": "0.30.
|
|
64
|
+
"@licklist/core": "0.30.3",
|
|
65
65
|
"@licklist/eslint-config": "0.5.6",
|
|
66
66
|
"@licklist/plugins": "0.33.1",
|
|
67
67
|
"@mantine/core": "6.0.22",
|
|
@@ -12,6 +12,8 @@ export const getDefaultValues = (
|
|
|
12
12
|
): ProductSetFormValues => ({
|
|
13
13
|
id: productSet?.id ?? 0,
|
|
14
14
|
name: productSet?.name ?? '',
|
|
15
|
+
description: productSet?.description ?? '',
|
|
16
|
+
image: productSet?.image,
|
|
15
17
|
type: productSet?.type ?? DEFAULT_PRODUCT_SET_TYPE,
|
|
16
18
|
termsAndConditions: productSet?.termsAndConditions ?? '',
|
|
17
19
|
operationalCost: productSet?.operationalCost ?? DEFAULT_OPERATIONAL_COST_TYPE,
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import { ReactNode } from 'react'
|
|
2
2
|
import clsx from 'clsx'
|
|
3
|
+
import { Image } from '@licklist/core/dist/DataMapper/Media/ImageDataMapper'
|
|
3
4
|
|
|
4
5
|
export const LAYOUT_GRID = 'grid'
|
|
5
6
|
export const LAYOUT_LIST = 'list'
|
|
6
7
|
|
|
7
|
-
type Layout = typeof LAYOUT_GRID | typeof LAYOUT_LIST
|
|
8
|
-
|
|
9
8
|
export type ActivityCardProps = {
|
|
10
9
|
title: ReactNode
|
|
11
10
|
duration: ReactNode
|
|
12
11
|
price: ReactNode
|
|
12
|
+
description?: ReactNode
|
|
13
13
|
onSelect: () => void
|
|
14
14
|
isSelected: boolean
|
|
15
|
-
layout?:
|
|
15
|
+
layout?: typeof LAYOUT_GRID | typeof LAYOUT_LIST
|
|
16
16
|
availableTimes?: string | null
|
|
17
|
+
image?: Image | null
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export const ActivityCard = ({
|
|
20
21
|
title,
|
|
21
22
|
duration,
|
|
22
23
|
price,
|
|
24
|
+
description,
|
|
23
25
|
availableTimes,
|
|
24
|
-
|
|
26
|
+
image,
|
|
25
27
|
onSelect,
|
|
26
28
|
isSelected,
|
|
27
29
|
layout = LAYOUT_GRID,
|
|
@@ -30,39 +32,48 @@ export const ActivityCard = ({
|
|
|
30
32
|
return (
|
|
31
33
|
<button
|
|
32
34
|
type='button'
|
|
33
|
-
className={clsx('activity-card', isSelected
|
|
35
|
+
className={clsx('activity-card', { active: isSelected })}
|
|
34
36
|
onClick={onSelect}
|
|
35
37
|
>
|
|
36
|
-
|
|
38
|
+
{image && (
|
|
39
|
+
<img src={image.url} alt={typeof title === 'string' ? title : ''} />
|
|
40
|
+
)}
|
|
41
|
+
|
|
42
|
+
<div>
|
|
37
43
|
<div className='activity-card-title'>{title}</div>
|
|
38
44
|
{duration && <div>{duration}</div>}
|
|
39
|
-
|
|
40
45
|
{price && <div>{price}</div>}
|
|
46
|
+
{description && (
|
|
47
|
+
<div className='mt-2 activity-card-description'>{description}</div>
|
|
48
|
+
)}
|
|
41
49
|
</div>
|
|
42
50
|
</button>
|
|
43
51
|
)
|
|
44
52
|
}
|
|
45
53
|
|
|
46
54
|
return (
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<div>
|
|
58
|
-
<p>{duration}</p>
|
|
59
|
-
</div>
|
|
60
|
-
)}
|
|
55
|
+
<button
|
|
56
|
+
type='button'
|
|
57
|
+
onClick={onSelect}
|
|
58
|
+
className={clsx('activity-card list-activity-card', {
|
|
59
|
+
active: isSelected,
|
|
60
|
+
})}
|
|
61
|
+
>
|
|
62
|
+
{image && (
|
|
63
|
+
<img src={image.url} alt={typeof title === 'string' ? title : ''} />
|
|
64
|
+
)}
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
</div>
|
|
66
|
+
<div className='activity-card-info'>
|
|
67
|
+
<div className='activity-card-title mb-2'>{title}</div>
|
|
68
|
+
{availableTimes && <div>{availableTimes}</div>}
|
|
69
|
+
{duration && <div>{duration}</div>}
|
|
70
|
+
{price && <div>{price}</div>}
|
|
71
|
+
{description && (
|
|
72
|
+
<div className='mt-2 activity-card-description'>{description}</div>
|
|
73
|
+
)}
|
|
64
74
|
</div>
|
|
75
|
+
|
|
65
76
|
<hr className='list-activity-card-hr' />
|
|
66
|
-
</
|
|
77
|
+
</button>
|
|
67
78
|
)
|
|
68
79
|
}
|
|
@@ -79,7 +79,13 @@ export function ProductSetCard({
|
|
|
79
79
|
>
|
|
80
80
|
{hasPermission && (
|
|
81
81
|
<>
|
|
82
|
-
<ListGroup.Item
|
|
82
|
+
<ListGroup.Item
|
|
83
|
+
action
|
|
84
|
+
as='div'
|
|
85
|
+
role='button'
|
|
86
|
+
tabIndex={0}
|
|
87
|
+
onClick={(e) => e.stopPropagation()}
|
|
88
|
+
>
|
|
83
89
|
{Boolean(onCopy) && (
|
|
84
90
|
<ConfirmModal>
|
|
85
91
|
{(confirm) => (
|
|
@@ -95,7 +101,14 @@ export function ProductSetCard({
|
|
|
95
101
|
</ConfirmModal>
|
|
96
102
|
)}
|
|
97
103
|
</ListGroup.Item>
|
|
98
|
-
<ListGroup.Item
|
|
104
|
+
<ListGroup.Item
|
|
105
|
+
action
|
|
106
|
+
className='text-danger'
|
|
107
|
+
as='div'
|
|
108
|
+
role='button'
|
|
109
|
+
tabIndex={0}
|
|
110
|
+
onClick={(e) => e.stopPropagation()}
|
|
111
|
+
>
|
|
99
112
|
{Boolean(onRemove) && (
|
|
100
113
|
<ConfirmModal>
|
|
101
114
|
{(confirm) => (
|
|
@@ -22,12 +22,11 @@ import HookFormService from '@licklist/plugins/dist/services/Form/HookFormServic
|
|
|
22
22
|
import { ruleForUrlWithProtocol } from '@licklist/plugins/dist/validation/Rules/urlRule'
|
|
23
23
|
import { WorkHour } from '@licklist/core/dist/DataMapper/Provider/WorkHourDataMapper'
|
|
24
24
|
import { checkIfZoneCategory } from '@licklist/plugins'
|
|
25
|
+
import { Image } from '@licklist/core/dist/DataMapper/Media/ImageDataMapper'
|
|
25
26
|
import { WarningMessage } from '../../static'
|
|
26
27
|
import { SelectItem } from '../../types/generic/SelectItem'
|
|
27
28
|
import {
|
|
28
29
|
DateAndRecurrenceInput,
|
|
29
|
-
// TODO: Show Date Component, when reccurent date bugs are fixed
|
|
30
|
-
// DateAndRecurrenceInput,
|
|
31
30
|
DateAndRecurrenceInputValues,
|
|
32
31
|
} from './DateAndRecurrenceInput'
|
|
33
32
|
import TutorialGifCard from './TutorialGifCard'
|
|
@@ -35,6 +34,7 @@ import { Step } from '../types'
|
|
|
35
34
|
import { StepsControl } from '../form/StepsControl'
|
|
36
35
|
import { Typeahead } from '../../typeahead'
|
|
37
36
|
import { DateInput } from './DateInput'
|
|
37
|
+
import { ProductSetImageControl } from './ProductSetImageControl'
|
|
38
38
|
|
|
39
39
|
const OPERATIONAL_COST_TITLES = {
|
|
40
40
|
[OPERATIONAL_COST_PROVIDER]: 'operationalCostProvider',
|
|
@@ -47,6 +47,8 @@ const RELY_ON_PEOPLE_TYPE_TITLES = {
|
|
|
47
47
|
[RELY_ON_PEOPLE_QUANTITY]: 'peopleQuantity',
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
const MAX_DESCRIPTION_LENGTH = 100
|
|
51
|
+
|
|
50
52
|
export interface TemplateItem {
|
|
51
53
|
id: string
|
|
52
54
|
value: EmailTemplate | SmsTemplate
|
|
@@ -55,6 +57,8 @@ export interface TemplateItem {
|
|
|
55
57
|
|
|
56
58
|
export interface ProductSetControlValues extends DateAndRecurrenceInputValues {
|
|
57
59
|
name: string
|
|
60
|
+
description?: string
|
|
61
|
+
image?: Image
|
|
58
62
|
type: ProductSetType
|
|
59
63
|
termsAndConditions: string
|
|
60
64
|
thankYouPageUrl: string
|
|
@@ -65,6 +69,7 @@ export interface ProductSetControlValues extends DateAndRecurrenceInputValues {
|
|
|
65
69
|
steps: Step[]
|
|
66
70
|
emailTemplates?: TemplateItem[]
|
|
67
71
|
smsTemplates?: TemplateItem[]
|
|
72
|
+
localImageBlobURL?: string
|
|
68
73
|
}
|
|
69
74
|
|
|
70
75
|
export interface ProductSetControlShared {
|
|
@@ -122,6 +127,7 @@ export function ProductSetControl({
|
|
|
122
127
|
const steps = watch('steps')
|
|
123
128
|
|
|
124
129
|
const nameId = useId()
|
|
130
|
+
const descriptionId = useId()
|
|
125
131
|
const termsAndConditionsId = useId()
|
|
126
132
|
const relyOnPeopleTypeId = useId()
|
|
127
133
|
|
|
@@ -174,6 +180,28 @@ export function ProductSetControl({
|
|
|
174
180
|
</Form.Control.Feedback>
|
|
175
181
|
</Form.Group>
|
|
176
182
|
|
|
183
|
+
<Form.Group controlId={descriptionId}>
|
|
184
|
+
<Form.Label>{t('Design:description')}</Form.Label>
|
|
185
|
+
<Form.Control
|
|
186
|
+
{...register('description', {
|
|
187
|
+
maxLength: {
|
|
188
|
+
value: MAX_DESCRIPTION_LENGTH,
|
|
189
|
+
message: t('Validation:fieldMaxLength', {
|
|
190
|
+
attribute: t('description'),
|
|
191
|
+
max: MAX_DESCRIPTION_LENGTH,
|
|
192
|
+
}),
|
|
193
|
+
},
|
|
194
|
+
})}
|
|
195
|
+
as='textarea'
|
|
196
|
+
isInvalid={Boolean(errors.description)}
|
|
197
|
+
/>
|
|
198
|
+
<Form.Control.Feedback type='invalid'>
|
|
199
|
+
{errors.description?.message}
|
|
200
|
+
</Form.Control.Feedback>
|
|
201
|
+
</Form.Group>
|
|
202
|
+
|
|
203
|
+
<ProductSetImageControl />
|
|
204
|
+
|
|
177
205
|
{showDateSelector ? (
|
|
178
206
|
<DateInput
|
|
179
207
|
workHours={isZoneAdded ? workHours : undefined}
|
|
@@ -207,27 +235,6 @@ export function ProductSetControl({
|
|
|
207
235
|
</Col>
|
|
208
236
|
<Col md={6} sm={12}>
|
|
209
237
|
<div className='second-column'>
|
|
210
|
-
{/* <Controller
|
|
211
|
-
control={control}
|
|
212
|
-
name="type"
|
|
213
|
-
render={({ field }) => (
|
|
214
|
-
<Form.Group className="d-flex flex-column flex-grow-1 align-items-start">
|
|
215
|
-
<Form.Label>{t("Design:checkoutType")}</Form.Label>
|
|
216
|
-
<Switch
|
|
217
|
-
name={field.name}
|
|
218
|
-
options={PRODUCT_SET_TYPES.map((type) => ({
|
|
219
|
-
key: type,
|
|
220
|
-
id: type,
|
|
221
|
-
value: t(type),
|
|
222
|
-
}))}
|
|
223
|
-
value={field.value}
|
|
224
|
-
onChange={field.onChange}
|
|
225
|
-
disabled={isLoading}
|
|
226
|
-
/>
|
|
227
|
-
</Form.Group>
|
|
228
|
-
)}
|
|
229
|
-
/> */}
|
|
230
|
-
|
|
231
238
|
<Form.Group>
|
|
232
239
|
<Form.Label className='mb-0'>
|
|
233
240
|
{t('Design:operationalCost')}
|
|
@@ -364,35 +371,28 @@ export function ProductSetControl({
|
|
|
364
371
|
<Controller
|
|
365
372
|
control={control}
|
|
366
373
|
name='fieldSetId'
|
|
367
|
-
render={({ field }) =>
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
</Form.Control>
|
|
390
|
-
<Form.Control.Feedback type='invalid'>
|
|
391
|
-
{HookFormService.getErrors('fieldSetId', errors)}
|
|
392
|
-
</Form.Control.Feedback>
|
|
393
|
-
</>
|
|
394
|
-
)
|
|
395
|
-
}}
|
|
374
|
+
render={({ field }) => (
|
|
375
|
+
<>
|
|
376
|
+
<Form.Label>{t('Design:customFields')}</Form.Label>
|
|
377
|
+
<Form.Control
|
|
378
|
+
onChange={field.onChange}
|
|
379
|
+
value={Number(field.value)}
|
|
380
|
+
as='select'
|
|
381
|
+
disabled={isOverrides}
|
|
382
|
+
isInvalid={HookFormService.isInvalid('fieldSetId', errors)}
|
|
383
|
+
>
|
|
384
|
+
<option value=''>{t('Design:choose')}</option>
|
|
385
|
+
{fieldSets?.map((fieldSet) => (
|
|
386
|
+
<option value={fieldSet.id} key={fieldSet.id}>
|
|
387
|
+
{fieldSet.name}
|
|
388
|
+
</option>
|
|
389
|
+
))}
|
|
390
|
+
</Form.Control>
|
|
391
|
+
<Form.Control.Feedback type='invalid'>
|
|
392
|
+
{HookFormService.getErrors('fieldSetId', errors)}
|
|
393
|
+
</Form.Control.Feedback>
|
|
394
|
+
</>
|
|
395
|
+
)}
|
|
396
396
|
/>
|
|
397
397
|
</Form.Group>
|
|
398
398
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { useFormContext } from 'react-hook-form'
|
|
2
|
+
import { HookFormService, useImages } from '@licklist/plugins'
|
|
3
|
+
import { IMAGE_TYPE_IMAGE } from '@licklist/core/dist/DataMapper/Media/ImageDataMapper'
|
|
4
|
+
import { useCallback, useEffect } from 'react'
|
|
5
|
+
import { Form } from 'react-bootstrap'
|
|
6
|
+
import { FileUpload } from 'src/file-upload'
|
|
7
|
+
import { useTranslation } from 'react-i18next'
|
|
8
|
+
import { isEqual } from 'lodash'
|
|
9
|
+
import { ProductSetControlValues } from '..'
|
|
10
|
+
|
|
11
|
+
export const ProductSetImageControl = () => {
|
|
12
|
+
const { t } = useTranslation('Design')
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
formState: { errors },
|
|
16
|
+
setValue,
|
|
17
|
+
watch,
|
|
18
|
+
clearErrors,
|
|
19
|
+
} = useFormContext<ProductSetControlValues>()
|
|
20
|
+
const currentProductSet: ProductSetControlValues = watch()
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
images,
|
|
24
|
+
handleImageRemove,
|
|
25
|
+
handleImageUploading,
|
|
26
|
+
isLoading: isImageUploading,
|
|
27
|
+
setImages,
|
|
28
|
+
} = useImages(null)
|
|
29
|
+
|
|
30
|
+
const onFilesChange = useCallback(
|
|
31
|
+
async (files: File[]) => {
|
|
32
|
+
const uploadedFiles = await handleImageUploading(files, IMAGE_TYPE_IMAGE)
|
|
33
|
+
|
|
34
|
+
if (!uploadedFiles) return
|
|
35
|
+
|
|
36
|
+
setValue('localImageBlobURL', URL.createObjectURL(files[0]) as never)
|
|
37
|
+
},
|
|
38
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
39
|
+
[handleImageUploading],
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
const onImageRemove = useCallback(
|
|
43
|
+
(id, path) => {
|
|
44
|
+
handleImageRemove(id, path)
|
|
45
|
+
setValue('localImageBlobURL', undefined as never)
|
|
46
|
+
},
|
|
47
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
48
|
+
[handleImageRemove],
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (!currentProductSet || !currentProductSet.image) return
|
|
53
|
+
|
|
54
|
+
setImages([
|
|
55
|
+
{
|
|
56
|
+
...currentProductSet.image,
|
|
57
|
+
url:
|
|
58
|
+
currentProductSet.image.url || currentProductSet?.localImageBlobURL,
|
|
59
|
+
},
|
|
60
|
+
])
|
|
61
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
62
|
+
}, [currentProductSet?.image])
|
|
63
|
+
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (isEqual(images[0], currentProductSet?.image)) return
|
|
66
|
+
|
|
67
|
+
setValue('image', (images[0] || null) as never)
|
|
68
|
+
|
|
69
|
+
if (images[0]) {
|
|
70
|
+
clearErrors('image')
|
|
71
|
+
}
|
|
72
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
|
+
}, [images])
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<Form.Group controlId='name'>
|
|
77
|
+
<Form.Control
|
|
78
|
+
isInvalid={HookFormService.isInvalid('image', errors)}
|
|
79
|
+
hidden
|
|
80
|
+
/>
|
|
81
|
+
<FileUpload
|
|
82
|
+
onFilesChange={onFilesChange}
|
|
83
|
+
allowedExtensions={['jpeg', 'jpg', 'png']}
|
|
84
|
+
subTitle='.jpeg .jpg .png'
|
|
85
|
+
enablePreview
|
|
86
|
+
onFileRemove={onImageRemove}
|
|
87
|
+
defaultFiles={images}
|
|
88
|
+
isLoading={isImageUploading}
|
|
89
|
+
withIcon
|
|
90
|
+
title={t('Design:addImage')}
|
|
91
|
+
/>
|
|
92
|
+
<Form.Control.Feedback type='invalid'>
|
|
93
|
+
{HookFormService.getErrors('image', errors)}
|
|
94
|
+
</Form.Control.Feedback>
|
|
95
|
+
</Form.Group>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
@@ -6,9 +6,7 @@ export function MobileFooter() {
|
|
|
6
6
|
|
|
7
7
|
return (
|
|
8
8
|
<div className='container product-set-mobile-footer'>
|
|
9
|
-
<div
|
|
10
|
-
className={`d-block d-sm-none bg-white border-top fixed-bottom py-4 px-5 d-flex justify-content-between flex-row-reverse`}
|
|
11
|
-
>
|
|
9
|
+
<div className='d-block d-sm-none bg-white border-top fixed-bottom py-4 px-5 d-flex justify-content-between flex-row-reverse'>
|
|
12
10
|
<Button type='submit'>{t('save')}</Button>
|
|
13
11
|
</div>
|
|
14
12
|
</div>
|
|
@@ -11,10 +11,7 @@
|
|
|
11
11
|
background-color: #fff;
|
|
12
12
|
font-size: 0.8rem;
|
|
13
13
|
background-color: $snippet-product-set-background-color;
|
|
14
|
-
|
|
15
|
-
div {
|
|
16
|
-
text-align: left;
|
|
17
|
-
}
|
|
14
|
+
text-align: left;
|
|
18
15
|
|
|
19
16
|
&.active {
|
|
20
17
|
border: 2px solid #0e8be1;
|
|
@@ -23,7 +20,24 @@
|
|
|
23
20
|
&-title {
|
|
24
21
|
font-weight: 600;
|
|
25
22
|
line-height: 1.25rem;
|
|
26
|
-
cursor: pointer;
|
|
27
23
|
font-size: 0.875rem;
|
|
28
24
|
}
|
|
25
|
+
|
|
26
|
+
img {
|
|
27
|
+
max-height: 100%;
|
|
28
|
+
max-width: 100%;
|
|
29
|
+
object-fit: cover;
|
|
30
|
+
aspect-ratio: 1.2/1;
|
|
31
|
+
margin-bottom: 0.8rem;
|
|
32
|
+
border-radius: 0.5rem;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&-description {
|
|
36
|
+
line-clamp: 5;
|
|
37
|
+
-webkit-line-clamp: 5;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
text-overflow: ellipsis;
|
|
40
|
+
display: -webkit-box;
|
|
41
|
+
-webkit-box-orient: vertical;
|
|
42
|
+
}
|
|
29
43
|
}
|
|
@@ -3,56 +3,26 @@
|
|
|
3
3
|
.list-activity-card {
|
|
4
4
|
display: flex;
|
|
5
5
|
justify-content: space-between;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
height: 6rem;
|
|
9
|
-
padding: 0.375rem;
|
|
10
|
-
border: 2px solid transparent;
|
|
11
|
-
border-radius: 0.5rem;
|
|
12
|
-
background-color: $snippet-product-set-background-color;
|
|
13
|
-
color: $snippet-product-set-font-color;
|
|
14
|
-
transition: $color-transition;
|
|
6
|
+
gap: 0.5rem;
|
|
7
|
+
width: 100%;
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
border: 2px solid #0e8be1;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
p {
|
|
21
|
-
margin-bottom: 0;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
.description {
|
|
9
|
+
&-info {
|
|
25
10
|
width: 70%;
|
|
26
11
|
font-size: 0.81rem;
|
|
27
12
|
display: flex;
|
|
28
13
|
flex-direction: column;
|
|
14
|
+
align-items: start;
|
|
29
15
|
}
|
|
30
16
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
font-size: 0.875rem;
|
|
34
|
-
line-height: 1.5rem;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.image-container {
|
|
38
|
-
display: flex;
|
|
39
|
-
justify-content: start;
|
|
17
|
+
img {
|
|
18
|
+
max-width: 120px;
|
|
40
19
|
height: 100%;
|
|
41
|
-
|
|
42
|
-
.
|
|
43
|
-
|
|
44
|
-
align-items: start;
|
|
45
|
-
width: 7rem;
|
|
46
|
-
height: 4rem;
|
|
47
|
-
margin-left: 3rem;
|
|
48
|
-
background-repeat: no-repeat;
|
|
49
|
-
background-size: cover;
|
|
50
|
-
background-position: center;
|
|
51
|
-
border-radius: 0.5rem;
|
|
52
|
-
}
|
|
20
|
+
object-fit: cover;
|
|
21
|
+
aspect-ratio: 1.2/1;
|
|
22
|
+
border-radius: 0.5rem;
|
|
53
23
|
}
|
|
54
|
-
}
|
|
55
24
|
|
|
56
|
-
|
|
57
|
-
|
|
25
|
+
&-hr {
|
|
26
|
+
margin-top: 0;
|
|
27
|
+
}
|
|
58
28
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
@import './
|
|
1
|
+
@import './ActivitiesCard.scss';
|
|
2
2
|
@import './ListActivitiesCard.scss';
|