@vtex/faststore-plugin-buyer-portal 1.1.95 → 1.1.97

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 (58) hide show
  1. package/package.json +1 -1
  2. package/src/features/addresses/components/AddressLocationsList/AddressLocationsList.tsx +28 -39
  3. package/src/features/addresses/components/AddressRecipientsList/AddressRecipientsList.tsx +42 -42
  4. package/src/features/addresses/layouts/AddressDetailsLayout/address-details-layout.scss +285 -286
  5. package/src/features/addresses/layouts/AddressesLayout/AddressesLayout.tsx +26 -29
  6. package/src/features/addresses/layouts/AddressesLayout/addresses-layout.scss +144 -151
  7. package/src/features/budgets/components/BudgetAllocationsSelection/BudgetAllocationsSelection.tsx +61 -57
  8. package/src/features/budgets/components/BudgetAllocationsSelection/budget-allocations-selection.scss +131 -232
  9. package/src/features/budgets/components/BudgetAllocationsTable/BudgetAllocationsTable.tsx +104 -91
  10. package/src/features/budgets/components/BudgetAllocationsTable/budget-allocations-table.scss +80 -182
  11. package/src/features/budgets/components/BudgetsTable/BudgetsTable.tsx +90 -107
  12. package/src/features/budgets/components/BudgetsTable/budgets-table.scss +128 -126
  13. package/src/features/budgets/layouts/BudgetsLayout/BudgetsLayout.tsx +0 -15
  14. package/src/features/buying-policies/components/AddBuyingPolicyDrawer/AddBuyingPolicyDrawer.tsx +4 -0
  15. package/src/features/buying-policies/components/BasicBuyingPolicyDrawer/BasicBuyingPolicyDrawer.tsx +35 -4
  16. package/src/features/buying-policies/components/BasicBuyingPolicyDrawer/basic-buying-policy-drawer.scss +2 -1
  17. package/src/features/buying-policies/components/BudgetCriteriaSelector/BudgetCriteriaSelector.tsx +113 -0
  18. package/src/features/buying-policies/components/BudgetCriteriaSelector/budget-criteria-selector.scss +139 -0
  19. package/src/features/buying-policies/components/BudgetCriteriaSelector/index.ts +4 -0
  20. package/src/features/buying-policies/components/BuyingPolicyDropdownMenu/BuyingPolicyDropdownMenu.tsx +5 -0
  21. package/src/features/buying-policies/components/UpdateBuyingPolicyDrawer/UpdateBuyingPolicyDrawer.tsx +5 -0
  22. package/src/features/buying-policies/layouts/BuyingPoliciesLayout/BuyingPoliciesLayout.tsx +66 -46
  23. package/src/features/buying-policies/layouts/BuyingPoliciesLayout/buying-policies-layout.scss +64 -70
  24. package/src/features/buying-policies/utils/index.ts +4 -1
  25. package/src/features/buying-policies/utils/orderFieldsCriteriaOptions.ts +12 -9
  26. package/src/features/collections/components/CollectionsTable/CollectionsTable.tsx +12 -18
  27. package/src/features/collections/components/CollectionsTable/collections-table.scss +138 -118
  28. package/src/features/collections/components/table/AddCollectionsDrawerTable.tsx +48 -54
  29. package/src/features/collections/components/table/add-collections-drawer-table.scss +57 -56
  30. package/src/features/credit-cards/layouts/CreditCardsLayout/CreditCardLayout.tsx +55 -61
  31. package/src/features/credit-cards/layouts/CreditCardsLayout/credit-card-layout.scss +63 -153
  32. package/src/features/payment-methods/components/AddPaymentMethodsDrawer/AddPaymentMethodsDrawer.tsx +58 -49
  33. package/src/features/payment-methods/components/AddPaymentMethodsDrawer/add-payment-methods-drawer.scss +58 -63
  34. package/src/features/payment-methods/layouts/PaymentMethodsLayout/PaymentMethodsLayout.tsx +15 -12
  35. package/src/features/roles/layout/RoleDetailsLayout/RoleDetailsLayout.tsx +57 -26
  36. package/src/features/roles/layout/RoleDetailsLayout/role-details-layout.scss +77 -0
  37. package/src/features/roles/layout/RolesLayout/RolesLayout.tsx +4 -12
  38. package/src/features/roles/layout/RolesLayout/roles-layout.scss +8 -22
  39. package/src/features/shared/components/CustomField/table/CustomFieldTable.tsx +67 -110
  40. package/src/features/shared/components/CustomField/table/custom-field-table.scss +39 -144
  41. package/src/features/shared/components/IconBookmarked/IconBookmarked.tsx +9 -0
  42. package/src/features/shared/components/IconBookmarked/icon-bookmarked.scss +9 -0
  43. package/src/features/shared/components/Table/Table.tsx +7 -2
  44. package/src/features/shared/components/Table/TableCell/TableCell.tsx +15 -3
  45. package/src/features/shared/components/Table/TableCell/table-cell.scss +34 -0
  46. package/src/features/shared/components/Table/TableHead/TableHead.tsx +34 -6
  47. package/src/features/shared/components/Table/TableHead/table-head.scss +53 -49
  48. package/src/features/shared/components/Table/TableLoading/TableLoading.tsx +16 -6
  49. package/src/features/shared/components/Table/TableLoading/table-loading.scss +13 -8
  50. package/src/features/shared/components/Table/TableRow/TableRow.tsx +65 -42
  51. package/src/features/shared/components/Table/TableRow/table-row.scss +104 -68
  52. package/src/features/shared/components/Table/table.scss +11 -6
  53. package/src/features/shared/components/Table/utils/tableColumns.ts +30 -33
  54. package/src/features/shared/components/index.ts +1 -0
  55. package/src/features/users/layouts/UsersLayout/UsersLayout.tsx +20 -27
  56. package/src/pages/budgets.tsx +1 -1
  57. package/src/pages/buying-policies.tsx +14 -1
  58. package/src/themes/layouts.scss +1 -0
