@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 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.66...HEAD
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/faststore-plugin-buyer-portal",
3
- "version": "1.3.66",
3
+ "version": "1.3.67",
4
4
  "description": "A plugin for faststore with buyer portal",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -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/paginated`,
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, filterByScope, page } = args;
45
+ const { contractId, cookie, name, unitId, page } = args;
47
46
 
48
47
  return this.get<GetProductAssortmentFromContractResponse>(
49
- `customers/${contractId}/units/${unitId}/collections/paginated`,
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
- ProductAssortmentSummary,
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
- ProductAssortmentSummary[]
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: selectedAssortment.map((s) => ({ name: s.name })),
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 && `(${selectedAssortment.length})`}
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>
@@ -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 { ProductAssortmentSummary } from "../../types";
14
+ import type { ProductAssortmentWithAdditionalInformation } from "../../types";
15
15
 
16
16
  interface AddProductAssortmentDrawerTableProps {
17
17
  loading?: boolean;
18
- data: ProductAssortmentSummary[];
19
- onChange: Dispatch<SetStateAction<ProductAssortmentSummary[]>>;
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 [selectedIds, setSelectedIds] = useState<string[]>([]);
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 allIds = useMemo(() => data.map((item) => item.id), [data]);
30
- const allSelected = selectedIds.length === data.length && data.length > 0;
31
- const partiallySelected = selectedIds.length > 0 && !allSelected;
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 ? [] : allIds;
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, allIds, data, onChange]);
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
- onChange={() => handleSelect(option.id)}
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 { getProductAssortmentFromScopeService } from "../services/get-product-assortment-from-scope.service";
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 getProductAssortmentFromScopeService>
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
- getProductAssortmentFromScopeService({
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
  },
@@ -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";
@@ -22,4 +22,4 @@ export const SCOPE_KEYS = {
22
22
  CREDIT_CARDS: "creditCards",
23
23
  } as const;
24
24
 
25
- export const CURRENT_VERSION = "1.3.66";
25
+ export const CURRENT_VERSION = "1.3.67";