@vtex/faststore-plugin-buyer-portal 1.1.86 → 1.1.88

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +39 -28
  2. package/package.json +1 -1
  3. package/src/features/addresses/components/AddressForm/AddressForm.tsx +72 -41
  4. package/src/features/addresses/data/USA.ts +69 -64
  5. package/src/features/addresses/data/countries.ts +6 -1
  6. package/src/features/addresses/data/states.ts +4 -2
  7. package/src/features/addresses/layouts/AddressDetailsLayout/AddressDetailsLayout.tsx +10 -1
  8. package/src/features/addresses/utils/index.ts +1 -0
  9. package/src/features/addresses/utils/stateUtils.ts +63 -0
  10. package/src/features/budgets/components/BudgetAddForm/budget-add-form.scss +9 -3
  11. package/src/features/budgets/components/BudgetAllocationsSelection/budget-allocations-selection.scss +2 -2
  12. package/src/features/budgets/components/BudgetAllocationsTable/budget-allocations-table.scss +29 -0
  13. package/src/features/budgets/components/BudgetDeleteDrawer/budget-delete-drawer.scss +13 -0
  14. package/src/features/budgets/components/BudgetRemainingBalance/BudgetRemainingBalance.tsx +5 -1
  15. package/src/features/budgets/components/BudgetRemainingBalance/budget-remaining-balance.scss +18 -1
  16. package/src/features/budgets/components/BudgetSettingsInfo/budget-settings-info.scss +19 -0
  17. package/src/features/budgets/components/BudgetsTable/BudgetsTable.tsx +12 -2
  18. package/src/features/budgets/components/BudgetsTable/budgets-table.scss +30 -1
  19. package/src/features/budgets/components/CreateBudgetAllocationDrawer/create-budget-allocation-drawer.scss +22 -6
  20. package/src/features/budgets/components/CreateBudgetDrawer/create-budget-drawer.scss +15 -6
  21. package/src/features/budgets/components/DeleteBudgetAllocationDrawer/delete-budget-allocations.scss +15 -1
  22. package/src/features/budgets/components/EditBudgetDrawer/edit-budget-drawer.scss +11 -1
  23. package/src/features/budgets/layouts/BudgetsDetailsLayout/BudgetsDetailsLayout.tsx +76 -75
  24. package/src/features/budgets/layouts/BudgetsDetailsLayout/budget-details-layout.scss +22 -19
  25. package/src/features/budgets/layouts/BudgetsLayout/budgets-layout.scss +6 -0
  26. package/src/features/buying-policies/components/BasicBuyingPolicyDrawer/basic-buying-policy-drawer.scss +4 -0
  27. package/src/features/buying-policies/layouts/BuyingPoliciesLayout/buying-policies-layout.scss +41 -6
  28. package/src/features/buying-policies/layouts/BuyingPolicyDetailsLayout/BuyingPolicyDetailsLayout.tsx +1 -1
  29. package/src/features/buying-policies/layouts/BuyingPolicyDetailsLayout/buying-policy-details-layout.scss +17 -1
  30. package/src/features/custom-fields/layouts/CustomFieldsLayout/custom-fields-layout.scss +4 -0
  31. package/src/features/payment-methods/components/AddPaymentMethodsDrawer/AddPaymentMethodsDrawer.tsx +93 -68
  32. package/src/features/payment-methods/components/AddPaymentMethodsDrawer/add-payment-methods-drawer.scss +66 -30
  33. package/src/features/payment-methods/components/SearchPaymentMethods/SearchPaymentMethods.tsx +6 -4
  34. package/src/features/payment-methods/components/SearchPaymentMethods/search-payment-methods.scss +4 -1
  35. package/src/features/payment-methods/layouts/PaymentMethodsLayout/PaymentMethodsLayout.tsx +65 -54
  36. package/src/features/payment-methods/layouts/PaymentMethodsLayout/payment-methods-layout.scss +121 -103
  37. package/src/features/shared/components/CustomDropdown/custom-dropdown.scss +5 -0
  38. package/src/features/shared/components/HeaderInside/header-inside.scss +1 -1
  39. package/src/features/shared/components/Pagination/Pagination.tsx +18 -8
  40. package/src/features/shared/components/Pagination/pagination.scss +14 -0
  41. package/src/features/shared/layouts/BaseTabsLayout/base-tabs-layout.scss +6 -1
  42. package/src/features/shared/layouts/BaseTabsLayout/sidebar-drawer/sidebar-drawer.scss +5 -3
  43. package/src/features/shared/layouts/CustomFieldLayout/CustomFieldLayout.tsx +1 -0
  44. package/src/features/shared/layouts/CustomFieldLayout/custom-field-layout.scss +28 -2