@@ -1,128 +1,130 @@
1
- @import "../BudgetProgressBar/budget-progress-bar.scss";
2
1
  [data-fs-bp-budgets-table] {
3
- @import "@faststore/ui/src/components/molecules/Tooltip/styles.scss";
4
- width: 100%;
5
-
6
- [data-fs-table] {
7
- overflow-x: visible;
8
- }
9
- [data-fs-bp-table-row] {
10
- cursor: pointer;
11
- }
12
-
13
- [data-fs-bp-head-row] {
14
- border-bottom: var(--fs-table-bordered-border-width) solid
15
- var(--fs-table-bordered-border-color);
16
-
17
- color: #5c5c5c;
18
- height: var(--fs-spacing-8);
19
- }
20
-
21
- [data-fs-table-head="true"] {
22
- [data-fs-bp-head-row="true"] {
23
- &:hover {
24
- background-color: initial;
25
- }
26
- }
27
- }
28
-
29
- [data-fs-table-cell-content] {
30
- width: 99%;
31
- height: 1.875rem;
32
- }
33
-
34
- [data-fs-tooltip] {
35
- --fs-tooltip-background: #1f1f1f;
36
- border-bottom: none;
37
- text-wrap: balance;
38
- text-align: justify;
39
-
40
- [data-fs-tooltip-placement="left-center"] {
41
- [data-fs-tooltip-indicator="true"] {
42
- margin-left: -0.1%;
43
- }
44
- }
45
- [data-fs-tooltip-placement="top-center"] {
46
- [data-fs-tooltip-indicator="true"] {
47
- margin-top: -1%;
48
- }
49
- }
50
- }
51
-
52
- [data-fs-table-row] {
53
- height: var(--fs-spacing-8);
54
- cursor: pointer;
55
- padding: 0 var(--fs-spacing-4);
56
-
57
- &:hover {
58
- background-color: var(--fs-color-neutral-bkg);
59
- }
60
-
61
- [data-fs-table-cell="header"] {
62
- display: flex;
63
- height: var(--fs-spacing-8);
64
- cursor: pointer;
65
- align-items: center;
66
- }
67
-
68
- @include media("<tablet") {
69
- [data-fs-table-cell] {
70
- display: none;
71
-
72
- &:first-child {
73
- display: flex;
74
- }
75
-
76
- &:last-child {
77
- display: table-cell;
78
- padding-right: 0;
79
- }
80
- }
81
- }
82
-
83
- @include media("<notebook") {
84
- [data-fs-table-cell="data"]:not(:first-of-type) {
85
- text-align: right;
86
- }
87
-
88
- [data-fs-bp-cell-remaining] {
89
- opacity: 0;
90
- }
91
-
92
- [data-fs-bp-cell-currency] {
93
- display: none;
94
- }
95
- }
96
- }
97
- [data-fs-table-cell-width] {
98
- width: 13.75rem;
99
- }
100
-
101
- [data-fs-bp-text-medium] {
102
- font-weight: var(--fs-text-weight-medium);
103
- font-size: var(--fs-text-size-1);
104
- line-height: 20px;
105
- letter-spacing: -1%;
106
- }
107
-
108
- [data-fs-bp-budgets-dropdown-trigger] [data-fs-icon] {
109
- margin-right: 0;
110
- }
111
-
112
- [data-fs-bp-table-row-options] {
113
- width: var(--fs-spacing-8);
114
- }
115
-
116
- [data-fs-bp-icon-cell] {
117
- display: flex;
118
- align-items: center;
119
- height: inherit;
120
-
121
- &[data-fs-table-cell] {
122
- [data-fs-icon] {
123
- width: var(--fs-spacing-4);
124
- height: var(--fs-spacing-4);
125
- }
126
- }
127
- }
2
+ @import "../BudgetProgressBar/budget-progress-bar.scss";
3
+ @import "@faststore/ui/src/components/molecules/Tooltip/styles.scss";
4
+ @import "../../../shared/components/Table/table.scss";
5
+
6
+ width: 100%;
7
+
8
+ [data-fs-table] {
9
+ overflow-x: visible;
10
+ }
11
+ [data-fs-bp-table-row] {
12
+ cursor: pointer;
13
+ }
14
+
15
+ [data-fs-bp-head-row] {
16
+ border-bottom: var(--fs-table-bordered-border-width) solid
17
+ var(--fs-table-bordered-border-color);
18
+
19
+ color: #5c5c5c;
20
+ height: var(--fs-spacing-8);
21
+ }
22
+
23
+ [data-fs-table-head="true"] {
24
+ [data-fs-bp-head-row="true"] {
25
+ &:hover {
26
+ background-color: initial;
27
+ }
28
+ }
29
+ }
30
+
31
+ [data-fs-table-cell-content] {
32
+ width: 99%;
33
+ height: 1.875rem;
34
+ }
35
+
36
+ [data-fs-tooltip] {
37
+ --fs-tooltip-background: #1f1f1f;
38
+ border-bottom: none;
39
+ text-wrap: balance;
40
+ text-align: justify;
41
+
42
+ [data-fs-tooltip-placement="left-center"] {
43
+ [data-fs-tooltip-indicator="true"] {
44
+ margin-left: -0.1%;
45
+ }
46
+ }
47
+ [data-fs-tooltip-placement="top-center"] {
48
+ [data-fs-tooltip-indicator="true"] {
49
+ margin-top: -1%;
50
+ }
51
+ }
52
+ }
53
+
54
+ [data-fs-table-row] {
55
+ height: var(--fs-spacing-8);
56
+ cursor: pointer;
57
+ padding: 0 var(--fs-spacing-4);
58
+
59
+ &:hover {
60
+ background-color: var(--fs-color-neutral-bkg);
61
+ }
62
+
63
+ [data-fs-table-cell="header"] {
64
+ display: flex;
65
+ height: var(--fs-spacing-8);
66
+ cursor: pointer;
67
+ align-items: center;
68
+ }
69
+
70
+ @include media("<tablet") {
71
+ [data-fs-table-cell] {
72
+ display: none;
73
+
74
+ &:first-child {
75
+ display: flex;
76
+ }
77
+
78
+ &:last-child {
79
+ display: table-cell;
80
+ padding-right: 0;
81
+ }
82
+ }
83
+ }
84
+
85
+ @include media("<notebook") {
86
+ [data-fs-table-cell="data"]:not(:first-of-type) {
87
+ text-align: right;
88
+ }
89
+
90
+ [data-fs-bp-cell-remaining] {
91
+ opacity: 0;
92
+ }
93
+
94
+ [data-fs-bp-cell-currency] {
95
+ display: none;
96
+ }
97
+ }
98
+ }
99
+ [data-fs-table-cell-width] {
100
+ width: 13.75rem;
101
+ }
102
+
103
+ [data-fs-bp-text-medium] {
104
+ font-weight: var(--fs-text-weight-medium);
105
+ font-size: var(--fs-text-size-1);
106
+ line-height: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
107
+ letter-spacing: -1%;
108
+ }
109
+
110
+ [data-fs-bp-budgets-dropdown-trigger] [data-fs-icon] {
111
+ margin-right: 0;
112
+ }
113
+
114
+ [data-fs-bp-table-row-options] {
115
+ width: var(--fs-spacing-8);
116
+ }
117
+
118
+ [data-fs-bp-icon-cell] {
119
+ display: flex;
120
+ align-items: center;
121
+ height: inherit;
122
+
123
+ &[data-fs-table-cell] {
124
+ [data-fs-icon] {
125
+ width: var(--fs-spacing-4);
126
+ height: var(--fs-spacing-4);
127
+ }
128
+ }
129
+ }
128
130
  }
