@vtex/faststore-plugin-buyer-portal 1.3.21 → 1.3.23
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 +16 -2
- package/package.json +1 -1
- package/src/features/buying-policies/components/AddBuyingPolicyDrawer/AddBuyingPolicyDrawer.tsx +0 -4
- package/src/features/buying-policies/components/BasicBuyingPolicyDrawer/BasicBuyingPolicyDrawer.tsx +0 -5
- package/src/features/buying-policies/components/BudgetCriteriaSelector/BudgetCriteriaSelector.tsx +58 -54
- package/src/features/buying-policies/components/BuyingPolicyDropdownMenu/BuyingPolicyDropdownMenu.tsx +0 -5
- package/src/features/buying-policies/components/UpdateBuyingPolicyDrawer/UpdateBuyingPolicyDrawer.tsx +0 -5
- package/src/features/buying-policies/hooks/useGetBudgets.ts +35 -0
- package/src/features/buying-policies/layouts/BuyingPoliciesLayout/BuyingPoliciesLayout.tsx +0 -5
- package/src/features/org-units/components/DeleteOrgUnitDrawer/DeleteOrgUnitDrawer.tsx +8 -4
- package/src/features/shared/components/CustomDropdown/CustomDropdown.tsx +9 -1
- package/src/features/shared/hooks/useQuery.ts +3 -1
- package/src/features/shared/utils/constants.ts +1 -1
- package/src/features/users/hooks/useGetUserByOrgUnitId.ts +20 -0
- 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.23] - 2025-11-25
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Refactor logic of fetching budgets to be handled by a new custom hook
|
|
15
|
+
|
|
16
|
+
## [1.3.22] - 2025-11-21
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Add validation to prevent Org Unit deletion if it has users
|
|
21
|
+
|
|
10
22
|
## [1.3.21] - 2025-11-05
|
|
11
23
|
|
|
12
24
|
### Removed
|
|
@@ -138,8 +150,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
138
150
|
## [1.2.4] - 2025-10-16
|
|
139
151
|
|
|
140
152
|
### Added
|
|
141
|
-
- Responsiviness adjustment to to Buying policies page
|
|
142
153
|
|
|
154
|
+
- Responsiviness adjustment to to Buying policies page
|
|
143
155
|
|
|
144
156
|
### Added
|
|
145
157
|
|
|
@@ -229,7 +241,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
229
241
|
- Add CHANGELOG file
|
|
230
242
|
- Add README file
|
|
231
243
|
|
|
232
|
-
[unreleased]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.
|
|
244
|
+
[unreleased]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.23...HEAD
|
|
233
245
|
[1.2.3]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.2.2...1.2.3
|
|
234
246
|
[1.2.3]: https://github.com/vtex/faststore-plugin-buyer-portal/releases/tag/1.2.3
|
|
235
247
|
[1.2.4]: https://github.com/vtex/faststore-plugin-buyer-portal/releases/tag/1.2.4
|
|
@@ -244,6 +256,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
244
256
|
|
|
245
257
|
# <<<<<<< HEAD
|
|
246
258
|
|
|
259
|
+
[1.3.23]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.22...v1.3.23
|
|
260
|
+
[1.3.22]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.21...v1.3.22
|
|
247
261
|
[1.3.21]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.20...v1.3.21
|
|
248
262
|
[1.3.20]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.19...v1.3.20
|
|
249
263
|
[1.3.19]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.18...v1.3.19
|
package/package.json
CHANGED
package/src/features/buying-policies/components/AddBuyingPolicyDrawer/AddBuyingPolicyDrawer.tsx
CHANGED
|
@@ -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
|
);
|
package/src/features/buying-policies/components/BasicBuyingPolicyDrawer/BasicBuyingPolicyDrawer.tsx
CHANGED
|
@@ -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)
|
package/src/features/buying-policies/components/BudgetCriteriaSelector/BudgetCriteriaSelector.tsx
CHANGED
|
@@ -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
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
);
|
|
49
|
-
if (selectedBudget)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
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
|
|
67
|
-
|
|
68
|
-
const
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
{
|
|
103
|
+
{budgets.data.find((b) => b.name === text)?.id}
|
|
93
104
|
</div>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
)}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
InputText,
|
|
12
12
|
type BasicDrawerProps,
|
|
13
13
|
} from "../../../shared/components";
|
|
14
|
+
import { useGetUserByOrgUnitId } from "../../../users/hooks/useGetUserByOrgUnitId";
|
|
14
15
|
import { useChildrenOrgUnits } from "../../hooks";
|
|
15
16
|
import { useDeleteOrgUnit } from "../../hooks/useDeleteOrgUnit";
|
|
16
17
|
|
|
@@ -28,12 +29,14 @@ export const DeleteOrgUnitDrawer = ({
|
|
|
28
29
|
}: DeleteOrgUnitDrawerProps) => {
|
|
29
30
|
const router = useRouter();
|
|
30
31
|
const { childrenOrgUnits } = useChildrenOrgUnits(id, name);
|
|
32
|
+
const { users } = useGetUserByOrgUnitId(id);
|
|
31
33
|
const { pushToast } = useUI();
|
|
32
34
|
|
|
33
35
|
const [confirmName, setConfirmName] = useState("");
|
|
34
36
|
const [isTouched, setIsTouched] = useState(false);
|
|
35
37
|
|
|
36
|
-
const hasChildren =
|
|
38
|
+
const hasChildren =
|
|
39
|
+
Boolean(childrenOrgUnits?.nodes?.length) || Boolean(users?.length);
|
|
37
40
|
|
|
38
41
|
const handleDeleteOrgUnitSuccess = () => {
|
|
39
42
|
pushToast({
|
|
@@ -111,13 +114,14 @@ export const DeleteOrgUnitDrawer = ({
|
|
|
111
114
|
<span data-fs-bp-delete-org-unit-drawer-message-name>
|
|
112
115
|
{` ${name} `}
|
|
113
116
|
</span>
|
|
114
|
-
, you must first remove all child organizational units
|
|
117
|
+
, you must first remove all child organizational units{" "}
|
|
118
|
+
{users?.length ? "and users" : ""}.
|
|
115
119
|
<br />
|
|
116
120
|
Please delete them individually, starting from the lowest level.
|
|
117
121
|
<br />
|
|
118
122
|
<br />
|
|
119
|
-
Once all child units
|
|
120
|
-
{name}.
|
|
123
|
+
Once all child units {users?.length ? "and users" : ""} bellow are
|
|
124
|
+
removed, you’ll be able to delete {name}.
|
|
121
125
|
</p>
|
|
122
126
|
|
|
123
127
|
<span data-fs-bp-delete-org-unit-drawer-subtitle>
|
|
@@ -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>(
|
|
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 () => {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type QueryOptions, useQuery } from "../../shared/hooks";
|
|
2
|
+
import { getUsersByOrgUnitIdService } from "../services";
|
|
3
|
+
|
|
4
|
+
export const useGetUserByOrgUnitId = (
|
|
5
|
+
orgUnitId: string,
|
|
6
|
+
options?: QueryOptions<AwaitedType<typeof getUsersByOrgUnitIdService>>
|
|
7
|
+
) => {
|
|
8
|
+
const { data, error, isLoading, refetch } = useQuery(
|
|
9
|
+
`org-unit/user/${orgUnitId}`,
|
|
10
|
+
({ cookie }) => getUsersByOrgUnitIdService({ orgUnitId, cookie }),
|
|
11
|
+
options
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
users: data?.users,
|
|
16
|
+
hasUserError: error,
|
|
17
|
+
isUserLoading: isLoading,
|
|
18
|
+
refetchUser: refetch,
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
</>
|