@vtex/faststore-plugin-buyer-portal 1.3.40 → 1.3.42
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 +25 -1
- package/package.json +1 -1
- package/src/features/addresses/components/AddressForm/AddressForm.tsx +254 -220
- package/src/features/addresses/components/CreateAddressSettingsDrawer/CreateAddressSettingsDrawer.tsx +64 -25
- package/src/features/addresses/components/CreateAddressSettingsDrawer/create-address-settings-drawer.scss +22 -22
- package/src/features/addresses/services/default-values/get-default-address.service.ts +1 -1
- package/src/features/addresses/types/AddressData.ts +1 -0
- package/src/features/payment-methods/layouts/PaymentMethodsLayout/PaymentMethodsLayout.tsx +8 -6
- package/src/features/shared/clients/ScopeClient.ts +38 -2
- package/src/features/shared/components/Error/Error.tsx +15 -13
- package/src/features/shared/components/SettingsDrawer/SettingsDrawer.tsx +106 -0
- package/src/features/shared/components/SettingsDrawer/SettingsDrawerContext.tsx +17 -0
- package/src/features/shared/components/SettingsDrawer/SettingsDrawerListType.tsx +100 -0
- package/src/features/shared/components/SettingsDrawer/settings-drawer.scss +61 -0
- package/src/features/shared/components/index.ts +7 -0
- package/src/features/shared/hooks/index.ts +2 -0
- package/src/features/shared/hooks/useGetScopeConfig.ts +35 -0
- package/src/features/shared/hooks/useSetScopeConfig.ts +30 -0
- package/src/features/shared/services/get-scope-config.service.ts +19 -0
- package/src/features/shared/services/index.ts +9 -0
- package/src/features/shared/services/set-scope-config.service.ts +27 -0
- package/src/features/shared/types/index.ts +1 -0
- package/src/features/shared/utils/constants.ts +10 -1
- package/src/features/shared/utils/index.ts +6 -1
- package/src/pages/payment-methods.tsx +1 -1
|
@@ -7,11 +7,14 @@ import { useUI, Skeleton } from "@faststore/ui";
|
|
|
7
7
|
import {
|
|
8
8
|
type BasicDrawerProps,
|
|
9
9
|
AutocompleteDropdown,
|
|
10
|
-
|
|
10
|
+
DEFAULT_LIST_TYPE_OPTIONS,
|
|
11
11
|
Icon,
|
|
12
|
+
ListTypeOption,
|
|
13
|
+
SettingsDrawer,
|
|
12
14
|
} from "../../../shared/components";
|
|
13
15
|
import { OptionSelected } from "../../../shared/components/OptionSelected/OptionSelected";
|
|
14
16
|
import { SearchHighlight } from "../../../shared/components/SearchHighlight/SearchHighlight";
|
|
17
|
+
import { useSetScopeConfig, SCOPE_KEYS } from "../../../shared/hooks";
|
|
15
18
|
import { ADDRESS_MESSAGES } from "../../constants/messages";
|
|
16
19
|
import { useDebouncedSearchAddressByUnitId } from "../../hooks/useDebouncedSearchAddressByUnitId";
|
|
17
20
|
import { useGetDefaultAddress } from "../../hooks/useGetDefaultAddresses";
|
|
@@ -28,14 +31,27 @@ export type CreateAddressSettingsDrawerProps = Omit<
|
|
|
28
31
|
onUpdate?: () => void;
|
|
29
32
|
};
|
|
30
33
|
|
|
34
|
+
export const ADDRESS_LIST_TYPE_OPTIONS: ListTypeOption[] = [
|
|
35
|
+
{
|
|
36
|
+
...DEFAULT_LIST_TYPE_OPTIONS[0],
|
|
37
|
+
description: "Manage a unique list of addresses for this organization.",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
...DEFAULT_LIST_TYPE_OPTIONS[1],
|
|
41
|
+
description:
|
|
42
|
+
"Use the shared list of addresses defined by the contract. Updates are automatic.",
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
31
46
|
export const CreateAddressSettingsDrawer = ({
|
|
32
47
|
close,
|
|
33
48
|
onUpdate,
|
|
34
|
-
...
|
|
49
|
+
...otherProps
|
|
35
50
|
}: CreateAddressSettingsDrawerProps) => {
|
|
36
51
|
const { pushToast } = useUI();
|
|
37
52
|
const router = useRouter();
|
|
38
53
|
|
|
54
|
+
const [listType, setListType] = useState<"sync" | "custom">("custom");
|
|
39
55
|
const [searchValue, setSearchValue] = useState("");
|
|
40
56
|
const [activeField, setActiveField] = useState<"Shipping" | "Billing" | null>(
|
|
41
57
|
"Shipping"
|
|
@@ -103,6 +119,21 @@ export const CreateAddressSettingsDrawer = ({
|
|
|
103
119
|
},
|
|
104
120
|
});
|
|
105
121
|
|
|
122
|
+
const { setScopeConfig, isSetScopeConfigLoading } = useSetScopeConfig({
|
|
123
|
+
onSuccess: () => {
|
|
124
|
+
pushToast({
|
|
125
|
+
message: "Scope configuration updated successfully",
|
|
126
|
+
status: "INFO",
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
onError: () => {
|
|
130
|
+
pushToast({
|
|
131
|
+
message: "Failed to update scope configuration",
|
|
132
|
+
status: "ERROR",
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
106
137
|
const isConfirmButtonEnabled = Boolean(
|
|
107
138
|
shippingAddress?.id || billingAddress?.id
|
|
108
139
|
);
|
|
@@ -125,6 +156,15 @@ export const CreateAddressSettingsDrawer = ({
|
|
|
125
156
|
}
|
|
126
157
|
|
|
127
158
|
const handleConfirmClick = () => {
|
|
159
|
+
// Update scope config if listType changed
|
|
160
|
+
setScopeConfig({
|
|
161
|
+
customerId: router.query.contractId as string,
|
|
162
|
+
unitId: router.query.orgUnitId as string,
|
|
163
|
+
scopeName: SCOPE_KEYS.ADDRESSES,
|
|
164
|
+
type: listType,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Set default addresses
|
|
128
168
|
setDefaultAddresses({
|
|
129
169
|
orgUnitId: router.query.orgUnitId as string,
|
|
130
170
|
customerId: router.query.contractId as string,
|
|
@@ -133,16 +173,29 @@ export const CreateAddressSettingsDrawer = ({
|
|
|
133
173
|
};
|
|
134
174
|
|
|
135
175
|
return (
|
|
136
|
-
<
|
|
137
|
-
|
|
176
|
+
<SettingsDrawer
|
|
177
|
+
title="Address settings"
|
|
178
|
+
{...otherProps}
|
|
138
179
|
close={close}
|
|
139
|
-
{
|
|
180
|
+
onPrimaryAction={handleConfirmClick}
|
|
181
|
+
isPrimaryButtonLoading={
|
|
182
|
+
isSetDefaultAddressesLoading || isSetScopeConfigLoading
|
|
183
|
+
}
|
|
184
|
+
isPrimaryButtonDisabled={!isConfirmButtonEnabled}
|
|
185
|
+
scopeName={SCOPE_KEYS.ADDRESSES}
|
|
186
|
+
onDismiss={close}
|
|
187
|
+
data-fs-bp-create-address-settings-drawer
|
|
140
188
|
>
|
|
141
|
-
<
|
|
189
|
+
<SettingsDrawer.ListType
|
|
190
|
+
title="List type"
|
|
191
|
+
name="listType"
|
|
192
|
+
value={listType}
|
|
193
|
+
onChange={setListType}
|
|
194
|
+
options={ADDRESS_LIST_TYPE_OPTIONS}
|
|
195
|
+
/>
|
|
142
196
|
|
|
143
|
-
<
|
|
144
|
-
<
|
|
145
|
-
<h4>Select the default addresses for this unit</h4>
|
|
197
|
+
<div data-fs-bp-default-addresses-section>
|
|
198
|
+
<h4 data-fs-bp-default-addresses-title>Default addresses</h4>
|
|
146
199
|
|
|
147
200
|
<p data-fs-bp-default-address-label>
|
|
148
201
|
Default shipping address (optional)
|
|
@@ -248,21 +301,7 @@ export const CreateAddressSettingsDrawer = ({
|
|
|
248
301
|
)}
|
|
249
302
|
/>
|
|
250
303
|
)}
|
|
251
|
-
</
|
|
252
|
-
|
|
253
|
-
<BasicDrawer.Footer>
|
|
254
|
-
<BasicDrawer.Button variant="ghost" onClick={close}>
|
|
255
|
-
Cancel
|
|
256
|
-
</BasicDrawer.Button>
|
|
257
|
-
<BasicDrawer.Button
|
|
258
|
-
variant="confirm"
|
|
259
|
-
disabled={!isConfirmButtonEnabled}
|
|
260
|
-
onClick={handleConfirmClick}
|
|
261
|
-
isLoading={isSetDefaultAddressesLoading}
|
|
262
|
-
>
|
|
263
|
-
Save
|
|
264
|
-
</BasicDrawer.Button>
|
|
265
|
-
</BasicDrawer.Footer>
|
|
266
|
-
</BasicDrawer>
|
|
304
|
+
</div>
|
|
305
|
+
</SettingsDrawer>
|
|
267
306
|
);
|
|
268
307
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
@import "../../../shared/components/
|
|
1
|
+
@import "../../../shared/components/SettingsDrawer/settings-drawer.scss";
|
|
2
2
|
|
|
3
3
|
[data-fs-bp-create-address-settings-drawer] {
|
|
4
4
|
@import "../../../shared/components/InputText/input-text.scss";
|
|
5
5
|
@import "../../../shared/components/ErrorMessage/error-message.scss";
|
|
6
6
|
@import "../../../shared/components/SearchHighlight/search-highlight.scss";
|
|
7
|
+
|
|
7
8
|
@import "../ExistingAddress/existing-address.scss";
|
|
8
9
|
@import "../LocationForm/location-form.scss";
|
|
9
10
|
@import "../RecipientsForm/recipients-form.scss";
|
|
@@ -12,33 +13,32 @@
|
|
|
12
13
|
@import "@faststore/ui/src/components/atoms/Button/styles.scss";
|
|
13
14
|
@import "@faststore/ui/src/components/molecules/Alert/styles.scss";
|
|
14
15
|
|
|
15
|
-
[data-fs-bp-
|
|
16
|
+
[data-fs-bp-settings-drawer-body] {
|
|
16
17
|
padding-bottom: 90px;
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
[data-fs-bp-default-addresses-section] {
|
|
20
|
+
[data-fs-bp-default-addresses-title] {
|
|
21
|
+
font-weight: var(--fs-text-weight-semibold);
|
|
22
|
+
font-size: var(--fs-text-size-1);
|
|
23
|
+
line-height: 1.25rem;
|
|
24
|
+
letter-spacing: -0.01em;
|
|
25
|
+
margin-bottom: var(--fs-spacing-4);
|
|
25
26
|
margin-top: 0;
|
|
27
|
+
color: #000000;
|
|
26
28
|
}
|
|
27
|
-
}
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
[data-fs-bp-default-address-label] {
|
|
31
|
+
font-weight: var(--fs-text-weight-regular);
|
|
32
|
+
font-size: var(--fs-text-size-1);
|
|
33
|
+
line-height: 1.5;
|
|
34
|
+
color: #1f1f1f;
|
|
35
|
+
margin-bottom: var(--fs-spacing-1);
|
|
36
|
+
margin-top: var(--fs-spacing-4);
|
|
35
37
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
color: #1f1f1f;
|
|
41
|
-
margin-bottom: var(--fs-spacing-0);
|
|
38
|
+
&:first-of-type {
|
|
39
|
+
margin-top: 0;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -45,7 +45,7 @@ export const PaymentMethodsLayout = ({
|
|
|
45
45
|
setSelectedMethod(undefined);
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
const isLastPage = data.paging
|
|
48
|
+
const isLastPage = data.paging?.pages === page || data.paging?.pages === 0;
|
|
49
49
|
|
|
50
50
|
const {
|
|
51
51
|
isLoading,
|
|
@@ -171,9 +171,9 @@ export const PaymentMethodsLayout = ({
|
|
|
171
171
|
textSearch={setSearchTerm}
|
|
172
172
|
/>
|
|
173
173
|
<Paginator.Counter
|
|
174
|
-
total={data.paging
|
|
174
|
+
total={data.paging?.total ?? 0}
|
|
175
175
|
itemsLength={
|
|
176
|
-
isLastPage ? data.paging
|
|
176
|
+
isLastPage ? data.paging?.total : page * data.paging?.perPage
|
|
177
177
|
}
|
|
178
178
|
/>
|
|
179
179
|
</div>
|
|
@@ -182,7 +182,7 @@ export const PaymentMethodsLayout = ({
|
|
|
182
182
|
|
|
183
183
|
{!isLoading && paymentMethods.length > 0 && (
|
|
184
184
|
<div data-fs-bp-payment-methods-paginator>
|
|
185
|
-
{data.paging
|
|
185
|
+
{(data.paging?.page ?? 1) > 1 ? (
|
|
186
186
|
<Paginator.NextPageButton
|
|
187
187
|
onClick={decreasePage}
|
|
188
188
|
disabled={isLoading}
|
|
@@ -204,9 +204,11 @@ export const PaymentMethodsLayout = ({
|
|
|
204
204
|
)}
|
|
205
205
|
|
|
206
206
|
<Paginator.Counter
|
|
207
|
-
total={data.paging
|
|
207
|
+
total={data.paging?.total ?? 0}
|
|
208
208
|
itemsLength={
|
|
209
|
-
isLastPage
|
|
209
|
+
isLastPage
|
|
210
|
+
? data.paging?.total ?? 0
|
|
211
|
+
: page * (data.paging?.perPage ?? 0)
|
|
210
212
|
}
|
|
211
213
|
/>
|
|
212
214
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getApiUrl } from "../../shared/utils";
|
|
1
|
+
import { getApiUrl, SCOPE_KEYS } from "../../shared/utils";
|
|
2
2
|
|
|
3
3
|
import { Client } from "./Client";
|
|
4
4
|
|
|
@@ -32,8 +32,44 @@ export default class ScopeClient extends Client {
|
|
|
32
32
|
}
|
|
33
33
|
);
|
|
34
34
|
}
|
|
35
|
+
|
|
36
|
+
getScopeConfig(
|
|
37
|
+
customerId: string,
|
|
38
|
+
unitId: string,
|
|
39
|
+
scopeName: string,
|
|
40
|
+
cookie: string
|
|
41
|
+
) {
|
|
42
|
+
return this.get<{ type: "sync" | "custom" }>(
|
|
43
|
+
`customers/${customerId}/units/${unitId}/scopes/configs`,
|
|
44
|
+
{
|
|
45
|
+
params: { scopeName },
|
|
46
|
+
headers: {
|
|
47
|
+
Cookie: cookie,
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
setScopeConfig(
|
|
54
|
+
customerId: string,
|
|
55
|
+
unitId: string,
|
|
56
|
+
scopeName: string,
|
|
57
|
+
type: "sync" | "custom",
|
|
58
|
+
cookie: string
|
|
59
|
+
) {
|
|
60
|
+
return this.post<{ message: string }, { type: "sync" | "custom" }>(
|
|
61
|
+
`customers/${customerId}/units/${unitId}/scopes/configs`,
|
|
62
|
+
{ type },
|
|
63
|
+
{
|
|
64
|
+
params: { scopeName },
|
|
65
|
+
headers: {
|
|
66
|
+
Cookie: cookie,
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
}
|
|
35
71
|
}
|
|
36
72
|
|
|
37
73
|
const scopesClient = new ScopeClient();
|
|
38
74
|
|
|
39
|
-
export { scopesClient };
|
|
75
|
+
export { scopesClient, SCOPE_KEYS };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { isDevelopment } from "../../utils/environment";
|
|
2
2
|
import { Icon } from "../Icon";
|
|
3
3
|
|
|
4
4
|
export type ErrorProps = {
|
|
@@ -20,18 +20,20 @@ export default function Error({ error }: ErrorProps) {
|
|
|
20
20
|
<button data-fs-bp-error-button onClick={() => window.location.reload()}>
|
|
21
21
|
Try again
|
|
22
22
|
</button>
|
|
23
|
-
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
{isDevelopment() && (
|
|
24
|
+
<div data-fs-bp-error-details>
|
|
25
|
+
<span data-fs-bp-error-details-type>{error?.tags?.errorType}</span>
|
|
26
|
+
<h2 data-fs-bp-error-details-title>Error Details</h2>
|
|
27
|
+
<p data-fs-bp-error-details-message>{error?.error.message}</p>
|
|
28
|
+
<p data-fs-bp-error-details-stack>Stack: {error?.error.stack}</p>
|
|
29
|
+
<p data-fs-bp-error-details-component>
|
|
30
|
+
Component: {error?.tags?.component}
|
|
31
|
+
</p>
|
|
32
|
+
<p data-fs-bp-error-details-query>
|
|
33
|
+
Query: {JSON.stringify(error?.query)}
|
|
34
|
+
</p>
|
|
35
|
+
</div>
|
|
36
|
+
)}
|
|
35
37
|
</div>
|
|
36
38
|
);
|
|
37
39
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { useBuyerPortal } from "../../hooks";
|
|
4
|
+
import { BasicDrawer, type BasicDrawerProps } from "../BasicDrawer/BasicDrawer";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
SettingsDrawerContext,
|
|
8
|
+
type SettingsDrawerContextType,
|
|
9
|
+
} from "./SettingsDrawerContext";
|
|
10
|
+
import {
|
|
11
|
+
SettingsDrawerListType,
|
|
12
|
+
type ListTypeOption,
|
|
13
|
+
type SettingsDrawerListTypeProps,
|
|
14
|
+
DEFAULT_LIST_TYPE_OPTIONS,
|
|
15
|
+
} from "./SettingsDrawerListType";
|
|
16
|
+
|
|
17
|
+
export type { ListTypeOption, SettingsDrawerListTypeProps };
|
|
18
|
+
export { DEFAULT_LIST_TYPE_OPTIONS };
|
|
19
|
+
|
|
20
|
+
export type SettingsDrawerProps = Omit<BasicDrawerProps, "children"> & {
|
|
21
|
+
title: string;
|
|
22
|
+
subtitle?: string;
|
|
23
|
+
children: React.ReactNode;
|
|
24
|
+
primaryButtonLabel?: string;
|
|
25
|
+
secondaryButtonLabel?: string;
|
|
26
|
+
onPrimaryAction?: () => void;
|
|
27
|
+
onSecondaryAction?: () => void;
|
|
28
|
+
isPrimaryButtonLoading?: boolean;
|
|
29
|
+
isPrimaryButtonDisabled?: boolean;
|
|
30
|
+
isSecondaryButtonDisabled?: boolean;
|
|
31
|
+
scopeName?: string;
|
|
32
|
+
customerId?: string;
|
|
33
|
+
unitId?: string;
|
|
34
|
+
onScopeConfigChange?: (type: "sync" | "custom") => void;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const SettingsDrawer = ({
|
|
38
|
+
title,
|
|
39
|
+
subtitle,
|
|
40
|
+
children,
|
|
41
|
+
primaryButtonLabel = "Save",
|
|
42
|
+
secondaryButtonLabel = "Cancel",
|
|
43
|
+
onPrimaryAction,
|
|
44
|
+
onSecondaryAction,
|
|
45
|
+
isPrimaryButtonLoading = false,
|
|
46
|
+
isPrimaryButtonDisabled = false,
|
|
47
|
+
isSecondaryButtonDisabled = false,
|
|
48
|
+
scopeName,
|
|
49
|
+
customerId,
|
|
50
|
+
unitId,
|
|
51
|
+
onScopeConfigChange,
|
|
52
|
+
onDismiss,
|
|
53
|
+
...otherProps
|
|
54
|
+
}: SettingsDrawerProps) => {
|
|
55
|
+
const { clientContext, currentOrgUnit, currentContract } = useBuyerPortal();
|
|
56
|
+
|
|
57
|
+
const resolvedCustomerId =
|
|
58
|
+
customerId || currentContract?.id || clientContext.customerId;
|
|
59
|
+
const resolvedUnitId = unitId || currentOrgUnit?.id || "";
|
|
60
|
+
|
|
61
|
+
const handleClose = () => {
|
|
62
|
+
onDismiss?.();
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const contextValue: SettingsDrawerContextType = {
|
|
66
|
+
scopeName,
|
|
67
|
+
customerId: resolvedCustomerId,
|
|
68
|
+
unitId: resolvedUnitId,
|
|
69
|
+
onScopeConfigChange,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<SettingsDrawerContext.Provider value={contextValue}>
|
|
74
|
+
<BasicDrawer
|
|
75
|
+
data-fs-bp-settings-drawer
|
|
76
|
+
onDismiss={handleClose}
|
|
77
|
+
{...otherProps}
|
|
78
|
+
>
|
|
79
|
+
<BasicDrawer.Heading title={title} onClose={handleClose} />
|
|
80
|
+
<BasicDrawer.Body data-fs-bp-settings-drawer-body>
|
|
81
|
+
{subtitle && <p data-fs-bp-settings-drawer-subtitle>{subtitle}</p>}
|
|
82
|
+
{children}
|
|
83
|
+
</BasicDrawer.Body>
|
|
84
|
+
<BasicDrawer.Footer>
|
|
85
|
+
<BasicDrawer.Button
|
|
86
|
+
variant="ghost"
|
|
87
|
+
onClick={onSecondaryAction || handleClose}
|
|
88
|
+
disabled={isSecondaryButtonDisabled}
|
|
89
|
+
>
|
|
90
|
+
{secondaryButtonLabel}
|
|
91
|
+
</BasicDrawer.Button>
|
|
92
|
+
<BasicDrawer.Button
|
|
93
|
+
variant="confirm"
|
|
94
|
+
onClick={onPrimaryAction}
|
|
95
|
+
isLoading={isPrimaryButtonLoading}
|
|
96
|
+
disabled={isPrimaryButtonDisabled}
|
|
97
|
+
>
|
|
98
|
+
{primaryButtonLabel}
|
|
99
|
+
</BasicDrawer.Button>
|
|
100
|
+
</BasicDrawer.Footer>
|
|
101
|
+
</BasicDrawer>
|
|
102
|
+
</SettingsDrawerContext.Provider>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
SettingsDrawer.ListType = SettingsDrawerListType;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
|
|
3
|
+
export type SettingsDrawerContextType = {
|
|
4
|
+
scopeName?: string;
|
|
5
|
+
customerId?: string;
|
|
6
|
+
unitId?: string;
|
|
7
|
+
onScopeConfigChange?: (type: "sync" | "custom") => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const SettingsDrawerContext = createContext<
|
|
11
|
+
SettingsDrawerContextType | undefined
|
|
12
|
+
>(undefined);
|
|
13
|
+
|
|
14
|
+
export const useSettingsDrawerContext = (): SettingsDrawerContextType => {
|
|
15
|
+
const context = useContext(SettingsDrawerContext);
|
|
16
|
+
return context || {};
|
|
17
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { RadioGroup, RadioOption } from "@faststore/ui";
|
|
4
|
+
|
|
5
|
+
import { useGetScopeConfig } from "../../hooks";
|
|
6
|
+
|
|
7
|
+
import { useSettingsDrawerContext } from "./SettingsDrawerContext";
|
|
8
|
+
|
|
9
|
+
export type ListTypeOption = {
|
|
10
|
+
value: string;
|
|
11
|
+
label: string;
|
|
12
|
+
description: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const DEFAULT_LIST_TYPE_OPTIONS: ListTypeOption[] = [
|
|
16
|
+
{
|
|
17
|
+
value: "custom",
|
|
18
|
+
label: "Custom list",
|
|
19
|
+
description: "Manage a unique for this organization.",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
value: "sync",
|
|
23
|
+
label: "Synchronized List",
|
|
24
|
+
description:
|
|
25
|
+
"Use the shared list defined by the contract. Updates are automatic.",
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
export type SettingsDrawerListTypeProps = {
|
|
30
|
+
title: string;
|
|
31
|
+
name: string;
|
|
32
|
+
value?: "sync" | "custom";
|
|
33
|
+
options?: ListTypeOption[];
|
|
34
|
+
onChange?: (value: "sync" | "custom") => void;
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const SettingsDrawerListType = ({
|
|
39
|
+
title,
|
|
40
|
+
name,
|
|
41
|
+
value: controlledValue,
|
|
42
|
+
options = DEFAULT_LIST_TYPE_OPTIONS,
|
|
43
|
+
onChange: controlledOnChange,
|
|
44
|
+
disabled = false,
|
|
45
|
+
}: SettingsDrawerListTypeProps) => {
|
|
46
|
+
const { scopeName, customerId, unitId } = useSettingsDrawerContext();
|
|
47
|
+
const [internalValue, setInternalValue] = useState<"sync" | "custom">(
|
|
48
|
+
"custom"
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const { isScopeConfigLoading } = useGetScopeConfig(
|
|
52
|
+
{
|
|
53
|
+
customerId: customerId ?? "",
|
|
54
|
+
unitId: unitId ?? "",
|
|
55
|
+
scopeName: scopeName ?? "",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
lazy: !scopeName || !customerId || !unitId,
|
|
59
|
+
onSuccess: (data) => {
|
|
60
|
+
if (data?.type) {
|
|
61
|
+
setInternalValue(data.type);
|
|
62
|
+
controlledOnChange?.(data.type);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const value = controlledValue ?? internalValue;
|
|
69
|
+
const isLoading = isScopeConfigLoading;
|
|
70
|
+
|
|
71
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
72
|
+
const newValue = e.target.value as "sync" | "custom";
|
|
73
|
+
setInternalValue(newValue);
|
|
74
|
+
|
|
75
|
+
if (controlledOnChange) {
|
|
76
|
+
controlledOnChange(newValue);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<div data-fs-bp-settings-drawer-list-type>
|
|
82
|
+
<h4 data-fs-bp-settings-drawer-list-type-title>{title}</h4>
|
|
83
|
+
<RadioGroup name={name} selectedValue={value} onChange={handleChange}>
|
|
84
|
+
{options.map((option) => (
|
|
85
|
+
<div key={option.value} data-fs-bp-settings-drawer-list-type-option>
|
|
86
|
+
<RadioOption
|
|
87
|
+
value={option.value}
|
|
88
|
+
label={option.label}
|
|
89
|
+
name={name}
|
|
90
|
+
disabled={disabled || isLoading}
|
|
91
|
+
/>
|
|
92
|
+
<p data-fs-bp-settings-drawer-list-type-description>
|
|
93
|
+
{option.description}
|
|
94
|
+
</p>
|
|
95
|
+
</div>
|
|
96
|
+
))}
|
|
97
|
+
</RadioGroup>
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
100
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
[data-fs-bp-settings-drawer] {
|
|
2
|
+
@import "@faststore/ui/src/components/atoms/Radio/styles.scss";
|
|
3
|
+
|
|
4
|
+
[data-fs-bp-settings-drawer-body] {
|
|
5
|
+
color: #1f1f1f;
|
|
6
|
+
font-size: var(--fs-text-size-1);
|
|
7
|
+
|
|
8
|
+
[data-fs-bp-settings-drawer-subtitle] {
|
|
9
|
+
margin-bottom: var(--fs-spacing-5);
|
|
10
|
+
color: #1f1f1f;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
[data-fs-bp-settings-drawer-list-type] {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
margin-bottom: var(--fs-spacing-4);
|
|
17
|
+
|
|
18
|
+
h4[data-fs-bp-settings-drawer-list-type-title] {
|
|
19
|
+
color: #000000;
|
|
20
|
+
font-weight: var(--fs-text-weight-semibold);
|
|
21
|
+
font-size: var(--fs-text-size-1);
|
|
22
|
+
line-height: 1.25rem;
|
|
23
|
+
letter-spacing: -0.01em;
|
|
24
|
+
margin-bottom: var(--fs-spacing-4);
|
|
25
|
+
margin-top: 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
[data-fs-bp-settings-drawer-list-type-option] {
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
margin-bottom: var(--fs-spacing-4);
|
|
32
|
+
|
|
33
|
+
&:last-child {
|
|
34
|
+
margin-bottom: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
[data-fs-radio-group-option] {
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: flex-start;
|
|
40
|
+
gap: var(--fs-spacing-2);
|
|
41
|
+
|
|
42
|
+
label {
|
|
43
|
+
font-weight: var(--fs-text-weight-regular);
|
|
44
|
+
font-size: var(--fs-text-size-1);
|
|
45
|
+
color: #1f1f1f;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
[data-fs-bp-settings-drawer-list-type-description] {
|
|
50
|
+
margin-left: var(--fs-spacing-5);
|
|
51
|
+
margin-bottom: 0;
|
|
52
|
+
color: #707070;
|
|
53
|
+
font-weight: var(--fs-text-weight-regular);
|
|
54
|
+
font-size: var(--fs-bp-text-size-0);
|
|
55
|
+
line-height: var(--fs-bp-text-size-2);
|
|
56
|
+
letter-spacing: 0;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -7,6 +7,13 @@ export {
|
|
|
7
7
|
export { useAutocompletePosition } from "./AutocompleteDropdown/useAutocompletePosition";
|
|
8
8
|
export { BasicCard, type BasicCardProps } from "./BasicCard/BasicCard";
|
|
9
9
|
export { BasicDrawer, type BasicDrawerProps } from "./BasicDrawer/BasicDrawer";
|
|
10
|
+
export {
|
|
11
|
+
SettingsDrawer,
|
|
12
|
+
type SettingsDrawerProps,
|
|
13
|
+
type ListTypeOption,
|
|
14
|
+
type SettingsDrawerListTypeProps,
|
|
15
|
+
DEFAULT_LIST_TYPE_OPTIONS,
|
|
16
|
+
} from "./SettingsDrawer/SettingsDrawer";
|
|
10
17
|
export {
|
|
11
18
|
BasicDropdownMenu,
|
|
12
19
|
type BasicDropdownMenuProps,
|
|
@@ -15,3 +15,5 @@ export { useRouterLoading } from "./useRouterLoading";
|
|
|
15
15
|
export { useLogger } from "./useLogger";
|
|
16
16
|
export { useGetDependenciesVersion } from "./useGetDependenciesVersion";
|
|
17
17
|
export { useAnalytics } from "./analytics/useAnalytics";
|
|
18
|
+
export { useGetScopeConfig, SCOPE_KEYS } from "./useGetScopeConfig";
|
|
19
|
+
export { useSetScopeConfig } from "./useSetScopeConfig";
|