@@ -1,7 +1,5 @@
1
1
  import { useCallback, useState } from "react";
2
2
 
3
- import { useRouter } from "next/router";
4
-
5
3
  import { IconButton } from "@faststore/ui";
6
4
 
7
5
  import { HeaderInside, Icon, InternalSearch } from "../../../shared/components";
@@ -13,7 +11,6 @@ import {
13
11
  useQueryParams,
14
12
  } from "../../../shared/hooks";
15
13
  import { FinanceTabsLayout, GlobalLayout } from "../../../shared/layouts";
16
- import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
17
14
  import { BudgetDeleteDrawer } from "../../components/BudgetDeleteDrawer/BudgetDeleteDrawer";
18
15
  import { BudgetsTable } from "../../components/BudgetsTable/BudgetsTable";
19
16
  import { CreateBudgetAllocationDrawer } from "../../components/CreateBudgetAllocationDrawer/CreateBudgetAllocationDrawer";
@@ -41,7 +38,6 @@ export const BudgetsLayout = ({ data }: BudgetsLayoutProps) => {
41
38
  currentOrgUnit: orgUnit,
42
39
  currentContract: contract,
43
40
  } = useBuyerPortal();
44
- const route = useRouter();
45
41
  const [paginationLoading, setPaginationLoading] = useState<boolean>(false);
