@vtex/faststore-plugin-buyer-portal 1.3.66 → 1.3.67
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 +10 -1
- package/package.json +1 -1
- package/src/features/product-assortment/clients/ProductAssortmentClient.ts +3 -5
- package/src/features/product-assortment/components/AddProductAssortmentDrawer/AddProductAssortmentDrawer.tsx +13 -6
- package/src/features/product-assortment/components/table/AddProductAssortmentDrawerTable.tsx +29 -11
- package/src/features/product-assortment/hooks/useGetProductAssortment.ts +4 -7
- package/src/features/product-assortment/layouts/ProductAssortmentLayout/ProductAssortmentLayout.tsx +1 -1
- package/src/features/product-assortment/services/get-product-assortment-attached.service.ts +32 -0
- package/src/features/product-assortment/services/index.ts +5 -0
- package/src/features/shared/utils/constants.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.3.67] - 2026-03-05
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Product Assortment table list now uses `collections/attached` endpoint
|
|
15
|
+
- Product Assortment drawer listing now uses `collections/available` endpoint
|
|
16
|
+
- Product Assortment drawer now shows already attached collections as selected and disabled
|
|
17
|
+
|
|
10
18
|
## [1.3.66] - 2026-02-13
|
|
11
19
|
|
|
12
20
|
### Fixed
|
|
@@ -487,7 +495,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
487
495
|
- Add CHANGELOG file
|
|
488
496
|
- Add README file
|
|
489
497
|
|
|
490
|
-
[unreleased]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.
|
|
498
|
+
[unreleased]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.67...HEAD
|
|
491
499
|
[1.3.55]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.54...v1.3.55
|
|
492
500
|
[1.3.54]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.53...v1.3.54
|
|
493
501
|
[1.3.53]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.52...v1.3.53
|
|
@@ -550,6 +558,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
550
558
|
[1.3.60]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.59...v1.3.60
|
|
551
559
|
[1.3.59]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.58...v1.3.59
|
|
552
560
|
[1.3.58]: https://github.com/vtex/faststore-plugin-buyer-portal/releases/tag/1.3.58
|
|
561
|
+
[1.3.67]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.66...v1.3.67
|
|
553
562
|
[1.3.66]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.65...v1.3.66
|
|
554
563
|
[1.3.65]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.64...v1.3.65
|
|
555
564
|
[1.3.64]: https://github.com/vtex/faststore-plugin-buyer-portal/releases/tag/1.3.64
|
package/package.json
CHANGED
|
@@ -24,7 +24,7 @@ export class ProductAssortmentClient extends Client {
|
|
|
24
24
|
const { contractId, cookie, name, unitId, page } = args;
|
|
25
25
|
|
|
26
26
|
return this.get<GetProductAssortmentFromContractResponse>(
|
|
27
|
-
`customers/${contractId}/units/${unitId}/collections/
|
|
27
|
+
`customers/${contractId}/units/${unitId}/collections/attached`,
|
|
28
28
|
{
|
|
29
29
|
headers: { Cookie: cookie },
|
|
30
30
|
params: {
|
|
@@ -40,19 +40,17 @@ export class ProductAssortmentClient extends Client {
|
|
|
40
40
|
unitId: string;
|
|
41
41
|
name?: string;
|
|
42
42
|
page: number;
|
|
43
|
-
filterByScope: boolean;
|
|
44
43
|
}
|
|
45
44
|
) {
|
|
46
|
-
const { contractId, cookie, name, unitId,
|
|
45
|
+
const { contractId, cookie, name, unitId, page } = args;
|
|
47
46
|
|
|
48
47
|
return this.get<GetProductAssortmentFromContractResponse>(
|
|
49
|
-
`customers/${contractId}/units/${unitId}/collections/
|
|
48
|
+
`customers/${contractId}/units/${unitId}/collections/available`,
|
|
50
49
|
{
|
|
51
50
|
headers: { Cookie: cookie },
|
|
52
51
|
params: {
|
|
53
52
|
...(name ? { name } : undefined),
|
|
54
53
|
page,
|
|
55
|
-
filterByScope,
|
|
56
54
|
v: new Date().getTime(),
|
|
57
55
|
},
|
|
58
56
|
}
|
|
@@ -18,7 +18,7 @@ import { AddProductAssortmentDrawerTable } from "../table/AddProductAssortmentDr
|
|
|
18
18
|
|
|
19
19
|
import type {
|
|
20
20
|
AddProductAssortmentDrawerProps,
|
|
21
|
-
|
|
21
|
+
ProductAssortmentWithAdditionalInformation,
|
|
22
22
|
} from "../../types";
|
|
23
23
|
|
|
24
24
|
export const AddProductAssortmentDrawer = ({
|
|
@@ -35,7 +35,6 @@ export const AddProductAssortmentDrawer = ({
|
|
|
35
35
|
useGetProductAssorments({
|
|
36
36
|
contractId: currentContract?.id ?? "",
|
|
37
37
|
unitId: currentOrgUnit?.id ?? "",
|
|
38
|
-
filterByScope: false,
|
|
39
38
|
page: drawerPage,
|
|
40
39
|
name: drawerSearch,
|
|
41
40
|
});
|
|
@@ -65,14 +64,21 @@ export const AddProductAssortmentDrawer = ({
|
|
|
65
64
|
const addProductAssortmentMutation = useAddProductAssortmentToScope();
|
|
66
65
|
|
|
67
66
|
const [selectedAssortment, setSelectedAssortment] = useState<
|
|
68
|
-
|
|
67
|
+
ProductAssortmentWithAdditionalInformation[]
|
|
69
68
|
>([]);
|
|
70
69
|
|
|
71
70
|
const handleSuccess = async () => {
|
|
71
|
+
const itemsToAdd = selectedAssortment.filter((s) => !s.isEnabled);
|
|
72
|
+
|
|
73
|
+
if (itemsToAdd.length === 0) {
|
|
74
|
+
close();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
72
78
|
await addProductAssortmentMutation.mutate({
|
|
73
79
|
unitId: unitId ?? "",
|
|
74
80
|
contractId: contractId ?? "",
|
|
75
|
-
data:
|
|
81
|
+
data: itemsToAdd.map((s) => ({ name: s.name })),
|
|
76
82
|
});
|
|
77
83
|
|
|
78
84
|
pushToast({
|
|
@@ -177,12 +183,13 @@ export const AddProductAssortmentDrawer = ({
|
|
|
177
183
|
</BasicDrawer.Button>
|
|
178
184
|
<BasicDrawer.Button
|
|
179
185
|
variant="confirm"
|
|
180
|
-
disabled={selectedAssortment.length === 0}
|
|
186
|
+
disabled={selectedAssortment.filter((s) => !s.isEnabled).length === 0}
|
|
181
187
|
onClick={handleSuccess}
|
|
182
188
|
isLoading={addProductAssortmentMutation.isLoading}
|
|
183
189
|
>
|
|
184
190
|
Add
|
|
185
|
-
{selectedAssortment.length > 0 &&
|
|
191
|
+
{selectedAssortment.filter((s) => !s.isEnabled).length > 0 &&
|
|
192
|
+
`(${selectedAssortment.filter((s) => !s.isEnabled).length})`}
|
|
186
193
|
</BasicDrawer.Button>
|
|
187
194
|
</BasicDrawer.Footer>
|
|
188
195
|
</BasicDrawer>
|
package/src/features/product-assortment/components/table/AddProductAssortmentDrawerTable.tsx
CHANGED
|
@@ -11,12 +11,14 @@ import { Checkbox } from "@faststore/ui";
|
|
|
11
11
|
import { Table } from "../../../shared/components";
|
|
12
12
|
|
|
13
13
|
import type { TableColumn } from "../../../shared/components/Table/TableHead/TableHead";
|
|
14
|
-
import type {
|
|
14
|
+
import type { ProductAssortmentWithAdditionalInformation } from "../../types";
|
|
15
15
|
|
|
16
16
|
interface AddProductAssortmentDrawerTableProps {
|
|
17
17
|
loading?: boolean;
|
|
18
|
-
data:
|
|
19
|
-
onChange: Dispatch<
|
|
18
|
+
data: ProductAssortmentWithAdditionalInformation[];
|
|
19
|
+
onChange: Dispatch<
|
|
20
|
+
SetStateAction<ProductAssortmentWithAdditionalInformation[]>
|
|
21
|
+
>;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export const AddProductAssortmentDrawerTable = ({
|
|
@@ -24,14 +26,27 @@ export const AddProductAssortmentDrawerTable = ({
|
|
|
24
26
|
loading,
|
|
25
27
|
onChange,
|
|
26
28
|
}: AddProductAssortmentDrawerTableProps) => {
|
|
27
|
-
const
|
|
29
|
+
const enabledIds = useMemo(
|
|
30
|
+
() => data.filter((item) => item.isEnabled).map((item) => item.id),
|
|
31
|
+
[data]
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const [selectedIds, setSelectedIds] = useState<string[]>(enabledIds);
|
|
28
35
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
const selectableIds = useMemo(
|
|
37
|
+
() => data.filter((item) => !item.isEnabled).map((item) => item.id),
|
|
38
|
+
[data]
|
|
39
|
+
);
|
|
40
|
+
const allSelected =
|
|
41
|
+
selectableIds.every((id) => selectedIds.includes(id)) &&
|
|
42
|
+
selectableIds.length > 0;
|
|
43
|
+
const partiallySelected =
|
|
44
|
+
selectedIds.some((id) => selectableIds.includes(id)) && !allSelected;
|
|
32
45
|
|
|
33
46
|
const handleSelect = useCallback(
|
|
34
|
-
(id: string) => {
|
|
47
|
+
(id: string, isEnabled: boolean) => {
|
|
48
|
+
if (isEnabled) return;
|
|
49
|
+
|
|
35
50
|
const newSelectedIds = selectedIds.includes(id)
|
|
36
51
|
? selectedIds.filter((item) => item !== id)
|
|
37
52
|
: [...selectedIds, id];
|
|
@@ -44,11 +59,13 @@ export const AddProductAssortmentDrawerTable = ({
|
|
|
44
59
|
);
|
|
45
60
|
|
|
46
61
|
const handleSelectAll = useCallback(() => {
|
|
47
|
-
const newSelectedIds = allSelected
|
|
62
|
+
const newSelectedIds = allSelected
|
|
63
|
+
? enabledIds
|
|
64
|
+
: [...selectableIds, ...enabledIds];
|
|
48
65
|
setSelectedIds(newSelectedIds);
|
|
49
66
|
const selectedItems = data.filter((d) => newSelectedIds.includes(d.id));
|
|
50
67
|
onChange(selectedItems);
|
|
51
|
-
}, [allSelected,
|
|
68
|
+
}, [allSelected, selectableIds, enabledIds, data, onChange]);
|
|
52
69
|
|
|
53
70
|
const columns: TableColumn[] = [
|
|
54
71
|
{
|
|
@@ -92,7 +109,8 @@ export const AddProductAssortmentDrawerTable = ({
|
|
|
92
109
|
<Checkbox
|
|
93
110
|
data-fs-bp-product-assortment-checkbox
|
|
94
111
|
checked={selectedIds.includes(option.id)}
|
|
95
|
-
|
|
112
|
+
disabled={option.isEnabled}
|
|
113
|
+
onChange={() => handleSelect(option.id, option.isEnabled)}
|
|
96
114
|
/>
|
|
97
115
|
</Table.Cell>
|
|
98
116
|
}
|
|
@@ -1,32 +1,29 @@
|
|
|
1
1
|
import { type QueryOptions, useQuery } from "../../shared/hooks";
|
|
2
|
-
import {
|
|
2
|
+
import { getProductAssortmentAttachedService } from "../services/get-product-assortment-attached.service";
|
|
3
3
|
|
|
4
4
|
export const useGetProductAssortment = ({
|
|
5
5
|
contractId,
|
|
6
6
|
orgUnitId,
|
|
7
7
|
search = "",
|
|
8
|
-
filterByScope = false,
|
|
9
8
|
page = 1,
|
|
10
9
|
options,
|
|
11
10
|
}: {
|
|
12
11
|
contractId: string;
|
|
13
12
|
orgUnitId: string;
|
|
14
|
-
filterByScope?: boolean;
|
|
15
13
|
search?: string;
|
|
16
14
|
page?: number;
|
|
17
15
|
options?: QueryOptions<
|
|
18
|
-
AwaitedType<typeof
|
|
16
|
+
AwaitedType<typeof getProductAssortmentAttachedService>
|
|
19
17
|
>;
|
|
20
18
|
}) => {
|
|
21
19
|
const { data, error, isLoading, refetch } = useQuery(
|
|
22
|
-
`customers/${contractId}/units/${orgUnitId}/collections`,
|
|
20
|
+
`customers/${contractId}/units/${orgUnitId}/collections/attached`,
|
|
23
21
|
({ cookie }) =>
|
|
24
|
-
|
|
22
|
+
getProductAssortmentAttachedService({
|
|
25
23
|
args: {
|
|
26
24
|
cookie,
|
|
27
25
|
contractId,
|
|
28
26
|
unitId: orgUnitId,
|
|
29
|
-
filterByScope,
|
|
30
27
|
name: search,
|
|
31
28
|
page,
|
|
32
29
|
},
|
package/src/features/product-assortment/layouts/ProductAssortmentLayout/ProductAssortmentLayout.tsx
CHANGED
|
@@ -60,12 +60,12 @@ export const ProductAssortmentLayout = ({
|
|
|
60
60
|
contractId,
|
|
61
61
|
orgUnitId,
|
|
62
62
|
});
|
|
63
|
+
|
|
63
64
|
const {
|
|
64
65
|
data: initialProductAssortment,
|
|
65
66
|
isProductAssortmentLoading,
|
|
66
67
|
refetchProductAssortment,
|
|
67
68
|
} = useGetProductAssortment({
|
|
68
|
-
filterByScope: true,
|
|
69
69
|
contractId,
|
|
70
70
|
orgUnitId,
|
|
71
71
|
search,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { isRightFormat } from "../../shared/utils/isRightFormat";
|
|
2
|
+
import { productAssortmentClient } from "../clients/ProductAssortmentClient";
|
|
3
|
+
import { GetProductAssortmentFromContractResponse } from "../types";
|
|
4
|
+
|
|
5
|
+
export interface GetProductAssortmentAttachedServiceProps {
|
|
6
|
+
args: Parameters<
|
|
7
|
+
typeof productAssortmentClient.getProductAssortmentsInfoInContract
|
|
8
|
+
>[0];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const getProductAssortmentAttachedService = async ({
|
|
12
|
+
args,
|
|
13
|
+
}: GetProductAssortmentAttachedServiceProps) => {
|
|
14
|
+
try {
|
|
15
|
+
const data =
|
|
16
|
+
await productAssortmentClient.getProductAssortmentsInfoInContract(args);
|
|
17
|
+
|
|
18
|
+
return data;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
if (error instanceof Error) {
|
|
21
|
+
const err = JSON.parse(error.message) as unknown;
|
|
22
|
+
if (
|
|
23
|
+
isRightFormat(err) &&
|
|
24
|
+
err.message.startsWith("No Product assortment found for the name")
|
|
25
|
+
) {
|
|
26
|
+
return {} as GetProductAssortmentFromContractResponse;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -2,3 +2,8 @@ export {
|
|
|
2
2
|
getProductAssortmentFromScopeService,
|
|
3
3
|
type GetProductAssortmentFromScopeServiceProps,
|
|
4
4
|
} from "./get-product-assortment-from-scope.service";
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
getProductAssortmentAttachedService,
|
|
8
|
+
type GetProductAssortmentAttachedServiceProps,
|
|
9
|
+
} from "./get-product-assortment-attached.service";
|