@vtex/faststore-plugin-buyer-portal 1.3.13 → 1.3.15

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,8 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.3.15] - 2025-11-03
11
+
12
+ ### Added
13
+
14
+ - Disable default button for inactive credit card
15
+
16
+ ## [1.3.14] - 2025-11-03
17
+
18
+ ### Fixed
19
+
20
+ - Click outside on Dropdown are now properly closing the dropdown on Budget allocation selection
21
+
10
22
  ## [1.3.13] - 2025-11-03
11
23
 
24
+ ### Fixed
25
+
12
26
  - Setup OTLP to send log events on error boundary
13
27
 
14
28
  ## [1.3.12] - 2025-10-30
@@ -175,7 +189,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
175
189
  - Add CHANGELOG file
176
190
  - Add README file
177
191
 
178
- [unreleased]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.13...HEAD
192
+ [unreleased]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.15...HEAD
179
193
  [1.2.3]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.2.2...1.2.3
180
194
  [1.2.3]: https://github.com/vtex/faststore-plugin-buyer-portal/releases/tag/1.2.3
181
195
  [1.2.4]: https://github.com/vtex/faststore-plugin-buyer-portal/releases/tag/1.2.4
@@ -190,6 +204,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
190
204
 
191
205
  # <<<<<<< HEAD
192
206
 
207
+ [1.3.15]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.14...v1.3.15
208
+ [1.3.14]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.13...v1.3.14
193
209
  [1.3.13]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.12...v1.3.13
194
210
  [1.3.12]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.11...v1.3.12
195
211
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/faststore-plugin-buyer-portal",
3
- "version": "1.3.13",
3
+ "version": "1.3.15",
4
4
  "description": "A plugin for faststore with buyer portal",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef } from "react";
1
+ import { useEffect, useRef, useState } from "react";
2
2
 