46
42
  const [loading, setLoading] = useState<boolean>(false);
47
43
  const [page, setPage] = useState<number>(1);
@@ -54,16 +50,6 @@ export const BudgetsLayout = ({ data }: BudgetsLayoutProps) => {
54
50
  useState<BudgetAllocationListResponse>();
55
51
  const [budgetsToEdit, setBudgetToEdit] = useState<Budget>();
56
52
 
57
- const handleEditPage = (budgetId: string) => {
58
- route.push(
59
- buyerPortalRoutes.budgetsDetails({
60
- orgUnitId: orgUnit?.id ?? "",
61
- contractId: contract?.id ?? "",
62
- budgetId,
63
- })
64
- );
65
- };
66
-
67
53
  const {
68
54
  open: openDeleteDrawer,
69
55
  close: closeDeleteDrawer,
@@ -186,7 +172,6 @@ export const BudgetsLayout = ({ data }: BudgetsLayoutProps) => {
186
172
  total={Number(total ?? 0)}
187
173
  onClickAllocationPage={handleAddAllocation}
188
174
  onClickEditBudget={handleBudgetEditPage}
189
- onClickDetailsPage={handleEditPage}
190
175
  openDeleteDrawer={(budgetId) => {
191
176
  setSelectedBudgetId(budgetId);
192
177
  openDeleteDrawer();
@@ -7,6 +7,7 @@ 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";
10
11
  import type { BuyingPolicy } from "../../types";
11
12
 
12
13
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -19,6 +20,7 @@ export type AddBuyingPolicyDrawerProps = Omit<
19
20
  onCreate?: () => void;
20
21
  orgUnitId: string;
21
22
  contractId: string;
23
+ budgetData?: BudgetListResponse;
22
24
  };
23
25
 
24
26
  export const AddBuyingPolicyDrawer = ({
@@ -26,6 +28,7 @@ export const AddBuyingPolicyDrawer = ({
26
28
  onCreate,
27
29
  orgUnitId,
28
30
  contractId,
31
+ budgetData = { data: [], total: 0 },
29
32
  ...props
30
33
  }: AddBuyingPolicyDrawerProps) => {
31
34
  const { pushToast } = useUI();
@@ -85,6 +88,7 @@ export const AddBuyingPolicyDrawer = ({
85
88
  orgUnitId={orgUnitId}
86
89
  contractId={contractId}
87
90
  initialValues={defaultBuyingPolicyValues}
91
+ budgetData={budgetData}
88
92
  {...props}
89
93
  />
90
94
  );
@@ -23,11 +23,15 @@ import { type BuyingPolicy } from "../../types";
23
23
  import {
24
24
  BUYING_POLICIES_WORKFLOW_TYPES,
25
25
  buyingPolicyDefault,
26
+ BUDGET_CRITERIA,
26
27
  orderFieldsCriteriaOptions,
27
28
  spendingLimitsCriteriaOptions,
28
29
  } from "../../utils";
29
30
  import { BUYING_POLICIES_WORKFLOW_LABELS } from "../../utils/buyingPoliciesWorkflowTypes";
30
31
  import { getHighlightedText } from "../../utils/criteriaHighlightSyntax";
32
+ import { BudgetCriteriaSelector } from "../BudgetCriteriaSelector";
33
+
34
+ import type { BudgetListResponse } from "../../../budgets/types";
31
35
 
32
36
  const LIMIT_OF_LEVELS = 5;
33
37
 
@@ -50,6 +54,7 @@ export type BasicBuyingPolicyDrawerProps = Omit<
50
54
  drawerTitle?: string;
51
55
  saveButtonLabel?: string;
52
56
  isDrawerLoading?: boolean;
57
+ budgetData?: BudgetListResponse;
53
58
  };
54
59
 
55
60
  export const BasicBuyingPolicyDrawer = ({
@@ -62,6 +67,7 @@ export const BasicBuyingPolicyDrawer = ({
62
67
  orgUnitId,
63
68
  contractId,
64
69
  initialValues = defaultBuyingPolicyValues,
70
+ budgetData = { data: [], total: 0 },
65
71
  ...props
66
72
  }: BasicBuyingPolicyDrawerProps) => {
67
73
  const [form, setForm] = useState<BuyingPolicyForm>(initialValues);
@@ -167,6 +173,27 @@ export const BasicBuyingPolicyDrawer = ({
167
173
  });
168
174
  };
169
175
 
176
+ const isBudgetCriteria =
177
+ criteria === BUDGET_CRITERIA ||
178
+ criteria.includes('$exists(budgetData.unitAllocations.*[budgetId="');
179
+
180
+ const renderCriteria = (criteria: string) => {
181
+ if (isBudgetCriteria) {
182
+ return (
183
+ <BudgetCriteriaSelector
184
+ budgetData={budgetData}
185
+ currentCriteria={criteria}
186
+ onCriteriaChange={(newCriteria) =>
187
+ updateField("criteria", newCriteria)
188
+ }
189
+ onEditablePartClick={() => setCriteriaFocused(true)}
190
+ />
191
+ );
192
+ }
193
+
194
+ return getHighlightedText(criteria);
195
+ };
196
+
170
197
  const isConfirmButtonEnabled = isAllFieldsFilled && !isLoading;
171
198
 
172
199
  return (
@@ -258,10 +285,14 @@ export const BasicBuyingPolicyDrawer = ({
258
285
  {!criteriaFocused && (
259
286
  <div
260
287
  data-fs-bp-basic-buying-policy-criteria-input-highlighted
261
- onClick={() => setCriteriaFocused(true)}
288
+ onClick={() => {
289
+ if (!isBudgetCriteria) {
290
+ setCriteriaFocused(true);
291
+ }
292
+ }}
262
293
  >
263
294
  {criteria ? (
264
- getHighlightedText(criteria)
295
+ renderCriteria(criteria)
265
296
  ) : (
266
297
  <span data-fs-bp-label>Example: value {">"} 10000</span>
267
298
  )}
@@ -280,7 +311,7 @@ export const BasicBuyingPolicyDrawer = ({
280
311
  label: option.label,
281
312
  value: option.criteria,
282
313
  }))}
283
- onSelect={(value) => updateField("criteria", value)}
314
+ onSelect={(value: string) => updateField("criteria", value)}
284
315
  triggerLabel="Set spending limit criteria"
285
316
  highlightText={getHighlightedText}
286
317
  />
@@ -290,7 +321,7 @@ export const BasicBuyingPolicyDrawer = ({
290
321
  label: option.label,
291
322
  value: option.criteria,
292
323
  }))}
293
- onSelect={(value) => updateField("criteria", value)}
324
+ onSelect={(value: string) => updateField("criteria", value)}
294
325
  triggerLabel="Set order field criteria"
295
326
  highlightText={getHighlightedText}
296
327
  />
@@ -1,6 +1,7 @@
1
1
  @import "../../../shared/components/BasicDrawer/basic-drawer.scss";
2
2
  @import "../../../shared/components/OrgUnitInputSearch/org-unit-input-search.scss";
3
3
  @import "../../../shared/components/CustomDropdown/custom-dropdown.scss";
4
+ @import "../BudgetCriteriaSelector/budget-criteria-selector.scss";
4
5
 
5
6
  [data-fs-bp-basic-buying-policy-drawer] {
6
7
  @import "../../../shared/components/InputText/input-text.scss";
@@ -105,7 +106,6 @@
105
106
  var(--fs-spacing-3);
106
107
  border-radius: calc(var(--fs-border-radius) * 2);
107
108
  text-wrap: nowrap;
108
- overflow: hidden;
109
109
  text-overflow: ellipsis;
110
110
  white-space: nowrap;
111
111
  cursor: pointer;
@@ -124,6 +124,7 @@
124
124
  }
125
125
  }
126
126
 
127
+
127
128
  [data-fs-bp-input-text-criteria] {
128
129
  color: #5c5c5c;
129
130
 
@@ -0,0 +1,113 @@
1
+ import { useState, useEffect } from "react";
2
+
3
+ import { CustomDropdown } from "../../../shared/components/CustomDropdown/CustomDropdown";
4
+
5
+ import type { BudgetListResponse } from "../../../budgets/types";
6
+
7
+ export type BudgetCriteriaSelectorProps = {
8
+ onCriteriaChange: (criteria: string) => void;
9
+ currentCriteria: string;
10
+ onEditablePartClick?: () => void;
11
+ budgetData?: BudgetListResponse;
12
+ };
13
+
14
+ export const BudgetCriteriaSelector = ({
15
+ onCriteriaChange,
16
+ currentCriteria,
17
+ onEditablePartClick,
18
+ budgetData = { data: [], total: 0 },
19
+ }: BudgetCriteriaSelectorProps) => {
20
+ const extractBudgetValueFromCriteria = (criteria: string): string => {
21
+ const match = criteria.match(/budgetId="([^"]+)"/);
22
+ return match ? match[1] : "budget-001";
23
+ };
24
+
25
+ const [currentBudgetValue, setCurrentBudgetValue] = useState<string>(
26
+ extractBudgetValueFromCriteria(currentCriteria)
27
+ );
28
+
29
+ useEffect(() => {
30
+ const extractedValue = extractBudgetValueFromCriteria(currentCriteria);
31
+ setCurrentBudgetValue(extractedValue);
32
+ }, [currentCriteria]);
33
+
34
+ const getMatchingBudget = () => {
35
+ return budgetData.data.find(
36
+ (budget) =>
37
+ budget.id === currentBudgetValue || budget.id === currentBudgetValue
38
+ );
39
+ };
40
+
41
+ const generateCriteriaString = (value: string) => {
42
+ return `$exists(budgetData.unitAllocations.*[budgetId="${value}"])`;
43
+ };
44
+
45
+ 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
+ }
55
+ };
56
+
57
+ const handleBudgetSelectorClick = (e: React.MouseEvent) => {
58
+ e.stopPropagation();
59
+ };
60
+
61
+ const handleEditablePartClick = (e: React.MouseEvent) => {
62
+ e.stopPropagation();
63
+ onEditablePartClick?.();
64
+ };
65
+
66
+ const matchingBudget = getMatchingBudget();
67
+ const displayValue = matchingBudget ? matchingBudget.id : currentBudgetValue;
68
+ const hasBudgetData = budgetData.data.length > 0;
69
+
70
+ return (
71
+ <div
72
+ data-fs-bp-budget-criteria-selector
73
+ onClick={handleBudgetSelectorClick}
74
+ >
75
+ <div data-fs-bp-budget-criteria-string>
76
+ <span onClick={handleEditablePartClick} data-fs-bp-editable-part>
77
+ $exists(budgetData.unitAllocations.*[budgetId="
78
+ </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
+ <div data-fs-bp-dropdown-option-uuid>
92
+ {budgetData.data.find((b) => b.name === text)?.id}
93
+ </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
+ )}
107
+ <span onClick={handleEditablePartClick} data-fs-bp-editable-part>
108
+ "])
109
+ </span>
110
+ </div>
111
+ </div>
112
+ );
113
+ };