@@ -1,12 +1,13 @@
1
- import { useState, useRef, useEffect, useMemo, useCallback } from "react";
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
2
 
3
3
  import { useRouter } from "next/router";
4
4
 
5
- import { useUI, Checkbox, Skeleton } from "@faststore/ui";
5
+ import { Checkbox, Skeleton, useUI } from "@faststore/ui";
6
6
 
7
7
  import {
8
8
  type BasicDrawerProps,
9
9
  BasicDrawer,
10
+ EmptyState,
10
11
  Icon,
11
12
  } from "../../../shared/components";
12
13
  import { useBuyerPortal } from "../../../shared/hooks";
@@ -49,8 +50,9 @@ export const AddPaymentMethodsDrawer = ({
49
50
  search: querySearch,
50
51
  });
51
52
 
52
- const availableMethods = paymentMethods?.filter(
53
- (method) => !method?.isEnabled
53
+ const availableMethods = useMemo(
54
+ () => (paymentMethods ?? []).filter((method) => !method?.isEnabled),
55
+ [paymentMethods]
54
56
  );
55
57
 
56
58
  const handleSuccess = () => {
@@ -95,13 +97,10 @@ export const AddPaymentMethodsDrawer = ({
95
97
 
96
98
  const toggleItem = useCallback((id: number) => {
97
99
  setSelectedMethods((prev) => {
98
- const newSet = new Set(prev);
99
- if (newSet.has(id)) {
100
- newSet.delete(id);
101
- } else {
102
- newSet.add(id);
103
- }
104
- return newSet;
100
+ const next = new Set(prev);
101
+ if (next.has(id)) next.delete(id);
102
+ else next.add(id);
103
+ return next;
105
104
  });
106
105
  }, []);
107
106
 
@@ -116,6 +115,86 @@ export const AddPaymentMethodsDrawer = ({
116
115
  addPaymentMethods({ customerId, unitId, paymentMethodsIds });
117
116
  };
118
117
 
118
+ const renderListHeader = () => (
119
+ <li
120
+ data-fs-bp-payment-methods-list-title
121
+ data-fs-bp-payment-methods-list-title-drawer
122
+ aria-label="Payment methods header"
123
+ >
124
+ <Checkbox
125
+ data-fs-bp-payment-methods-checkbox
126
+ ref={selectAllRef}
127
+ checked={allSelected}
128
+ onChange={toggleAll}
129
+ disabled={readonly || availableMethods.length === 0}
130
+ aria-label="Select all payment methods"
131
+ />
132
+ Name
133
+ </li>
134
+ );
135
+
136
+ const renderList = () => (
137
+ <ul data-fs-payment-methods-list>
138
+ {renderListHeader()}
139
+ {availableMethods.map(({ id, name }) => (
140
+ <li key={id} data-fs-payment-methods-line>
141
+ <div
142
+ data-fs-payment-methods-row
143
+ data-fs-payment-methods-row-selected={selectedMethods.has(id)}
144
+ >
145
+ <div data-fs-payment-methods-row-information>
146
+ <Checkbox
147
+ data-fs-bp-payment-methods-checkbox
148
+ checked={selectedMethods.has(id)}
149
+ onChange={() => toggleItem(id)}
150
+ disabled={readonly}
151
+ aria-label={`Select ${name}`}
152
+ />
153
+ <span data-fs-payment-methods-row-icon-wrapper>
154
+ <Icon name="AccountBalanceWallet" width={20} height={20} />
155
+ </span>
156
+ <div data-fs-payment-methods-name>{name}</div>
157
+ </div>
158
+ </div>
159
+ </li>
160
+ ))}
161
+ </ul>
162
+ );
163
+
164
+ const renderLoading = () => (
165
+ <div data-fs-payment-methods-loading>
166
+ {Array.from({ length: 5 }).map((_, index) => (
167
+ <Skeleton key={index} size={{ width: "100%", height: "1.5rem" }} />
168
+ ))}
169
+ </div>
170
+ );
171
+
172
+ const renderEmpty = () => (
173
+ <EmptyState
174
+ title="No results found"
175
+ description={
176
+ querySearch.length > 0
177
+ ? "Try using different terms"
178
+ : "No payment methods found"
179
+ }
180
+ />
181
+ );
182
+
183
+ const renderBodyContent = () => {
184
+ if (isLoadingPaymentMethods) return renderLoading();
185
+
186
+ if ((paymentMethods?.length ?? 0) === 0) return renderEmpty();
187
+
188
+ if (availableMethods.length > 0) return renderList();
189
+
190
+ return (
191
+ <EmptyState
192
+ title="All methods already added"
193
+ description="There are no additional payment methods to add for this unit."
194
+ />
195
+ );
196
+ };
197
+
119
198
  return (
120
199
  <BasicDrawer data-fs-bp-add-payment-methods-drawer close={close} {...props}>
121
200
  <BasicDrawer.Heading title="Add payment methods" onClose={close} />
@@ -134,62 +213,7 @@ export const AddPaymentMethodsDrawer = ({
134
213
  textSearch={setQuerySearch}
135
214
  />
136
215
 
137
- {isLoadingPaymentMethods ? (
138
- <div data-fs-payment-methods-loading>
139
- {Array.from({ length: 5 }).map((_, index) => (
140
- <Skeleton
141
- key={index}
142
- size={{ width: "100%", height: "1.5rem" }}
143
- />
144
- ))}
145
- </div>
146
- ) : (
147
- <ul data-fs-payment-methods-list>
148
- <div
149
- data-fs-bp-payment-methods-list-title
150
- data-fs-bp-payment-methods-list-title-drawer
151
- >
152
- <Checkbox
153
- data-fs-bp-payment-methods-checkbox
154
- ref={selectAllRef}
155
- checked={allSelected}
156
- onChange={toggleAll}
157
- disabled={readonly}
158
- aria-label="Select all payment methods"
159
- />
160
- Name
161
- </div>
162
-
163
- {availableMethods.map(({ id, name }) => (
164
- <li key={id} data-fs-payment-methods-line>
165
- <div
166
- data-fs-payment-methods-row
167
- data-fs-payment-methods-row-selected={selectedMethods.has(
168
- id
169
- )}
170
- >
171
- <div data-fs-payment-methods-row-information>
172
- <Checkbox
173
- data-fs-bp-payment-methods-checkbox
174
- checked={selectedMethods.has(id)}
175
- onChange={() => toggleItem(id)}
176
- disabled={readonly}
177
- aria-label={`Select ${name}`}
178
- />
179
- <span data-fs-payment-methods-row-icon-wrapper>
180
- <Icon
181
- name="AccountBalanceWallet"
182
- width={20}
183
- height={20}
184
- />
185
- </span>
186
- <div data-fs-payment-methods-name>{name}</div>
187
- </div>
188
- </div>
189
- </li>
190
- ))}
191
- </ul>
192
- )}
216
+ {renderBodyContent()}
193
217
  </section>
194
218
  </BasicDrawer.Body>
195
219
 
@@ -197,11 +221,12 @@ export const AddPaymentMethodsDrawer = ({
197
221
  <BasicDrawer.Button variant="ghost" onClick={close}>
198
222
  Cancel
199
223
  </BasicDrawer.Button>
224
+
200
225
  <BasicDrawer.Button
201
226
  variant="confirm"
202
227
  isLoading={isAddPaymentMethodsLoading}
203
228
  onClick={handleSubmit}
204
- disabled={!selectedMethods.size}
229
+ disabled={isAddPaymentMethodsLoading || selectedMethods.size === 0}
205
230
  >
206
231
  Add
207
232
  </BasicDrawer.Button>
@@ -1,44 +1,80 @@
1
1
  @import "../SearchPaymentMethods/search-payment-methods.scss";
2
2
 
3
+ [data-fs-bp-basic-drawer][data-fs-slide-over-size="partial"] {
4
+ width: 66%;
5
+ min-width: 66%;
6
+
7
+ @include media(">=notebook") {
8
+ width: 60rem;
9
+ min-width: 60rem;
10
+ max-width: 60rem;
11
+ }
12
+ }
13
+
3
14
  [data-fs-bp-add-payment-methods-drawer] {
4
- min-width: 66% !important;
15
+ [data-fs-payment-methods-drawer] {
16
+ @import "../../../shared/components/EmptyState/empty-state.scss";
17
+ @import "@faststore/ui/src/components/atoms/Checkbox/styles.scss";
18
+ @import "@faststore/ui/src/components/atoms/Skeleton/styles.scss";
19
+
20
+ [data-fs-bp-add-payment-methods-drawer-description] {
21
+ color: #1f1f1f;
22
+ margin-bottom: var(--fs-spacing-3);
23
+
24
+ span {
25
+ color: #0366dd;
26
+ }
27
+ }
5
28
 
6
- [data-fs-payment-methods-drawer] {
7
- @import "@faststore/ui/src/components/atoms/Checkbox/styles.scss";
8
- @import "@faststore/ui/src/components/atoms/Skeleton/styles.scss";
29
+ [data-fs-bp-payment-methods-checkbox] {
30
+ border-color: #e5e5e5;
31
+ }
9
32
 
10
- [data-fs-bp-add-payment-methods-drawer-description] {
11
- color: #1f1f1f;
12
- margin-bottom: var(--fs-spacing-3);
33
+ [data-fs-bp-payment-methods-checkbox]:checked {
34
+ background-color: #0366dd;
35
+ }
13
36
 
14
- span {
15
- color: #0366dd;
16
- }
17
- }
37
+ [data-fs-bp-basic-drawer-button-loading-indicator] {
38
+ position: relative;
39
+ }
18
40
 
19
- [data-fs-bp-payment-methods-checkbox] {
20
- border-color: #e5e5e5;
21
- }
41
+ [data-fs-payment-methods-loading] {
42
+ * {
43
+ margin-top: var(--fs-spacing-1);
44
+ padding: var(--fs-spacing-2) 0;
45
+ }
46
+ }
47
+ }
22
48
 
23
- [data-fs-bp-payment-methods-checkbox]:checked {
24
- background-color: #0366dd;
25
- }
49
+ [data-fs-bp-add-payment-methods-drawer-footer] {
50
+ display: flex;
51
+ justify-content: flex-end;
52
+ gap: var(--fs-spacing-3);
53
+ }
54
+ [data-fs-bp-payment-methods-search-container] {
55
+ [data-fs-bp-pagination] {
56
+ [data-fs-bp-counter-bottom] {
57
+ display: block;
58
+ text-align: end;
59
+ }
60
+ }
61
+ }
26
62
 
27
- [data-fs-bp-basic-drawer-button-loading-indicator] {
28
- position: relative;
29
- }
63
+ @include media("<=tablet") {
64
+ [data-fs-buyer-portal-internal-search] {
65
+ width: 18rem !important;
66
+ }
67
+ }
30
68
 
31
- [data-fs-payment-methods-loading] {
32
- * {
33
- margin-top: var(--fs-spacing-1);
34
- padding: var(--fs-spacing-2) 0;
35
- }
36
- }
69
+ @include media("<=phonemid") {
70
+ [data-fs-buyer-portal-internal-search] {
71
+ width: 14rem !important;
37
72
  }
73
+ }
38
74
 
39
- [data-fs-bp-add-payment-methods-drawer-footer] {
40
- display: flex;
41
- justify-content: flex-end;
42
- gap: var(--fs-spacing-3);
75
+ @include media("<=phone") {
76
+ [data-fs-buyer-portal-internal-search] {
77
+ width: 10rem !important;
43
78
  }
79
+ }
44
80
  }
@@ -1,4 +1,4 @@
1
- import { InternalSearch } from "../../../shared/components";
1
+ import { InternalSearch, Pagination } from "../../../shared/components";
2
2
  import { InternalSearchProps } from "../../../shared/components/InternalSearch/InternalSearch";
3
3
  import { useQueryParams } from "../../../shared/hooks";
4
4
 
@@ -36,9 +36,11 @@ export const SearchPaymentMethods = ({
36
36
  }
37
37
  }
38
38
  />
39
- <p data-fs-bp-payment-methods-search-container-counter>
40
- {`${getCount(data)} of ${getCount(paymentMethodsData)}`}
41
- </p>
39
+ <Pagination
40
+ total={getCount(paymentMethodsData)}
41
+ currentCount={getCount(data)}
42
+ variant="counter"
43
+ />
42
44
  </div>
43
45
  );
44
46
  };
@@ -14,7 +14,7 @@
14
14
  display: block;
15
15
  }
16
16
 
17
- @media (max-width: 768px) {
17
+ @include media("<=tablet") {
18
18
  [data-fs-payment-methods-section] {
19
19
  [data-fs-buyer-portal-internal-search] {
20
20
  width: 100%;
@@ -24,5 +24,8 @@
24
24
  [data-fs-bp-payment-methods-search-container-counter] {
25
25
  display: none;
26
26
  }
27
+ [data-fs-bp-counter-bottom] {
28
+ display: none;
29
+ }
27
30
  }
28
31
  }
@@ -1,4 +1,4 @@
1
- import { useEffect, useState } from "react";
1
+ import { useEffect, useMemo, useState } from "react";
2
2
 
3
3
  import { HeaderInside, Table } from "../../../shared/components";
4
4
  import ConditionalTooltip from "../../../shared/components/ConditionalTooltip/ConditionalTooltip";
@@ -49,6 +49,7 @@ export const PaymentMethodsLayout = ({
49
49
  isOpen: isAddPaymentMethodDrawerOpen,
50
50
  ...addDrawerProps
51
51
  } = useDrawerProps();
52
+
52
53
  const {
53
54
  open: openRemoveDrawer,
54
55
  isOpen: isRemovePaymentMethodDrawerOpen,
@@ -68,11 +69,21 @@ export const PaymentMethodsLayout = ({
68
69
  search: querySearch,
69
70
  });
70
71
 
72
+ const fetchedMethods = paymentMethods ?? [];
73
+ const currentPaymentMethods = useMemo(
74
+ () => (paymentMethodsData ?? []).filter((m) => m?.isEnabled),
75
+ [paymentMethodsData]
76
+ );
77
+
78
+ const isSinglePaymentMethod = currentPaymentMethods.length <= 1;
79
+ const allPaymentMethodsSelected =
80
+ currentPaymentMethods.length === (paymentMethodsData?.length ?? 0);
81
+
71
82
  useEffect(() => {
72
83
  if (!isLoadingPaymentMethods && querySearch.length > 0) {
73
- setPaymentMethodsData(paymentMethods);
84
+ setPaymentMethodsData(fetchedMethods);
74
85
  }
75
- }, [paymentMethods, isLoadingPaymentMethods, querySearch]);
86
+ }, [fetchedMethods, isLoadingPaymentMethods, querySearch]);
76
87
 
77
88
  const handleSearch = (searchTerm: string) => {
78
89
  setQuerySearch(searchTerm);
@@ -94,13 +105,53 @@ export const PaymentMethodsLayout = ({
94
105
  }
95
106
  };
96
107
 
97
- const currentPaymentMethods = paymentMethodsData?.filter(
98
- (method) => method?.isEnabled
108
+ // --------- Render helpers (sem ternários encadeados) ----------
109
+ const renderEmpty = () => (
110
+ <EmptyState
111
+ title="No results found"
112
+ description={
113
+ querySearch.length > 0
114
+ ? "Try using different terms"
115
+ : "No payment methods found"
116
+ }
117
+ />
99
118
  );
100
119
 
101
- const isSinglePaymentMethod = currentPaymentMethods?.length <= 1;
102
- const allPaymentMethodsSelected =
103
- currentPaymentMethods?.length === paymentMethodsData?.length;
120
+ const renderTableRows = () =>
121
+ currentPaymentMethods.map((method) => (
122
+ <Table.Row
123
+ data-fs-bp-payment-method-table-row
124
+ key={method?.id}
125
+ searchTerm={querySearch}
126
+ title={method?.name}
127
+ iconName="AccountBalanceWallet"
128
+ iconSize={24}
129
+ children={
130
+ <td>
131
+ <RemoveMethodButton
132
+ isLoading={isRemovingPaymentMethod}
133
+ onClick={() => onRemoveClick(method)}
134
+ disabled={isSinglePaymentMethod || isRemovingPaymentMethod}
135
+ />
136
+ </td>
137
+ }
138
+ />
139
+ ));
140
+
141
+ const renderTable = () => (
142
+ <Table>
143
+ <Table.Head columns={getTableColumns()} />
144
+ <Table.Body>
145
+ {isLoadingPaymentMethods ? <Table.Loading /> : renderTableRows()}
146
+ </Table.Body>
147
+ </Table>
148
+ );
149
+
150
+ const renderContent = () => {
151
+ if (!isLoadingPaymentMethods && fetchedMethods.length === 0)
152
+ return renderEmpty();
153
+ return renderTable();
154
+ };
104
155
 
105
156
  return (
106
157
  <GlobalLayout>
@@ -129,71 +180,31 @@ export const PaymentMethodsLayout = ({
129
180
  />
130
181
  </ConditionalTooltip>
131
182
  </HeaderInside>
183
+
132
184
  <SearchPaymentMethods
133
185
  data={currentPaymentMethods}
134
186
  paymentMethodsData={paymentMethodsData}
135
187
  defaultValue={querySearch}
136
188
  textSearch={handleSearch}
137
189
  />
138
- {!isLoadingPaymentMethods && paymentMethods?.length === 0 ? (
139
- <EmptyState
140
- title="No results found"
141
- description={
142
- querySearch.length > 0
143
- ? "Try using different terms"
144
- : "No payment methods found"
145
- }
146
- />
147
- ) : (
148
- <Table>
149
- <Table.Head columns={getTableColumns()} />
150
- {isLoadingPaymentMethods ? (
151
- <Table.Body>
152
- <Table.Loading />
153
- </Table.Body>
154
- ) : (
155
- <Table.Body>
156
- {currentPaymentMethods.map((method) => (
157
- <Table.Row
158
- data-fs-bp-payment-method-table-row
159
- key={method?.id}
160
- searchTerm={querySearch}
161
- title={method?.name}
162
- iconName={"AccountBalanceWallet"}
163
- iconSize={24}
164
- children={
165
- <td>
166
- <RemoveMethodButton
167
- isLoading={isRemovingPaymentMethod}
168
- onClick={() => {
169
- onRemoveClick(method);
170
- }}
171
- disabled={
172
- isSinglePaymentMethod || isRemovingPaymentMethod
173
- }
174
- />
175
- </td>
176
- }
177
- />
178
- ))}
179
- </Table.Body>
180
- )}
181
- </Table>
182
- )}
190
+
191
+ {renderContent()}
183
192
 
184
193
  {!isLoadingPaymentMethods && (
185
194
  <p data-fs-bp-payment-methods-search-container-counter-bottom>
186
- {`${currentPaymentMethods?.length ?? 0} of ${
195
+ {`${currentPaymentMethods.length} of ${
187
196
  paymentMethodsData?.length ?? 0
188
197
  }`}
189
198
  </p>
190
199
  )}
200
+
191
201
  {isAddPaymentMethodDrawerOpen && (
192
202
  <AddPaymentMethodsDrawer
193
203
  {...addDrawerProps}
194
204
  isOpen={isAddPaymentMethodDrawerOpen}
195
205
  />
196
206
  )}
207
+
197
208
  {isRemovePaymentMethodDrawerOpen && selectedMethod && (
198
209
  <RemovePaymentMethodsDrawer
199
210
  {...removeDrawerProps}