3
3
  import {
4
4
  Checkbox,
@@ -16,6 +16,7 @@ import { getTableColumns } from "../../../shared/components/Table/utils/tableCol
16
16
  import { useBuyerPortal } from "../../../shared/hooks";
17
17
  import { IPagination } from "../../../shared/types";
18
18
  import { Dictionary } from "../../../shared/utils";
19
+ import { useClickOutside } from "../../hooks";
19
20
 
20
21
  import type { BudgetAllocationsSelectionDataType } from "../../types";
21
22
 
@@ -48,12 +49,19 @@ export const BudgetAllocationsSelection = ({
48
49
  onSortChange,
49
50
  setFilter,
50
51
  }: BudgetAllocationsSelectionProps) => {
52
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
53
+
51
54
  const { currentContract: contract } = useBuyerPortal();
55
+
52
56
  const options = Object.keys(sortingOptions);
53
57
 
54
58
  const svgProps = { width: 10, height: 10 };
55
59
  const selectAllRef = useRef<HTMLInputElement>(null);
56
60
 
61
+ const dropdownRef = useClickOutside<HTMLDivElement>(() => {
62
+ setIsDropdownOpen(false);
63
+ });
64
+
57
65
  const updateCurrentSort = (newSort: string) => {
58
66
  onSortChange(newSort);
59
67
  };
@@ -155,8 +163,11 @@ export const BudgetAllocationsSelection = ({
155
163
  return (
156
164
  <div data-fs-bp-budget-allocation-table>
157
165
  <div data-fs-bp-budget-allocation-wrapper>
158
- <Dropdown>
159
- <DropdownButton data-fs-bp-budget-allocation-select-current>
166
+ <Dropdown isOpen={isDropdownOpen}>
167
+ <DropdownButton
168
+ data-fs-bp-budget-allocation-select-current
169
+ onClick={() => setIsDropdownOpen((prev) => !prev)}
170
+ >
160
171
  {currentSort}
161
172
  <Icon
162
173
  name="CaretRight"
@@ -166,21 +177,27 @@ export const BudgetAllocationsSelection = ({
166
177
  />
167
178
  </DropdownButton>
168
179
  <DropdownMenu align="left">
169
- {options.map((option) => (
170
- <DropdownItem
171
- key={option}
172
- onClick={() => updateCurrentSort(option)}
173
- data-fs-bp-budget-allocation-select-item
174
- data-fs-bp-budget-allocation-selected={currentSort === option}
175
- >
176
- <div data-fs-bp-budget-allocation-selected-wrapper>
177
- <span>{option}</span>
178
- {currentSort === option && (
179
- <Icon name="Check" width={16} height={16} />
180
- )}
181
- </div>
182
- </DropdownItem>
183
- ))}
180
+ <div ref={dropdownRef}>
181
+ {options.map((option) => (
182
+ <DropdownItem
183
+ key={option}
184
+ onClick={(e) => {
185
+ e.stopPropagation();
186
+ updateCurrentSort(option);
187
+ setIsDropdownOpen(false);
188
+ }}
189
+ data-fs-bp-budget-allocation-select-item
190
+ data-fs-bp-budget-allocation-selected={currentSort === option}
191
+ >
192
+ <div data-fs-bp-budget-allocation-selected-wrapper>
193
+ <span>{option}</span>
194
+ {currentSort === option && (
195
+ <Icon name="Check" width={16} height={16} />
196
+ )}
197
+ </div>
198
+ </DropdownItem>
199
+ ))}
200
+ </div>
184
201
  </DropdownMenu>
185
202
  </Dropdown>
186
203
 
@@ -137,5 +137,6 @@
137
137
  align-items: center;
138
138
  justify-content: space-between;
139
139
  width: 100%;
140
+ gap: var(--fs-spacing-2);
140
141
  }
141
142
  }
@@ -8,3 +8,4 @@ export { useListBudgets } from "./useListBudgets";
8
8
  export { useUpdateBudget } from "./useUpdateBudget";
9
9
  export { useListUsers } from "./useListUsers";
10
10
  export { useListAddresses } from "./useListAddressess";
11
+ export { useClickOutside } from "./useClickOutside";
@@ -0,0 +1,26 @@
1
+ import { RefObject, useEffect, useRef } from "react";
2
+
3
+ export function useClickOutside<T extends HTMLElement>(
4
+ callback: () => void
5
+ ): RefObject<T> {
6
+ const ref = useRef<T>(null);
7
+ const callbackRef = useRef(callback);
8
+
9
+ // Update callbackRef to always hold the latest callback
10
+ useEffect(() => {
11
+ callbackRef.current = callback;
12
+ }, [callback]);
13
+
14
+ useEffect(() => {
15
+ const handleClick = (event: Event) => {
16
+ if (ref.current && !ref.current.contains(event.target as Node)) {
17
+ callbackRef.current();
18
+ }
19
+ };
20
+
21
+ document.addEventListener("click", handleClick, true);
22
+ return () => document.removeEventListener("click", handleClick, true);
23
+ }, []);
24
+
25
+ return ref;
26
+ }
@@ -114,17 +114,18 @@ export const CreditCardDropdownMenu = ({
114
114
  Rename
115
115
  </DropdownItem> */}
116
116
 
117
- {currentCreditCard.isDefault ? (
118
- <DropdownItem onClick={handleUnsetAsDefault}>
119
- <Icon name="BookmarkRemove" {...sizeProps} />
120
- Unset as default
121
- </DropdownItem>
122
- ) : (
123
- <DropdownItem onClick={handleSetAsDefault}>
124
- <Icon name="BookmarkAdd" {...sizeProps} />
125
- Set as default
126
- </DropdownItem>
127
- )}
117
+ {currentCreditCard.isActive &&
118
+ (currentCreditCard.isDefault ? (
119
+ <DropdownItem onClick={handleUnsetAsDefault}>
120
+ <Icon name="BookmarkRemove" {...sizeProps} />
121
+ Unset as default
122
+ </DropdownItem>
123
+ ) : (
124
+ <DropdownItem onClick={handleSetAsDefault}>
125
+ <Icon name="BookmarkAdd" {...sizeProps} />
126
+ Set as default
127
+ </DropdownItem>
128
+ ))}
128
129
 
129
130
  {/* Precisamos controlar scope com um toggle pra credit card devido a suas particularidades */}
130
131
  {/* <DropdownItem onClick={openRemoveDrawer}>
@@ -134,7 +135,7 @@ export const CreditCardDropdownMenu = ({
134
135
  {
135
136
  // isRootLevelOrgUnit && ( TODO: Put again when we validate the delete rule
136
137
  <>
137
- <BasicDropdownMenu.Separator />
138
+ {currentCreditCard.isActive && <BasicDropdownMenu.Separator />}
138
139
 
139
140
  <DropdownItem
140
141
  onClick={openDeleteDrawer}
@@ -97,7 +97,14 @@ export const CreditCardLayout = ({ data }: CreditCardsLayoutProps) => {
97
97
  aria-label="is contract active"
98
98
  defaultChecked={creditCard.isActive}
99
99
  onChange={(event) => {
100
+ updateItemsFromRefetch(
101
+ creditCards.map((c) =>
102
+ c === creditCard ? { ...c, isActive: !c.isActive } : c
103
+ )
104
+ );
105
+
100
106
  creditCard.isActive = !creditCard.isActive;
107
+
101
108
  handleCardChangeStatus(
102
109
  event,
103
110
  creditCard.accountId,
@@ -62,7 +62,7 @@ export const CustomFieldsLayout = ({
62
62
  const lastSearchValue = useRef(filter.search);
63
63
  const contractId = contract?.id ?? "";
64
64
  const unitId = orgUnit?.id ?? "";
65
- const cookie = clientContext.cookie;
65
+ const cookie = clientContext?.cookie ?? "";
66
66
  const debouncedSearchValue = useDebounce(filter.search, 500);
67
67
 
68
68
  useEffect(() => {
@@ -26,13 +26,13 @@ export type UsePageItemsProps<T> = {
26
26
  };
27
27
 
28
28
  export const usePageItems = <T>({
29
- initialItems,
29
+ initialItems = [],
30
30
  search,
31
31
  page = 1,
32
32
  searchParam = SEARCH_PARAMS.DEFAULT,
33
33
  pageParam = PAGE_PARAMS.DEFAULT,
34
34
  }: UsePageItemsProps<T>) => {
35
- const [items, setItems] = useState<T[]>(initialItems ?? []);
35
+ const [items, setItems] = useState<T[]>(initialItems);
36
36
  const [total, setTotal] = useState<number>(initialItems.length);
37
37
  const [searchTerm, setSearchTerm] = useState(search ?? "");
38
38
  const [isLoading, setIsLoading] = useState(false);
@@ -13,4 +13,4 @@ export const LOCAL_STORAGE_LOCATION_EDIT_KEY = "bp_hide_edit_location_confirm";
13
13
  export const LOCAL_STORAGE_RECIPIENT_EDIT_KEY =
14
14
  "bp_hide_edit_recipient_confirm";
15
15
 
16
- export const CURRENT_VERSION = "1.3.13";
16
+ export const CURRENT_VERSION = "1.3.15";