@servicetitan/mpa-components 1.11.0 → 2.0.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.
- package/CHANGELOG.md +8 -0
- package/lib/components/brands/brand-card/actions-button-section.d.ts +6 -0
- package/lib/components/brands/brand-card/actions-button-section.d.ts.map +1 -0
- package/lib/components/brands/brand-card/actions-button-section.js +26 -0
- package/lib/components/brands/brand-card/actions-button-section.js.map +1 -0
- package/lib/components/brands/brand-card/brand-card.d.ts +1 -1
- package/lib/components/brands/brand-card/brand-card.d.ts.map +1 -1
- package/lib/components/brands/brand-card/brand-card.js +10 -55
- package/lib/components/brands/brand-card/brand-card.js.map +1 -1
- package/lib/components/brands/brand-card/brand-logo.d.ts +6 -0
- package/lib/components/brands/brand-card/brand-logo.d.ts.map +1 -0
- package/lib/components/brands/brand-card/brand-logo.js +8 -0
- package/lib/components/brands/brand-card/brand-logo.js.map +1 -0
- package/lib/components/brands/brand-card/cart-tags.d.ts +6 -0
- package/lib/components/brands/brand-card/cart-tags.d.ts.map +1 -0
- package/lib/components/brands/brand-card/cart-tags.js +10 -0
- package/lib/components/brands/brand-card/cart-tags.js.map +1 -0
- package/lib/components/brands/brand-card/name-and-mail-section.d.ts +7 -0
- package/lib/components/brands/brand-card/name-and-mail-section.d.ts.map +1 -0
- package/lib/components/brands/brand-card/name-and-mail-section.js +7 -0
- package/lib/components/brands/brand-card/name-and-mail-section.js.map +1 -0
- package/lib/components/brands/brand-card/single-action-button.d.ts +6 -0
- package/lib/components/brands/brand-card/single-action-button.d.ts.map +1 -0
- package/lib/components/brands/brand-card/single-action-button.js +34 -0
- package/lib/components/brands/brand-card/single-action-button.js.map +1 -0
- package/lib/components/brands/cards-grid/cards-grid.d.ts +2 -1
- package/lib/components/brands/cards-grid/cards-grid.d.ts.map +1 -1
- package/lib/components/brands/cards-grid/cards-grid.js +2 -3
- package/lib/components/brands/cards-grid/cards-grid.js.map +1 -1
- package/lib/components/brands/styles.module.less +7 -21
- package/lib/enums/brands.d.ts +4 -19
- package/lib/enums/brands.d.ts.map +1 -1
- package/lib/enums/brands.js +6 -1
- package/lib/enums/brands.js.map +1 -1
- package/lib/index.d.ts +3 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -1
- package/lib/index.js.map +1 -1
- package/lib/utils/interfaces.d.ts +22 -0
- package/lib/utils/interfaces.d.ts.map +1 -0
- package/lib/utils/interfaces.js +2 -0
- package/lib/utils/interfaces.js.map +1 -0
- package/lib/utils/mappers.d.ts +4 -0
- package/lib/utils/mappers.d.ts.map +1 -0
- package/lib/utils/mappers.js +13 -0
- package/lib/utils/mappers.js.map +1 -0
- package/package.json +2 -2
- package/src/components/brands/brand-card/actions-button-section.tsx +62 -0
- package/src/components/brands/brand-card/brand-card.tsx +30 -220
- package/src/components/brands/brand-card/brand-logo.tsx +21 -0
- package/src/components/brands/brand-card/cart-tags.tsx +20 -0
- package/src/components/brands/brand-card/name-and-mail-section.tsx +28 -0
- package/src/components/brands/brand-card/single-action-button.tsx +84 -0
- package/src/components/brands/cards-grid/cards-grid.tsx +10 -6
- package/src/components/brands/styles.module.less +7 -21
- package/src/components/brands/styles.module.less.d.ts +2 -3
- package/src/enums/brands.ts +4 -22
- package/src/index.ts +3 -1
- package/src/utils/interfaces.ts +23 -0
- package/src/utils/mappers.ts +14 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { FC, useState } from 'react';
|
|
2
|
+
import { useHistory } from 'react-router-dom';
|
|
3
|
+
|
|
4
|
+
import { ActionMenu, BodyText, Button, Icon } from '@servicetitan/design-system';
|
|
5
|
+
|
|
6
|
+
import { SingleActionButtonSection } from './single-action-button';
|
|
7
|
+
import { BrandAction } from '../../../utils/interfaces';
|
|
8
|
+
|
|
9
|
+
export const ActionsButtonSection: FC<{
|
|
10
|
+
actions: BrandAction | BrandAction[];
|
|
11
|
+
}> = ({ actions }) => {
|
|
12
|
+
const [isOpen, setOpen] = useState(false);
|
|
13
|
+
const history = useHistory();
|
|
14
|
+
|
|
15
|
+
if (!Array.isArray(actions)) {
|
|
16
|
+
return <SingleActionButtonSection action={actions} />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const trigger = (
|
|
20
|
+
<Button
|
|
21
|
+
outline
|
|
22
|
+
size="small"
|
|
23
|
+
onClick={() => setOpen(true)}
|
|
24
|
+
className="qa-brand-card-actions-trigger"
|
|
25
|
+
>
|
|
26
|
+
Actions <Icon name="keyboard_arrow_down" size={16} />
|
|
27
|
+
</Button>
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<ActionMenu
|
|
32
|
+
trigger={trigger}
|
|
33
|
+
open={isOpen}
|
|
34
|
+
onClickOutside={() => setOpen(false)}
|
|
35
|
+
direction="bl"
|
|
36
|
+
className="qa-brand-card-action-menu"
|
|
37
|
+
>
|
|
38
|
+
{actions.map(action => {
|
|
39
|
+
const actionClick = () => {
|
|
40
|
+
setOpen(false);
|
|
41
|
+
if (action.action) {
|
|
42
|
+
action.action();
|
|
43
|
+
}
|
|
44
|
+
if (action.href) {
|
|
45
|
+
history.push(action.href);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<ActionMenu.Item
|
|
51
|
+
disabled={action.disabled}
|
|
52
|
+
key={action.name}
|
|
53
|
+
onClick={actionClick}
|
|
54
|
+
className="qa-brand-card-action-menu-item"
|
|
55
|
+
>
|
|
56
|
+
<BodyText subdued={action.disabled}>{action.name}</BodyText>
|
|
57
|
+
</ActionMenu.Item>
|
|
58
|
+
);
|
|
59
|
+
})}
|
|
60
|
+
</ActionMenu>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
import { FC
|
|
2
|
-
import
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
ActionMenu,
|
|
6
|
-
BodyText,
|
|
7
|
-
Button,
|
|
8
|
-
Card,
|
|
9
|
-
Headline,
|
|
10
|
-
Icon,
|
|
11
|
-
Stack,
|
|
12
|
-
Tag,
|
|
13
|
-
Tooltip,
|
|
14
|
-
} from '@servicetitan/design-system';
|
|
15
|
-
import { DomainValidationStatus } from '@servicetitan/marketing-services-api/dist/settings/brand.mrk.api';
|
|
16
|
-
import { tokens } from '@servicetitan/tokens/core';
|
|
4
|
+
import { Flex, Card } from '@servicetitan/anvil2';
|
|
17
5
|
|
|
18
|
-
import {
|
|
6
|
+
import { NameAndMailSection } from './name-and-mail-section';
|
|
7
|
+
import { BrandCardProps } from '../../../utils/interfaces';
|
|
8
|
+
import { ActionsButtonSection } from './actions-button-section';
|
|
9
|
+
import { CardTags } from './cart-tags';
|
|
10
|
+
import { BrandLogo } from './brand-logo';
|
|
19
11
|
|
|
20
12
|
import * as Styles from '../styles.module.less';
|
|
21
13
|
|
|
@@ -23,223 +15,41 @@ const BRAND_NAME_PLACEHOLDER = 'Assign Brand Name';
|
|
|
23
15
|
|
|
24
16
|
export const BrandCard: FC<BrandCardProps> = ({
|
|
25
17
|
actions,
|
|
26
|
-
domainValidationStatus,
|
|
27
18
|
email,
|
|
28
19
|
isDefault,
|
|
29
20
|
isShared,
|
|
30
21
|
logo,
|
|
31
22
|
name,
|
|
23
|
+
hasError,
|
|
32
24
|
}) => {
|
|
33
|
-
const [isOpen, setOpen] = useState(false);
|
|
34
|
-
|
|
35
|
-
const actionsButtonSection = useMemo(() => {
|
|
36
|
-
if (!Array.isArray(actions)) {
|
|
37
|
-
return (
|
|
38
|
-
<SingleActionButtonSection
|
|
39
|
-
action={actions}
|
|
40
|
-
domainValidationStatus={domainValidationStatus}
|
|
41
|
-
/>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const trigger = (
|
|
46
|
-
<Button outline size="small" onClick={() => setOpen(true)}>
|
|
47
|
-
Actions <Icon name="keyboard_arrow_down" size={16} />
|
|
48
|
-
</Button>
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
return (
|
|
52
|
-
<ActionMenu
|
|
53
|
-
trigger={trigger}
|
|
54
|
-
open={isOpen}
|
|
55
|
-
onClickOutside={() => setOpen(false)}
|
|
56
|
-
direction="bl"
|
|
57
|
-
>
|
|
58
|
-
{actions.map(action => {
|
|
59
|
-
if (action.href) {
|
|
60
|
-
return (
|
|
61
|
-
<Link to={action.href} key={action.name}>
|
|
62
|
-
<ActionMenu.Item key={action.name} disabled={action.disabled}>
|
|
63
|
-
<BodyText subdued={action.disabled}>{action.name}</BodyText>
|
|
64
|
-
</ActionMenu.Item>
|
|
65
|
-
</Link>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const actionClick = () => {
|
|
70
|
-
setOpen(false);
|
|
71
|
-
if (action.action) {
|
|
72
|
-
action.action();
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
return (
|
|
77
|
-
<ActionMenu.Item
|
|
78
|
-
disabled={action.disabled}
|
|
79
|
-
key={action.name}
|
|
80
|
-
onClick={actionClick}
|
|
81
|
-
>
|
|
82
|
-
<BodyText subdued={action.disabled}>{action.name}</BodyText>
|
|
83
|
-
</ActionMenu.Item>
|
|
84
|
-
);
|
|
85
|
-
})}
|
|
86
|
-
</ActionMenu>
|
|
87
|
-
);
|
|
88
|
-
}, [isOpen, setOpen, actions, domainValidationStatus]);
|
|
89
|
-
|
|
90
25
|
const nameToShow = name || BRAND_NAME_PLACEHOLDER;
|
|
91
26
|
|
|
92
27
|
return (
|
|
93
28
|
<Card
|
|
94
|
-
className={
|
|
95
|
-
|
|
29
|
+
className={classNames(
|
|
30
|
+
{
|
|
31
|
+
[Styles.cardWithError]: hasError,
|
|
32
|
+
},
|
|
33
|
+
Styles.brandCard,
|
|
34
|
+
'qa-brand-card',
|
|
35
|
+
)}
|
|
36
|
+
padding="large"
|
|
96
37
|
>
|
|
97
|
-
<
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
)}
|
|
38
|
+
<Flex className={Styles.cardContent} justifyContent="space-between" direction="column">
|
|
39
|
+
<Flex
|
|
40
|
+
justifyContent="space-between"
|
|
41
|
+
alignItems="flex-start"
|
|
42
|
+
className="qa-brand-card-left-section"
|
|
43
|
+
>
|
|
44
|
+
<BrandLogo logo={logo} alt={nameToShow} />
|
|
45
|
+
<ActionsButtonSection actions={actions} />
|
|
46
|
+
</Flex>
|
|
107
47
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
el="p"
|
|
111
|
-
subdued={!name}
|
|
112
|
-
className="t-truncate-i m-0"
|
|
113
|
-
title={nameToShow}
|
|
114
|
-
>
|
|
115
|
-
{nameToShow}
|
|
116
|
-
</Headline>
|
|
117
|
-
{email && (
|
|
118
|
-
<BodyText subdued title={email} className="t-truncate-i">
|
|
119
|
-
{email}
|
|
120
|
-
</BodyText>
|
|
121
|
-
)}
|
|
122
|
-
</Stack>
|
|
123
|
-
</Stack>
|
|
124
|
-
</Stack.Item>
|
|
125
|
-
<Stack direction="column">
|
|
126
|
-
{actionsButtonSection}
|
|
48
|
+
<Flex justifyContent="space-between">
|
|
49
|
+
<NameAndMailSection name={name} nameToShow={nameToShow} email={email} />
|
|
127
50
|
<CardTags isDefault={isDefault} isShared={isShared} />
|
|
128
|
-
</
|
|
129
|
-
</
|
|
51
|
+
</Flex>
|
|
52
|
+
</Flex>
|
|
130
53
|
</Card>
|
|
131
54
|
);
|
|
132
55
|
};
|
|
133
|
-
|
|
134
|
-
const CardTags: FC<{ isDefault: boolean; isShared: boolean }> = ({ isDefault, isShared }) => {
|
|
135
|
-
if (!isDefault && !isShared) {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return (
|
|
140
|
-
<Stack direction="column" alignItems="flex-end" className={Styles.tags}>
|
|
141
|
-
{isShared && (
|
|
142
|
-
<Tag className={Styles.corporateTag} color="info" subtle compact>
|
|
143
|
-
Corporate HQ
|
|
144
|
-
</Tag>
|
|
145
|
-
)}
|
|
146
|
-
{isDefault && (
|
|
147
|
-
<Tag className={Styles.defaultTag} compact>
|
|
148
|
-
Default
|
|
149
|
-
</Tag>
|
|
150
|
-
)}
|
|
151
|
-
</Stack>
|
|
152
|
-
);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const SingleActionButtonSection: FC<{
|
|
156
|
-
action: BrandAction;
|
|
157
|
-
domainValidationStatus?: DomainValidationStatus;
|
|
158
|
-
}> = ({ domainValidationStatus, action }) => {
|
|
159
|
-
const validationStatusIcon = useMemo(() => {
|
|
160
|
-
return <ValidationStatusIcon status={domainValidationStatus} />;
|
|
161
|
-
}, [domainValidationStatus]);
|
|
162
|
-
|
|
163
|
-
if (domainValidationStatus === DomainValidationStatus.Pending) {
|
|
164
|
-
return (
|
|
165
|
-
<Stack spacing={1} alignItems="center">
|
|
166
|
-
<BodyText size="small">Validation In Process</BodyText>
|
|
167
|
-
{validationStatusIcon}
|
|
168
|
-
</Stack>
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return (
|
|
173
|
-
<Stack spacing={2} alignItems="center">
|
|
174
|
-
{validationStatusIcon}
|
|
175
|
-
{action.isConfigured && (
|
|
176
|
-
<Icon name="check_circle" color={tokens.colorGreen500} size={24} />
|
|
177
|
-
)}
|
|
178
|
-
|
|
179
|
-
{action.inProgress ? (
|
|
180
|
-
<InProgressButton action={action} />
|
|
181
|
-
) : (
|
|
182
|
-
<StandardButton action={action} />
|
|
183
|
-
)}
|
|
184
|
-
</Stack>
|
|
185
|
-
);
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
const StandardButton: FC<{ action: BrandAction }> = ({ action }) => (
|
|
189
|
-
<Tooltip text={action.disabled ? action.tooltipMessage : ''}>
|
|
190
|
-
{action.href ? (
|
|
191
|
-
<Link to={action.href}>
|
|
192
|
-
<Button size="small" primary outline disabled={action.disabled}>
|
|
193
|
-
{action.name}
|
|
194
|
-
</Button>
|
|
195
|
-
</Link>
|
|
196
|
-
) : (
|
|
197
|
-
<Button size="small" primary onClick={action.action} outline disabled={action.disabled}>
|
|
198
|
-
{action.name}
|
|
199
|
-
</Button>
|
|
200
|
-
)}
|
|
201
|
-
</Tooltip>
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
const InProgressButton: FC<{ action: BrandAction }> = ({ action }) => (
|
|
205
|
-
<Tooltip text={action.disabled ? action.tooltipMessage : ''}>
|
|
206
|
-
{action.href ? (
|
|
207
|
-
<Link to={action.href}>
|
|
208
|
-
<Button size="small" primary text className="m-0 p-1">
|
|
209
|
-
<BodyText size="small" className="m-r-half">
|
|
210
|
-
Registration In Progress
|
|
211
|
-
</BodyText>
|
|
212
|
-
<Icon name="hourglass_full" color={tokens.colorBlue} size={16} />
|
|
213
|
-
</Button>
|
|
214
|
-
</Link>
|
|
215
|
-
) : (
|
|
216
|
-
<Button size="small" primary text className="m-0 p-1" onClick={action.action}>
|
|
217
|
-
<BodyText size="small" className="m-r-1">
|
|
218
|
-
Registration In Progress
|
|
219
|
-
</BodyText>
|
|
220
|
-
<Icon name="hourglass_full" color={tokens.colorBlue} size={16} />
|
|
221
|
-
</Button>
|
|
222
|
-
)}
|
|
223
|
-
</Tooltip>
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
const ValidationStatusIcon: FC<{ status?: DomainValidationStatus }> = ({ status }) => {
|
|
227
|
-
switch (status) {
|
|
228
|
-
case DomainValidationStatus.Error:
|
|
229
|
-
return (
|
|
230
|
-
<Tooltip
|
|
231
|
-
direction="t"
|
|
232
|
-
text="Error is detected in processing the Sender Domain validation. Please check and try again."
|
|
233
|
-
className="cursor-pointer"
|
|
234
|
-
>
|
|
235
|
-
<Icon name="warning" color={tokens.colorRed500} size={24} />
|
|
236
|
-
</Tooltip>
|
|
237
|
-
);
|
|
238
|
-
case DomainValidationStatus.Validated:
|
|
239
|
-
return <Icon name="check_circle" color={tokens.colorGreen500} size={24} />;
|
|
240
|
-
case DomainValidationStatus.Pending:
|
|
241
|
-
return <Icon name="hourglass_full" color={tokens.colorBlue500} size={24} />;
|
|
242
|
-
default:
|
|
243
|
-
return null;
|
|
244
|
-
}
|
|
245
|
-
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
|
|
4
|
+
import { Flex, Icon } from '@servicetitan/anvil2';
|
|
5
|
+
import ImageIcon from '@servicetitan/anvil2/assets/icons/material/round/image.svg';
|
|
6
|
+
import { tokens } from '@servicetitan/tokens/core/index';
|
|
7
|
+
|
|
8
|
+
import * as Styles from '../styles.module.less';
|
|
9
|
+
|
|
10
|
+
export const BrandLogo: FC<{ logo?: string; alt?: string }> = ({ logo, alt }) =>
|
|
11
|
+
logo ? (
|
|
12
|
+
<img className={classNames(Styles.brandImg, 'qa-brand-logo')} src={logo} alt={alt} />
|
|
13
|
+
) : (
|
|
14
|
+
<Flex
|
|
15
|
+
className={classNames(Styles.brandImgPlaceholder, 'qa-brand-logo-placeholder')}
|
|
16
|
+
alignItems="center"
|
|
17
|
+
justifyContent="center"
|
|
18
|
+
>
|
|
19
|
+
<Icon svg={ImageIcon} size="large" color={tokens.colorNeutral90} />
|
|
20
|
+
</Flex>
|
|
21
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Chip, Flex } from '@servicetitan/anvil2';
|
|
4
|
+
import { tokens } from '@servicetitan/tokens/core/index';
|
|
5
|
+
|
|
6
|
+
export const CardTags: FC<{ isDefault?: boolean; isShared?: boolean }> = ({
|
|
7
|
+
isDefault,
|
|
8
|
+
isShared,
|
|
9
|
+
}) => {
|
|
10
|
+
if (!isDefault && !isShared) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<Flex direction="column" alignItems="flex-end" className="qa-brand-card-tags" gap="1">
|
|
16
|
+
{isShared && <Chip color={tokens.colorPurple100} label="Corporate HQ" size="small" />}
|
|
17
|
+
{isDefault && <Chip label="Default" color={tokens.colorNeutral50} size="small" />}
|
|
18
|
+
</Flex>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
|
|
4
|
+
import { BodyText, Headline } from '@servicetitan/design-system';
|
|
5
|
+
import { Flex } from '@servicetitan/anvil2';
|
|
6
|
+
|
|
7
|
+
import * as Styles from '../styles.module.less';
|
|
8
|
+
|
|
9
|
+
export const NameAndMailSection: FC<{ name?: string; nameToShow: string; email?: string }> = ({
|
|
10
|
+
name,
|
|
11
|
+
email,
|
|
12
|
+
nameToShow,
|
|
13
|
+
}) => (
|
|
14
|
+
<Flex
|
|
15
|
+
justifyContent="space-between"
|
|
16
|
+
direction="column"
|
|
17
|
+
className={classNames(Styles.cardLeftSectionTexts, 'qa-brand-card-name-and-mail')}
|
|
18
|
+
>
|
|
19
|
+
<Headline el="p" subdued={!name} className="t-truncate-i m-0" title={nameToShow}>
|
|
20
|
+
{nameToShow}
|
|
21
|
+
</Headline>
|
|
22
|
+
{email && (
|
|
23
|
+
<BodyText subdued title={email} className="t-truncate-i">
|
|
24
|
+
{email}
|
|
25
|
+
</BodyText>
|
|
26
|
+
)}
|
|
27
|
+
</Flex>
|
|
28
|
+
);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { FC, PropsWithChildren } from 'react';
|
|
2
|
+
import { useHistory } from 'react-router-dom';
|
|
3
|
+
|
|
4
|
+
import HelpIcon from '@servicetitan/anvil2/assets/icons/material/round/help.svg';
|
|
5
|
+
import { Chip, Flex, Tooltip as TooltipA2, Button } from '@servicetitan/anvil2';
|
|
6
|
+
import { ButtonAppearance } from '@servicetitan/hammer-react/dist/types/props';
|
|
7
|
+
|
|
8
|
+
import { BrandAction } from '../../../utils/interfaces';
|
|
9
|
+
import { BrandActionChipColor, BrandActionChipLabel } from '../../../utils/mappers';
|
|
10
|
+
import { ActionStatus } from '../../../enums/brands';
|
|
11
|
+
|
|
12
|
+
export const SingleActionButtonSection: FC<{
|
|
13
|
+
action: BrandAction;
|
|
14
|
+
}> = ({ action }) => {
|
|
15
|
+
const history = useHistory();
|
|
16
|
+
const handleClick = () => {
|
|
17
|
+
if (action.action) {
|
|
18
|
+
action.action();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (action.href) {
|
|
22
|
+
history.push(action.href);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
let buttonAppearance: ButtonAppearance | undefined;
|
|
27
|
+
if (action.status === undefined) {
|
|
28
|
+
buttonAppearance = 'primary';
|
|
29
|
+
} else if (!action.disabled) {
|
|
30
|
+
buttonAppearance = 'secondary';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Flex gap="2" alignItems="center" className="qa-brand-card-single-action">
|
|
35
|
+
<ActionChip status={action.status} statusTooltip={action.statusTooltip} />
|
|
36
|
+
<Button
|
|
37
|
+
size="small"
|
|
38
|
+
onClick={handleClick}
|
|
39
|
+
disabled={action.disabled}
|
|
40
|
+
appearance={buttonAppearance}
|
|
41
|
+
>
|
|
42
|
+
{action.name}
|
|
43
|
+
</Button>
|
|
44
|
+
{action.disabled && (
|
|
45
|
+
<DisabledActionHelper>{action.disableTooltipContent?.()}</DisabledActionHelper>
|
|
46
|
+
)}
|
|
47
|
+
</Flex>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const ActionChip: FC<{ status?: ActionStatus; statusTooltip?: string }> = ({
|
|
52
|
+
status,
|
|
53
|
+
statusTooltip,
|
|
54
|
+
}) => {
|
|
55
|
+
if (status === undefined) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const chip = (
|
|
60
|
+
<Chip
|
|
61
|
+
label={BrandActionChipLabel[status]}
|
|
62
|
+
color={BrandActionChipColor[status]}
|
|
63
|
+
size="small"
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return statusTooltip ? (
|
|
68
|
+
<TooltipA2>
|
|
69
|
+
<TooltipA2.Trigger>{chip}</TooltipA2.Trigger>
|
|
70
|
+
<TooltipA2.Content>{statusTooltip}</TooltipA2.Content>
|
|
71
|
+
</TooltipA2>
|
|
72
|
+
) : (
|
|
73
|
+
chip
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const DisabledActionHelper: FC<PropsWithChildren> = ({ children }) => (
|
|
78
|
+
<TooltipA2>
|
|
79
|
+
<TooltipA2.Trigger>
|
|
80
|
+
<Button icon={HelpIcon} size="small" />
|
|
81
|
+
</TooltipA2.Trigger>
|
|
82
|
+
<TooltipA2.Content>{children}</TooltipA2.Content>
|
|
83
|
+
</TooltipA2>
|
|
84
|
+
);
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
2
3
|
|
|
3
4
|
import { Grid } from '@servicetitan/anvil2';
|
|
4
5
|
|
|
5
6
|
import { BrandCard } from '../brand-card/brand-card';
|
|
6
|
-
import { BrandCardProps } from '../../../
|
|
7
|
+
import { BrandCardProps } from '../../../utils/interfaces';
|
|
7
8
|
|
|
8
9
|
import * as Styles from '../styles.module.less';
|
|
9
10
|
|
|
10
|
-
export const CardsGrid: FC<{
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
export const CardsGrid: FC<{
|
|
12
|
+
brands: BrandCardProps[];
|
|
13
|
+
qaIdentifier: string;
|
|
14
|
+
}> = ({ brands, qaIdentifier }) => (
|
|
15
|
+
<Grid className={classNames(Styles.grid, `qa-${qaIdentifier}-cards-grid`)} gap="6">
|
|
16
|
+
{brands.map(brand => (
|
|
17
|
+
<BrandCard key={brand.id} {...brand} />
|
|
18
|
+
))}
|
|
15
19
|
</Grid>
|
|
16
20
|
);
|
|
@@ -30,17 +30,14 @@
|
|
|
30
30
|
height: 200px;
|
|
31
31
|
min-width: @card-min-width;
|
|
32
32
|
max-width: @card-max-width;
|
|
33
|
-
box-sizing: border-box;
|
|
34
|
-
background: inherit !important;
|
|
35
|
-
|
|
36
|
-
:global(.CardSection) {
|
|
37
|
-
height: 150px;
|
|
38
|
-
background-color: @color-white;
|
|
39
|
-
}
|
|
40
33
|
}
|
|
41
34
|
|
|
42
35
|
.card-content {
|
|
43
|
-
|
|
36
|
+
width: 100%;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.card-left-section-texts {
|
|
40
|
+
min-width: 0;
|
|
44
41
|
}
|
|
45
42
|
|
|
46
43
|
.brand-img {
|
|
@@ -57,17 +54,6 @@
|
|
|
57
54
|
background-color: @color-neutral-60;
|
|
58
55
|
}
|
|
59
56
|
|
|
60
|
-
.
|
|
61
|
-
|
|
62
|
-
margin-bottom: 2px;
|
|
63
|
-
margin-top: auto;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.default-tag {
|
|
67
|
-
width: 53px;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.corporate-tag {
|
|
71
|
-
min-width: 86px;
|
|
72
|
-
margin-bottom: @spacing-half;
|
|
57
|
+
.card-with-error {
|
|
58
|
+
border-color: @color-red-500;
|
|
73
59
|
}
|
|
@@ -3,9 +3,8 @@ export const brandCard: string;
|
|
|
3
3
|
export const brandImg: string;
|
|
4
4
|
export const brandImgPlaceholder: string;
|
|
5
5
|
export const cardContent: string;
|
|
6
|
-
export const
|
|
7
|
-
export const
|
|
6
|
+
export const cardLeftSectionTexts: string;
|
|
7
|
+
export const cardWithError: string;
|
|
8
8
|
export const deleteTooltip: string;
|
|
9
9
|
export const grid: string;
|
|
10
|
-
export const tags: string;
|
|
11
10
|
|
package/src/enums/brands.ts
CHANGED
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
disabled?: boolean;
|
|
6
|
-
|
|
7
|
-
tooltipMessage?: string;
|
|
8
|
-
inProgress?: boolean;
|
|
9
|
-
isConfigured?: boolean;
|
|
10
|
-
href?: string;
|
|
11
|
-
action?: () => void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface BrandCardProps {
|
|
15
|
-
id: string;
|
|
16
|
-
actions: BrandAction | BrandAction[];
|
|
17
|
-
logo?: string;
|
|
18
|
-
name?: string;
|
|
19
|
-
isDefault: boolean;
|
|
20
|
-
email?: string;
|
|
21
|
-
domainValidationStatus?: DomainValidationStatus;
|
|
22
|
-
isShared: boolean;
|
|
1
|
+
export enum ActionStatus {
|
|
2
|
+
Error,
|
|
3
|
+
Pending,
|
|
4
|
+
Approved,
|
|
23
5
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from './components/settings';
|
|
2
2
|
export * from './components/campaign-actions';
|
|
3
|
-
export * from './
|
|
3
|
+
export * from './components/settings';
|
|
4
4
|
export * from './utils/helpers';
|
|
5
|
+
export * from './utils/interfaces';
|
|
6
|
+
export * from './enums/brands';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { JSX } from 'react';
|
|
2
|
+
import { ActionStatus } from '../enums/brands';
|
|
3
|
+
|
|
4
|
+
export interface BrandAction {
|
|
5
|
+
name: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
disableTooltipContent?: () => JSX.Element | string;
|
|
8
|
+
href?: string;
|
|
9
|
+
status?: ActionStatus;
|
|
10
|
+
statusTooltip?: string;
|
|
11
|
+
action?: () => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface BrandCardProps {
|
|
15
|
+
id: string;
|
|
16
|
+
hasError?: boolean;
|
|
17
|
+
actions: BrandAction | BrandAction[];
|
|
18
|
+
logo?: string;
|
|
19
|
+
name?: string;
|
|
20
|
+
isDefault: boolean;
|
|
21
|
+
email?: string;
|
|
22
|
+
isShared?: boolean;
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ActionStatus } from '../enums/brands';
|
|
2
|
+
import { tokens } from '@servicetitan/tokens/core';
|
|
3
|
+
|
|
4
|
+
export const BrandActionChipLabel: Record<ActionStatus, string> = {
|
|
5
|
+
[ActionStatus.Pending]: 'Pending',
|
|
6
|
+
[ActionStatus.Error]: 'Error',
|
|
7
|
+
[ActionStatus.Approved]: 'Complete',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const BrandActionChipColor: Record<ActionStatus, string> = {
|
|
11
|
+
[ActionStatus.Pending]: tokens.colorOrange200,
|
|
12
|
+
[ActionStatus.Error]: tokens.colorRed500,
|
|
13
|
+
[ActionStatus.Approved]: tokens.colorGreen200,
|
|
14
|
+
};
|