@vtex/faststore-plugin-buyer-portal 1.3.22 → 1.3.24

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 (22) hide show
  1. package/CHANGELOG.md +15 -1
  2. package/package.json +1 -1
  3. package/src/features/addresses/layouts/AddressesLayout/addresses-layout.scss +12 -10
  4. package/src/features/budgets/layouts/BudgetsLayout/budgets-layout.scss +15 -0
  5. package/src/features/buying-policies/components/AddBuyingPolicyDrawer/AddBuyingPolicyDrawer.tsx +0 -4
  6. package/src/features/buying-policies/components/BasicBuyingPolicyDrawer/BasicBuyingPolicyDrawer.tsx +0 -5
  7. package/src/features/buying-policies/components/BudgetCriteriaSelector/BudgetCriteriaSelector.tsx +58 -54
  8. package/src/features/buying-policies/components/BuyingPolicyDropdownMenu/BuyingPolicyDropdownMenu.tsx +0 -5
  9. package/src/features/buying-policies/components/UpdateBuyingPolicyDrawer/UpdateBuyingPolicyDrawer.tsx +0 -5
  10. package/src/features/buying-policies/hooks/useGetBudgets.ts +35 -0
  11. package/src/features/buying-policies/layouts/BuyingPoliciesLayout/BuyingPoliciesLayout.tsx +0 -5
  12. package/src/features/buying-policies/layouts/BuyingPoliciesLayout/buying-policies-layout.scss +1 -1
  13. package/src/features/credit-cards/layouts/CreditCardsLayout/credit-card-layout.scss +15 -0
  14. package/src/features/custom-fields/layouts/CustomFieldsLayout/custom-fields-layout.scss +15 -0
  15. package/src/features/org-units/layouts/OrgUnitsLayout/org-units-layout.scss +15 -0
  16. package/src/features/payment-methods/layouts/PaymentMethodsLayout/payment-methods-layout.scss +7 -6
  17. package/src/features/product-assortment/layouts/ProductAssortmentLayout/product-assortment-layout.scss +15 -0
  18. package/src/features/shared/components/CustomDropdown/CustomDropdown.tsx +9 -1
  19. package/src/features/shared/hooks/useQuery.ts +3 -1
  20. package/src/features/shared/utils/constants.ts +1 -1
  21. package/src/features/users/layouts/UsersLayout/users-layout.scss +15 -0
  22. package/src/pages/buying-policies.tsx +20 -37
package/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.3.24] - 2025-11-25
11
+
12
+ ### Added
13
+
14
+ - Adjusts the position of the **“+”** button in the responsive layout
15
+
16
+ ## [1.3.23] - 2025-11-25
17
+
18
+ ### Changed
19
+
20
+ - Refactor logic of fetching budgets to be handled by a new custom hook
21
+
10
22
  ## [1.3.22] - 2025-11-21
11
23
 
12
24
  ### Added
@@ -235,7 +247,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
235
247
  - Add CHANGELOG file
236
248
  - Add README file
237
249
 
238
- [unreleased]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.22...HEAD
250
+ [unreleased]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.24...HEAD
239
251
  [1.2.3]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.2.2...1.2.3
240
252
  [1.2.3]: https://github.com/vtex/faststore-plugin-buyer-portal/releases/tag/1.2.3
241
253
  [1.2.4]: https://github.com/vtex/faststore-plugin-buyer-portal/releases/tag/1.2.4
@@ -250,6 +262,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
250
262
 
251
263
  # <<<<<<< HEAD
252
264
 
265
+ [1.3.24]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.23...v1.3.24
266
+ [1.3.23]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.22...v1.3.23
253
267
  [1.3.22]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.21...v1.3.22
254
268
  [1.3.21]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.20...v1.3.21
255
269
  [1.3.20]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.19...v1.3.20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/faststore-plugin-buyer-portal",
3
- "version": "1.3.22",
3
+ "version": "1.3.24",
4
4
  "description": "A plugin for faststore with buyer portal",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -26,25 +26,27 @@
26
26
  flex-direction: column;
27
27
  height: 100%;
28
28
 
29
- @include media("<=tablet") {
30
- padding: 0;
31
- }
29
+ @include media("<=phonemid") {
30
+ padding: 0 0 var(--fs-spacing-7) 0;
32
31
 
33
- [data-fs-bp-header-inside] {
34
- [data-fs-bp-header-buttons] > button {
35
- display: flex;
36
- }
37
- @include media("<=tablet") {
38
- [data-fs-header-inside-button]:nth-child(3) {
32
+ [data-fs-bp-header-inside] {
33
+ [data-fs-header-inside-button] {
39
34
  position: fixed;
40
35
  bottom: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
41
36
  right: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
37
+ padding: var(--fs-spacing-2);
42
38
  cursor: pointer;
43
- z-index: 1000;
39
+ z-index: 10;
44
40
  }
45
41
  }
46
42
  }
47
43
 
44
+ [data-fs-bp-header-inside] {
45
+ [data-fs-bp-header-buttons] > button {
46
+ display: flex;
47
+ }
48
+ }
49
+
48
50
  [data-fs-bp-address-tabs-paginator-last] {
49
51
  display: flex;
50
52
  justify-content: flex-end;
@@ -15,6 +15,21 @@
15
15
 
16
16
  width: 100%;
17
17
 
18
+ @include media("<=phonemid") {
19
+ padding-bottom: var(--fs-spacing-7);
20
+
21
+ [data-fs-bp-header-inside] {
22
+ [data-fs-header-inside-button] {
23
+ position: fixed;
24
+ bottom: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
25
+ right: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
26
+ padding: var(--fs-spacing-2);
27
+ cursor: pointer;
28
+ z-index: 10;
29
+ }
30
+ }
31
+ }
32
+
18
33
  [data-fs-button] {
19
34
  border-radius: var(--fs-border-radius-circle);
20
35
  padding: 0;
@@ -7,7 +7,6 @@ import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
7
7
  import { useAddBuyingPolicy } from "../../hooks";
8
8
  import { buyingPolicyDefault } from "../../utils";
9
9
 
10
- import type { BudgetListResponse } from "../../../budgets/types";
11
10
  import type { BuyingPolicy } from "../../types";
12
11
 
13
12
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -20,7 +19,6 @@ export type AddBuyingPolicyDrawerProps = Omit<
20
19
  onCreate?: () => void;
21
20
  orgUnitId: string;
22
21
  contractId: string;
23
- budgetData?: BudgetListResponse;
24
22
  };
25
23
 
26
24
  export const AddBuyingPolicyDrawer = ({
@@ -28,7 +26,6 @@ export const AddBuyingPolicyDrawer = ({
28
26
  onCreate,
29
27
  orgUnitId,
30
28
  contractId,
31
- budgetData = { data: [], total: 0 },
32
29
  ...props
33
30
  }: AddBuyingPolicyDrawerProps) => {
34
31
  const { pushToast } = useUI();
@@ -88,7 +85,6 @@ export const AddBuyingPolicyDrawer = ({
88
85
  orgUnitId={orgUnitId}
89
86
  contractId={contractId}
90
87
  initialValues={defaultBuyingPolicyValues}
91
- budgetData={budgetData}
92
88
  {...props}
93
89
  />
94
90
  );
@@ -31,8 +31,6 @@ import { BUYING_POLICIES_WORKFLOW_LABELS } from "../../utils/buyingPoliciesWorkf
31
31
  import { getHighlightedText } from "../../utils/criteriaHighlightSyntax";
32
32
  import { BudgetCriteriaSelector } from "../BudgetCriteriaSelector";
33
33
 
34
- import type { BudgetListResponse } from "../../../budgets/types";
35
-
36
34
  const LIMIT_OF_LEVELS = 5;
37
35
 
38
36
  export type BuyingPolicyForm = Omit<BuyingPolicy, "id"> & {
@@ -54,7 +52,6 @@ export type BasicBuyingPolicyDrawerProps = Omit<
54
52
  drawerTitle?: string;
55
53
  saveButtonLabel?: string;
56
54
  isDrawerLoading?: boolean;
57
- budgetData?: BudgetListResponse;
58
55
  };
59
56
 
60
57
  export const BasicBuyingPolicyDrawer = ({
@@ -67,7 +64,6 @@ export const BasicBuyingPolicyDrawer = ({
67
64
  orgUnitId,
68
65
  contractId,
69
66
  initialValues = defaultBuyingPolicyValues,
70
- budgetData = { data: [], total: 0 },
71
67
  ...props
72
68
  }: BasicBuyingPolicyDrawerProps) => {
73
69
  const [form, setForm] = useState<BuyingPolicyForm>(initialValues);
@@ -181,7 +177,6 @@ export const BasicBuyingPolicyDrawer = ({
181
177
  if (isBudgetCriteria) {
182
178
  return (
183
179
  <BudgetCriteriaSelector
184
- budgetData={budgetData}
185
180
  currentCriteria={criteria}
186
181
  onCriteriaChange={(newCriteria) =>
187
182
  updateField("criteria", newCriteria)
@@ -1,22 +1,32 @@
1
1
  import { useState, useEffect } from "react";
2
2
 
3
3
  import { CustomDropdown } from "../../../shared/components/CustomDropdown/CustomDropdown";
4
-
5
- import type { BudgetListResponse } from "../../../budgets/types";
4
+ import { useBuyerPortal } from "../../../shared/hooks";
5
+ import { useGetBudgets } from "../../hooks/useGetBudgets";
6
6
 
7
7
  export type BudgetCriteriaSelectorProps = {
8
8
  onCriteriaChange: (criteria: string) => void;
9
9
  currentCriteria: string;
10
10
  onEditablePartClick?: () => void;
11
- budgetData?: BudgetListResponse;
12
11
  };
13
12
 
14
13
  export const BudgetCriteriaSelector = ({
15
14
  onCriteriaChange,
16
15
  currentCriteria,
17
16
  onEditablePartClick,
18
- budgetData = { data: [], total: 0 },
19
17
  }: BudgetCriteriaSelectorProps) => {
18
+ const {
19
+ clientContext: { customerId },
20
+ currentOrgUnit: orgUnit,
21
+ } = useBuyerPortal();
22
+
23
+ const { budgets, isBudgetsLoading, refetchBudgets } = useGetBudgets({
24
+ data: { customerId, orgUnitId: orgUnit?.id || "" },
25
+ options: { lazy: true },
26
+ });
27
+
28
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
29
+
20
30
  const extractBudgetValueFromCriteria = (criteria: string): string => {
21
31
  const match = criteria.match(/id="([^"]+)"/);
22
32
  return match ? match[1] : "budget-001";
@@ -31,31 +41,28 @@ export const BudgetCriteriaSelector = ({
31
41
  setCurrentBudgetValue(extractedValue);
32
42
  }, [currentCriteria]);
33
43
 
34
- const getMatchingBudget = () => {
35
- return budgetData.data.find(
36
- (budget) =>
37
- budget.id === currentBudgetValue || budget.id === currentBudgetValue
38
- );
39
- };
40
-
41
44
  const generateCriteriaString = (value: string) => {
42
45
  return `$exists(budgetData.budgets[id="${value}"])`;
43
46
  };
44
47
 
45
48
  const handleBudgetSelect = (budgetId: string) => {
46
- const selectedBudget = budgetData.data.find(
47
- (budget) => budget.id === budgetId
48
- );
49
- if (selectedBudget) {
50
- const newValue = selectedBudget.id;
51
- setCurrentBudgetValue(newValue);
52
- const newCriteria = generateCriteriaString(newValue);
53
- onCriteriaChange(newCriteria);
54
- }
49
+ if (budgetId === "loading") return;
50
+
51
+ const selectedBudget = budgets.data.find((b) => b.id === budgetId);
52
+ if (!selectedBudget) return;
53
+
54
+ setCurrentBudgetValue(selectedBudget.id);
55
+ onCriteriaChange(generateCriteriaString(selectedBudget.id));
56
+ setIsDropdownOpen(false);
55
57
  };
56
58
 
57
- const handleBudgetSelectorClick = (e: React.MouseEvent) => {
59
+ const handleBudgetValueClick = (e: React.MouseEvent) => {
58
60
  e.stopPropagation();
61
+ setIsDropdownOpen(true);
62
+
63
+ if (budgets.data.length === 0 && !isBudgetsLoading) {
64
+ refetchBudgets();
65
+ }
59
66
  };
60
67
 
61
68
  const handleEditablePartClick = (e: React.MouseEvent) => {
@@ -63,47 +70,44 @@ export const BudgetCriteriaSelector = ({
63
70
  onEditablePartClick?.();
64
71
  };
65
72
 
66
- const matchingBudget = getMatchingBudget();
67
- const displayValue = matchingBudget ? matchingBudget.id : currentBudgetValue;
68
- const hasBudgetData = budgetData.data.length > 0;
73
+ const loadingOptions = [{ label: "Loading budgets...", value: "loading" }];
74
+
75
+ const budgetOptions = budgets.data.map((b) => ({
76
+ label: b.name,
77
+ value: b.id,
78
+ }));
79
+
80
+ const options =
81
+ isBudgetsLoading || budgets.data.length === 0
82
+ ? loadingOptions
83
+ : budgetOptions;
69
84
 
70
85
  return (
71
- <div
72
- data-fs-bp-budget-criteria-selector
73
- onClick={handleBudgetSelectorClick}
74
- >
86
+ <div data-fs-bp-budget-criteria-selector>
75
87
  <div data-fs-bp-budget-criteria-string>
76
88
  <span onClick={handleEditablePartClick} data-fs-bp-editable-part>
77
89
  $exists(budgetData.budgets[id="
78
90
  </span>
79
- {hasBudgetData ? (
80
- <div onClick={handleBudgetSelectorClick}>
81
- <CustomDropdown
82
- options={budgetData.data.map((budget) => ({
83
- label: budget.name,
84
- value: budget.id,
85
- }))}
86
- onSelect={handleBudgetSelect}
87
- triggerLabel={displayValue}
88
- highlightText={(text) => (
89
- <div data-fs-bp-dropdown-option>
90
- <div data-fs-bp-dropdown-option-label>{text}</div>
91
+
92
+ <div onClick={handleBudgetValueClick}>
93
+ <CustomDropdown
94
+ options={options}
95
+ onSelect={handleBudgetSelect}
96
+ triggerLabel={isBudgetsLoading ? "Loading..." : currentBudgetValue}
97
+ isOpen={isDropdownOpen}
98
+ highlightText={(text) => (
99
+ <div data-fs-bp-dropdown-option>
100
+ <div data-fs-bp-dropdown-option-label>{text}</div>
101
+ {!isBudgetsLoading && (
91
102
  <div data-fs-bp-dropdown-option-uuid>
92
- {budgetData.data.find((b) => b.name === text)?.id}
103
+ {budgets.data.find((b) => b.name === text)?.id}
93
104
  </div>
94
- </div>
95
- )}
96
- />
97
- </div>
98
- ) : (
99
- <span
100
- onClick={handleEditablePartClick}
101
- data-fs-bp-editable-part
102
- data-fs-bp-budget-value
103
- >
104
- {displayValue}
105
- </span>
106
- )}
105
+ )}
106
+ </div>
107
+ )}
108
+ />
109
+ </div>
110
+
107
111
  <span onClick={handleEditablePartClick} data-fs-bp-editable-part>
108
112
  "])
109
113
  </span>
@@ -7,14 +7,11 @@ import { BasicDropdownMenu, Icon } from "../../../shared/components";
7
7
  import { useBuyerPortal, useDrawerProps } from "../../../shared/hooks";
8
8
  import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
9
9
 
10
- import type { BudgetListResponse } from "../../../budgets/types";
11
-
12
10
  export type BuyingPolicyDropdownMenuProps = {
13
11
  id: string;
14
12
  name: string;
15
13
  onDelete?: () => void;
16
14
  onUpdate?: () => void;
17
- budgetData?: BudgetListResponse;
18
15
  };
19
16
 
20
17
  export const BuyingPolicyDropdownMenu = ({
@@ -22,7 +19,6 @@ export const BuyingPolicyDropdownMenu = ({
22
19
  name,
23
20
  onDelete,
24
21
  onUpdate,
25
- budgetData = { data: [], total: 0 },
26
22
  }: BuyingPolicyDropdownMenuProps) => {
27
23
  const { currentContract, currentOrgUnit } = useBuyerPortal();
28
24
 
@@ -84,7 +80,6 @@ export const BuyingPolicyDropdownMenu = ({
84
80
  contractId={currentContract?.id ?? ""}
85
81
  buyingPolicyId={id}
86
82
  onUpdate={onUpdate}
87
- budgetData={budgetData}
88
83
  {...updateBuyingPolicyDrawerProps}
89
84
  isOpen={isUpdateBuyingPolicyDrawerOpen}
90
85
  />
@@ -7,8 +7,6 @@ import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
7
7
  import { useGetBuyingPolicy, useUpdateBuyingPolicy } from "../../hooks";
8
8
  import { buyingPolicyDefault } from "../../utils";
9
9
 
10
- import type { BudgetListResponse } from "../../../budgets/types";
11
-
12
10
  export type UpdateBuyingPolicyDrawerProps = Omit<
13
11
  BasicBuyingPolicyDrawerProps,
14
12
  "children" | "initialValues"
@@ -17,7 +15,6 @@ export type UpdateBuyingPolicyDrawerProps = Omit<
17
15
  orgUnitId: string;
18
16
  contractId: string;
19
17
  buyingPolicyId: string;
20
- budgetData?: BudgetListResponse;
21
18
  };
22
19
 
23
20
  export const UpdateBuyingPolicyDrawer = ({
@@ -26,7 +23,6 @@ export const UpdateBuyingPolicyDrawer = ({
26
23
  orgUnitId,
27
24
  contractId,
28
25
  buyingPolicyId,
29
- budgetData = { data: [], total: 0 },
30
26
  ...props
31
27
  }: UpdateBuyingPolicyDrawerProps) => {
32
28
  const { buyingPolicy, isBuyingPolicyLoading } = useGetBuyingPolicy(
@@ -97,7 +93,6 @@ export const UpdateBuyingPolicyDrawer = ({
97
93
  initialValues={{ ...buyingPolicyDefault, ...(buyingPolicy ?? {}) }}
98
94
  orgUnitId={orgUnitId}
99
95
  contractId={contractId}
100
- budgetData={budgetData}
101
96
  {...props}
102
97
  />
103
98
  );
@@ -0,0 +1,35 @@
1
+ import { listBudgetsService } from "../../budgets/services";
2
+ import { QueryOptions, useQuery } from "../../shared/hooks";
3
+
4
+ import type { BudgetListResponse } from "../../budgets/types";
5
+
6
+ interface UseGetBudgetsProps {
7
+ data: {
8
+ customerId: string;
9
+ orgUnitId: string;
10
+ };
11
+ options?: QueryOptions<BudgetListResponse>;
12
+ }
13
+
14
+ export const useGetBudgets = ({
15
+ data: { customerId, orgUnitId },
16
+ options,
17
+ }: UseGetBudgetsProps) => {
18
+ const { data, error, isLoading, refetch } = useQuery(
19
+ `api/budgets/${customerId}/${orgUnitId}`,
20
+ ({ cookie }) =>
21
+ listBudgetsService({
22
+ customerId,
23
+ unitId: orgUnitId,
24
+ cookie,
25
+ }),
26
+ options
27
+ );
28
+
29
+ return {
30
+ budgets: data ?? { data: [], total: 0 },
31
+ hasBudgetsError: error,
32
+ isBudgetsLoading: isLoading,
33
+ refetchBudgets: refetch,
34
+ };
35
+ };
@@ -21,7 +21,6 @@ import { BuyingPolicyDropdownMenu } from "../../components";
21
21
  import { AddBuyingPolicyDrawer } from "../../components/AddBuyingPolicyDrawer/AddBuyingPolicyDrawer";
22
22
  import { useGetBuyingPolicies } from "../../hooks/useGetBuyingPolicies";
23
23
 
24
- import type { BudgetListResponse } from "../../../budgets/types";
25
24
  import type { BuyingPolicy } from "../../types";
26
25
 
27
26
  export type BuyingPoliciesLayoutProps = {
@@ -29,14 +28,12 @@ export type BuyingPoliciesLayoutProps = {
29
28
  total: number;
30
29
  search: string;
31
30
  page: number;
32
- budgetData?: BudgetListResponse;
33
31
  };
34
32
 
35
33
  export const BuyingPoliciesLayout = ({
36
34
  buyingPolicies: initialBuyingPolicies,
37
35
  search,
38
36
  page,
39
- budgetData = { data: [], total: 0 },
40
37
  }: BuyingPoliciesLayoutProps) => {
41
38
  const { currentContract, currentOrgUnit } = useBuyerPortal();
42
39
 
@@ -136,7 +133,6 @@ export const BuyingPoliciesLayout = ({
136
133
  name={buyingPolicy.name}
137
134
  onUpdate={handleRefetchBuyingPolicies}
138
135
  onDelete={handleRefetchBuyingPolicies}
139
- budgetData={budgetData}
140
136
  />
141
137
  }
142
138
  />
@@ -191,7 +187,6 @@ export const BuyingPoliciesLayout = ({
191
187
  contractId={currentContract?.id ?? ""}
192
188
  isOpen={isAddBuyingPolicyDrawerOpen}
193
189
  onCreate={handleRefetchBuyingPolicies}
194
- budgetData={budgetData}
195
190
  {...addBuyingPolicyDrawerProps}
196
191
  />
197
192
  )}
@@ -15,7 +15,7 @@
15
15
  display: flex;
16
16
  flex-direction: column;
17
17
 
18
- @include media("<=tablet") {
18
+ @include media("<=phonemid") {
19
19
  padding-bottom: var(--fs-spacing-7);
20
20
 
21
21
  [data-fs-bp-header-inside] {
@@ -18,6 +18,21 @@
18
18
  padding: 0;
19
19
  }
20
20
 
21
+ @include media("<=phonemid") {
22
+ padding-bottom: var(--fs-spacing-7);
23
+
24
+ [data-fs-bp-header-inside] {
25
+ [data-fs-header-inside-button] {
26
+ position: fixed;
27
+ bottom: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
28
+ right: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
29
+ padding: var(--fs-spacing-2);
30
+ cursor: pointer;
31
+ z-index: 10;
32
+ }
33
+ }
34
+ }
35
+
21
36
  [data-fs-topbar-actions-wrapper] {
22
37
  display: flex;
23
38
  flex-direction: row;
@@ -13,6 +13,21 @@
13
13
  padding: 0;
14
14
  }
15
15
 
16
+ @include media("<=phonemid") {
17
+ padding-bottom: var(--fs-spacing-7);
18
+
19
+ [data-fs-bp-header-inside] {
20
+ [data-fs-header-inside-button] {
21
+ position: fixed;
22
+ bottom: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
23
+ right: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
24
+ padding: var(--fs-spacing-2);
25
+ cursor: pointer;
26
+ z-index: 10;
27
+ }
28
+ }
29
+ }
30
+
16
31
  [data-fs-bp-header-inside] {
17
32
  #header-inside-button-ghost {
18
33
  background-color: transparent;
@@ -16,6 +16,21 @@
16
16
  @import "../../../shared/components/HierarchyTree/hierarchy-tree.scss";
17
17
  @import "../../../shared/components/InternalSearch/internal-search.scss";
18
18
 
19
+ @include media("<=phonemid") {
20
+ padding-bottom: var(--fs-spacing-7);
21
+
22
+ [data-fs-bp-header-inside] {
23
+ [data-fs-header-inside-button] {
24
+ position: fixed;
25
+ bottom: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
26
+ right: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
27
+ padding: var(--fs-spacing-2);
28
+ cursor: pointer;
29
+ z-index: 10;
30
+ }
31
+ }
32
+ }
33
+
19
34
  [data-fs-hierarchy-tree-wrapper] {
20
35
  flex: 1;
21
36
  display: flex;
@@ -112,7 +112,9 @@
112
112
  }
113
113
  }
114
114
 
115
- @include media("<=tablet") {
115
+ @include media("<=phonemid") {
116
+ padding-bottom: var(--fs-spacing-7);
117
+
116
118
  [data-fs-buyer-portal-internal-search] {
117
119
  width: 100% !important;
118
120
  }
@@ -120,12 +122,11 @@
120
122
  [data-fs-bp-header-inside] {
121
123
  [data-fs-header-inside-button] {
122
124
  position: fixed;
123
- bottom: 20px;
124
- right: 20px;
125
- border: none;
126
- border-radius: 50%;
125
+ bottom: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
126
+ right: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
127
+ padding: var(--fs-spacing-2);
127
128
  cursor: pointer;
128
- z-index: 1;
129
+ z-index: 10;
129
130
  }
130
131
  }
131
132
  }
@@ -14,6 +14,21 @@
14
14
 
15
15
  width: 100%;
16
16
 
17
+ @include media("<=phonemid") {
18
+ padding-bottom: var(--fs-spacing-7);
19
+
20
+ [data-fs-bp-header-inside] {
21
+ [data-fs-header-inside-button] {
22
+ position: fixed;
23
+ bottom: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
24
+ right: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
25
+ padding: var(--fs-spacing-2);
26
+ cursor: pointer;
27
+ z-index: 10;
28
+ }
29
+ }
30
+ }
31
+
17
32
  [data-fs-bp-header] {
18
33
  display: flex;
19
34
  width: 100%;
@@ -10,6 +10,7 @@ interface CustomDropdownProps<T> {
10
10
  onSelect: (value: T) => void;
11
11
  triggerLabel: string;
12
12
  highlightText?: (text: string) => React.ReactNode;
13
+ isOpen?: boolean;
13
14
  }
14
15
 
15
16
  export function CustomDropdown<T>({
@@ -17,11 +18,18 @@ export function CustomDropdown<T>({
17
18
  onSelect,
18
19
  triggerLabel,
19
20
  highlightText = (text) => text,
21
+ isOpen: controlledIsOpen,
20
22
  }: CustomDropdownProps<T>) {
21
- const [isOpen, setIsOpen] = useState(false);
23
+ const [isOpen, setIsOpen] = useState(controlledIsOpen ?? false);
22
24
  const [focusedIndex, setFocusedIndex] = useState(-1);
23
25
  const dropdownRef = useRef<HTMLDivElement>(null);
24
26
 
27
+ useEffect(() => {
28
+ if (controlledIsOpen !== undefined) {
29
+ setIsOpen(controlledIsOpen);
30
+ }
31
+ }, [controlledIsOpen]);
32
+
25
33
  const handleOutsideClick = (e: MouseEvent) => {
26
34
  if (
27
35
  dropdownRef.current &&
@@ -24,7 +24,9 @@ export const useQuery = <TData>(
24
24
  ): QueryResult<TData> => {
25
25
  const [data, setData] = useState<TData | null>(null);
26
26
  const [error, setError] = useState<Error | null>(null);
27
- const [isLoading, setIsLoading] = useState<boolean>(true);
27
+ const [isLoading, setIsLoading] = useState<boolean>(
28
+ options?.lazy ? false : true
29
+ );
28
30
  const { clientContext } = useBuyerPortal();
29
31
 
30
32
  const fetchData = useCallback(async () => {
@@ -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.22";
16
+ export const CURRENT_VERSION = "1.3.24";
@@ -19,6 +19,21 @@
19
19
 
20
20
  --data-fs-users-table-width: 11.875rem;
21
21
 
22
+ @include media("<=phonemid") {
23
+ padding-bottom: var(--fs-spacing-7);
24
+
25
+ [data-fs-bp-header-inside] {
26
+ [data-fs-header-inside-button] {
27
+ position: fixed;
28
+ bottom: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
29
+ right: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
30
+ padding: var(--fs-spacing-2);
31
+ cursor: pointer;
32
+ z-index: 10;
33
+ }
34
+ }
35
+ }
36
+
22
37
  [data-fs-bp-header-inside-title] {
23
38
  @include media("<=phonemid") {
24
39
  font-size: var(--fs-text-size-1);
@@ -1,4 +1,3 @@
1
- import { listBudgetsService } from "../features/budgets/services";
2
1
  import { BuyingPoliciesLayout } from "../features/buying-policies/layouts";
3
2
  import { getBuyingPoliciesService } from "../features/buying-policies/services";
4
3
  import { getContractDetailsService } from "../features/contracts/services";
@@ -16,7 +15,6 @@ import {
16
15
  import { getUserByIdService } from "../features/users/services";
17
16
 
18
17
  import type { GetAddressesServiceProps } from "../features/addresses/services";
19
- import type { BudgetListResponse } from "../features/budgets/types";
20
18
  import type { BuyingPolicy } from "../features/buying-policies/types";
21
19
  import type { ContractData } from "../features/contracts/types";
22
20
  import type { OrgUnitBasicData } from "../features/org-units/types";
@@ -34,7 +32,6 @@ export type BuyingPoliciesPageData = {
34
32
  currentOrgUnit: OrgUnitBasicData | null;
35
33
  currentUser: UserData | null;
36
34
  };
37
- budgetData?: BudgetListResponse;
38
35
  hasError?: boolean;
39
36
  error?: ErrorBoundaryProps;
40
37
  };
@@ -68,40 +65,29 @@ const loaderFunction = async (
68
65
  currentContract: null,
69
66
  currentUser: null,
70
67
  },
71
- budgetData: { data: [], total: 0 },
72
68
  };
73
69
  }
74
70
 
75
- const [
76
- currentOrgUnit,
77
- user,
78
- contract,
79
- budgetData,
80
- buyingPoliciesResponse,
81
- ] = await Promise.all([
82
- getOrgUnitBasicDataService({
83
- id: orgUnitId,
84
- cookie,
85
- }),
86
- getUserByIdService({ orgUnitId, userId, cookie }),
87
- getContractDetailsService({
88
- contractId,
89
- cookie,
90
- unitId: orgUnitId,
91
- }),
92
- listBudgetsService({
93
- customerId,
94
- cookie,
95
- unitId: orgUnitId,
96
- }),
97
- getBuyingPoliciesService({
98
- orgUnitId,
99
- contractId,
100
- cookie,
101
- page,
102
- search,
103
- }),
104
- ]);
71
+ const [currentOrgUnit, user, contract, buyingPoliciesResponse] =
72
+ await Promise.all([
73
+ getOrgUnitBasicDataService({
74
+ id: orgUnitId,
75
+ cookie,
76
+ }),
77
+ getUserByIdService({ orgUnitId, userId, cookie }),
78
+ getContractDetailsService({
79
+ contractId,
80
+ cookie,
81
+ unitId: orgUnitId,
82
+ }),
83
+ getBuyingPoliciesService({
84
+ orgUnitId,
85
+ contractId,
86
+ cookie,
87
+ page,
88
+ search,
89
+ }),
90
+ ]);
105
91
 
106
92
  const { data: buyingPolicies = [], total = 0 } = buyingPoliciesResponse;
107
93
 
@@ -122,7 +108,6 @@ const loaderFunction = async (
122
108
  currentUser: user,
123
109
  currentContract: contract,
124
110
  },
125
- budgetData: budgetData ?? { data: [], total: 0 },
126
111
  };
127
112
  }
128
113
  );
@@ -140,7 +125,6 @@ const BuyingPoliciesPage = ({
140
125
  total,
141
126
  hasError,
142
127
  error,
143
- budgetData = { data: [], total: 0 },
144
128
  }: BuyingPoliciesPageData) => (
145
129
  <>
146
130
  {hasError ? (
@@ -151,7 +135,6 @@ const BuyingPoliciesPage = ({
151
135
  search={search}
152
136
  page={page}
153
137
  total={total}
154
- budgetData={budgetData}
155
138
  />
156
139
  )}
157
140
  </>