@vtex/faststore-plugin-buyer-portal 1.3.27 → 1.3.28

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 (34) hide show
  1. package/CHANGELOG.md +8 -2
  2. package/package.json +1 -1
  3. package/src/features/addresses/components/AddRecipientsDrawer/AddRecipientsDrawer.tsx +20 -2
  4. package/src/features/addresses/components/CreateAddressDrawer/CreateAddressDrawer.tsx +50 -4
  5. package/src/features/addresses/components/DeleteAddressDrawer/DeleteAddressDrawer.tsx +26 -2
  6. package/src/features/addresses/components/DeleteAddressLocationDrawer/DeleteAddressLocationDrawer.tsx +29 -3
  7. package/src/features/addresses/components/DeleteRecipientAddressDrawer/DeleteRecipientAddressDrawer.tsx +24 -2
  8. package/src/features/addresses/components/EditAddressDrawer/EditAddressDrawer.tsx +28 -2
  9. package/src/features/addresses/components/EditAddressLocationDrawer/EditAddressLocationDrawer.tsx +30 -4
  10. package/src/features/addresses/components/EditRecipientAddressDrawer/EditRecipientAddressDrawer.tsx +30 -2
  11. package/src/features/addresses/components/LocationsDrawer/LocationsDrawer.tsx +29 -2
  12. package/src/features/budgets/components/BudgetDeleteDrawer/BudgetDeleteDrawer.tsx +32 -4
  13. package/src/features/budgets/components/CreateBudgetDrawer/CreateBudgetDrawer.tsx +59 -4
  14. package/src/features/budgets/components/EditBudgetDrawer/EditBudgetDrawer.tsx +28 -1
  15. package/src/features/buying-policies/components/AddBuyingPolicyDrawer/AddBuyingPolicyDrawer.tsx +48 -5
  16. package/src/features/buying-policies/components/DeleteBuyingPolicyDrawer/DeleteBuyingPolicyDrawer.tsx +28 -2
  17. package/src/features/buying-policies/components/UpdateBuyingPolicyDrawer/UpdateBuyingPolicyDrawer.tsx +49 -5
  18. package/src/features/custom-fields/components/CreateCustomFieldValueDrawer/CreateCustomFieldValueDrawer.tsx +60 -5
  19. package/src/features/custom-fields/components/DeleteCustomFieldValueDrawer/DeleteCustomFieldValueDrawer.tsx +61 -5
  20. package/src/features/custom-fields/components/UpdateCustomFieldValueDrawer/UpdateCustomFieldValueDrawer.tsx +32 -3
  21. package/src/features/org-units/components/CreateOrgUnitDrawer/CreateOrgUnitDrawer.tsx +18 -0
  22. package/src/features/org-units/components/DeleteOrgUnitDrawer/DeleteOrgUnitDrawer.tsx +28 -0
  23. package/src/features/org-units/components/UpdateOrgUnitDrawer/UpdateOrgUnitDrawer.tsx +28 -0
  24. package/src/features/shared/hooks/analytics/types.ts +14 -0
  25. package/src/features/shared/hooks/analytics/useAnalytics.ts +249 -0
  26. package/src/features/shared/hooks/index.ts +1 -0
  27. package/src/features/shared/services/logger/analytics/analytics.ts +101 -0
  28. package/src/features/shared/services/logger/analytics/constants.ts +83 -0
  29. package/src/features/shared/services/logger/analytics/types.ts +108 -0
  30. package/src/features/shared/services/logger/index.ts +1 -0
  31. package/src/features/shared/utils/constants.ts +1 -1
  32. package/src/features/users/components/CreateUserDrawer/CreateUserDrawer.tsx +24 -0
  33. package/src/features/users/components/DeleteUserDrawer/DeleteUserDrawer.tsx +23 -2
  34. package/src/features/users/components/UpdateUserDrawer/UpdateUserDrawer.tsx +45 -4
@@ -1,4 +1,4 @@
1
- import { useCallback, useState } from "react";
1
+ import { useCallback, useEffect, useState } from "react";
2
2
 
3
3
  import { useRouter } from "next/router";
4
4
 
@@ -9,7 +9,8 @@ import {
9
9
  Icon,
10
10
  type BasicDrawerProps,
11
11
  } from "../../../shared/components";
12
- import { useBuyerPortal } from "../../../shared/hooks";
12
+ import { useAnalytics, useBuyerPortal } from "../../../shared/hooks";
13
+ import { ANALYTICS_EVENTS } from "../../../shared/services/logger/analytics/constants";
13
14
  import { sortingOptionsAllocations } from "../../../shared/utils";
14
15
  import { parseAmount } from "../../../shared/utils/budgetAmountParse";
15
16
  import { getKeyByValue } from "../../../shared/utils/getKeyByValue";
@@ -65,6 +66,12 @@ export const CreateBudgetDrawer = ({
65
66
  } = useBuyerPortal();
66
67
  const router = useRouter();
67
68
  const { pushToast } = useUI();
69
+ const { trackEvent, trackEntityCreated, trackEntityCreateError } =
70
+ useAnalytics({
71
+ entityType: "budget",
72
+ defaultTimerName: "budget_creation",
73
+ shouldTrackDefaultTimer: true,
74
+ });
68
75
 
69
76
  const {
70
77
  filter,
@@ -86,6 +93,21 @@ export const CreateBudgetDrawer = ({
86
93
 
87
94
  type DrawerStep = "form" | "allocations" | "confirmation";
88
95
  const [step, setStep] = useState<DrawerStep>("form");
96
+ const [previousStep, setPreviousStep] = useState<DrawerStep | null>(null);
97
+
98
+ useEffect(() => {
99
+ if (previousStep !== null && previousStep !== step) {
100
+ trackEvent(ANALYTICS_EVENTS.BUDGET_STEP_TIMING, {
101
+ flow_name: "budget_creation",
102
+ from_step: previousStep,
103
+ to_step: step,
104
+ step_name: step,
105
+ org_unit_id: unitId,
106
+ contract_id: contractId,
107
+ });
108
+ }
109
+ setPreviousStep(step);
110
+ }, [step, previousStep, trackEvent, unitId, contractId]);
89
111
 
90
112
  const [budget, setBudget] = useState<BudgetInput>({
91
113
  name: "",
@@ -132,6 +154,16 @@ export const CreateBudgetDrawer = ({
132
154
  return;
133
155
  }
134
156
 
157
+ // Track successful budget creation
158
+ trackEntityCreated(ANALYTICS_EVENTS.BUDGET_CREATED, "budget", {
159
+ budget_name: budget.name,
160
+ amount: budget.amount,
161
+ has_notifications: Boolean(budget.notifications?.hasNotification),
162
+ allocations_count: selectedAllocations.length,
163
+ org_unit_id: unitId,
164
+ contract_id: contractId,
165
+ });
166
+
135
167
  pushToast({
136
168
  message: "Budget added successfully.",
137
169
  status: "INFO",
@@ -139,8 +171,14 @@ export const CreateBudgetDrawer = ({
139
171
  close();
140
172
  router.reload();
141
173
  },
142
- onError: (error: Error) =>
143
- pushToast({ message: error.message, status: "ERROR" }),
174
+ onError: (error: Error) => {
175
+ trackEntityCreateError(ANALYTICS_EVENTS.BUDGET_CREATE_ERROR, error, {
176
+ org_unit_id: unitId,
177
+ contract_id: contractId,
178
+ });
179
+
180
+ pushToast({ message: error.message, status: "ERROR" });
181
+ },
144
182
  },
145
183
  }
146
184
  );
@@ -149,6 +187,18 @@ export const CreateBudgetDrawer = ({
149
187
  useUpdateBudget({
150
188
  options: {
151
189
  onSuccess: () => {
190
+ // Track successful budget creation (with policy)
191
+ if (firstBudget) {
192
+ trackEntityCreated(ANALYTICS_EVENTS.BUDGET_CREATED, "budget", {
193
+ budget_name: budget.name,
194
+ amount: budget.amount,
195
+ has_notifications: Boolean(budget.notifications?.hasNotification),
196
+ has_policy: true,
197
+ org_unit_id: unitId,
198
+ contract_id: contractId,
199
+ });
200
+ }
201
+
152
202
  pushToast({
153
203
  message: "Budget added successfully.",
154
204
  status: "INFO",
@@ -167,6 +217,11 @@ export const CreateBudgetDrawer = ({
167
217
  router.reload();
168
218
  },
169
219
  onError: (error: Error) => {
220
+ trackEntityCreateError(ANALYTICS_EVENTS.BUDGET_CREATE_ERROR, error, {
221
+ org_unit_id: unitId,
222
+ contract_id: contractId,
223
+ });
224
+
170
225
  pushToast({
171
226
  message: error?.message || "An error occurred. Please try again.",
172
227
  status: "ERROR",
@@ -5,7 +5,8 @@ import { useRouter } from "next/router";
5
5
  import { useUI } from "@faststore/ui";
6
6
 
7
7
  import { BasicDrawer, type BasicDrawerProps } from "../../../shared/components";
8
- import { useBuyerPortal } from "../../../shared/hooks";
8
+ import { useAnalytics, useBuyerPortal } from "../../../shared/hooks";
9
+ import { ANALYTICS_EVENTS } from "../../../shared/services/logger/analytics/constants";
9
10
  import { parseAmount } from "../../../shared/utils/budgetAmountParse";
10
11
  import { useUpdateBudget } from "../../hooks";
11
12
  import { BudgetAddForm } from "../BudgetAddForm/BudgetAddForm";
@@ -75,6 +76,12 @@ export const EditBudgetDrawer = ({
75
76
  const { clientContext } = useBuyerPortal();
76
77
  const { pushToast } = useUI();
77
78
  const router = useRouter();
79
+ const { trackEntityEdited, trackEntityEditError } = useAnalytics({
80
+ entityType: "budget",
81
+ entityId: budgetId,
82
+ defaultTimerName: "budget_edit",
83
+ shouldTrackDefaultTimer: true,
84
+ });
78
85
 
79
86
  const [budget, setBudget] = useState<BudgetInput>(() =>
80
87
  getInitialBudget(initialBudget)
@@ -86,12 +93,32 @@ export const EditBudgetDrawer = ({
86
93
  const { mutate: updateBudget, isLoading } = useUpdateBudget({
87
94
  options: {
88
95
  onSuccess: () => {
96
+ trackEntityEdited(ANALYTICS_EVENTS.BUDGET_EDITED, {
97
+ budget_id: budgetId,
98
+ budget_name: budget.name,
99
+ amount: budget.amount,
100
+ has_notifications: Boolean(budget.notifications?.hasNotification),
101
+ org_unit_id: orgUnitId,
102
+ contract_id: contractId,
103
+ });
104
+
89
105
  pushToast({ message: "Budget updated successfully.", status: "INFO" });
90
106
  onSubmit?.(budget);
91
107
  close();
92
108
  router.reload();
93
109
  },
94
110
  onError: (error: Error) => {
111
+ trackEntityEditError(
112
+ ANALYTICS_EVENTS.BUDGET_EDIT_ERROR,
113
+ "budget",
114
+ budgetId,
115
+ error,
116
+ {
117
+ org_unit_id: orgUnitId,
118
+ contract_id: contractId,
119
+ }
120
+ );
121
+
95
122
  pushToast({
96
123
  message: error?.message || "An error occurred. Please try again.",
97
124
  status: "ERROR",
@@ -1,13 +1,21 @@
1
+ import { useRef } from "react";
2
+
1
3
  import { useRouter } from "next/router";
2
4
 
3
5
  import { useUI } from "@faststore/ui";
4
6
 
5
7
  import { BasicBuyingPolicyDrawer, type BasicBuyingPolicyDrawerProps } from "..";
8
+ import { useAnalytics } from "../../../shared/hooks";
9
+ import { ANALYTICS_EVENTS } from "../../../shared/services/logger/analytics/constants";
6
10
  import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
7
11
  import { useAddBuyingPolicy } from "../../hooks";
8
- import { buyingPolicyDefault } from "../../utils";
12
+ import {
13
+ buyingPolicyDefault,
14
+ BUYING_POLICIES_WORKFLOW_TYPES,
15
+ } from "../../utils";
9
16
 
10
17
  import type { BuyingPolicy } from "../../types";
18
+ import type { BuyingPolicyForm } from "../BasicBuyingPolicyDrawer/BasicBuyingPolicyDrawer";
11
19
 
12
20
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
13
21
  const { id, ...defaultBuyingPolicyValues } = buyingPolicyDefault;
@@ -30,8 +38,33 @@ export const AddBuyingPolicyDrawer = ({
30
38
  }: AddBuyingPolicyDrawerProps) => {
31
39
  const { pushToast } = useUI();
32
40
  const router = useRouter();
41
+ const { trackEntityCreated, trackEntityCreateError } = useAnalytics({
42
+ entityType: "buying_policy",
43
+ defaultTimerName: "buying_policy_creation",
44
+ shouldTrackDefaultTimer: true,
45
+ });
46
+ const formDataRef = useRef<BuyingPolicyForm | null>(null);
33
47
 
34
48
  const handleAddBuyingPolicySuccess = (data: BuyingPolicy) => {
49
+ const formData = formDataRef.current;
50
+
51
+ trackEntityCreated(
52
+ ANALYTICS_EVENTS.BUYING_POLICY_CREATED,
53
+ "buying_policy",
54
+ {
55
+ policy_name: formData?.name,
56
+ policy_description: formData?.description,
57
+ policy_criteria: formData?.criteria,
58
+ policy_type: formData?.action.type,
59
+ ...(formData?.action.type ===
60
+ BUYING_POLICIES_WORKFLOW_TYPES.SEQUENTIAL_WORKFLOW && {
61
+ approval_levels_count: formData?.action.levels?.length,
62
+ }),
63
+ org_unit_id: orgUnitId,
64
+ contract_id: contractId,
65
+ }
66
+ );
67
+
35
68
  pushToast({
36
69
  message: "Buying policy added successfully",
37
70
  status: "INFO",
@@ -60,7 +93,16 @@ export const AddBuyingPolicyDrawer = ({
60
93
 
61
94
  const { addBuyingPolicy, isAddBuyingPolicyLoading } = useAddBuyingPolicy({
62
95
  onSuccess: handleAddBuyingPolicySuccess,
63
- onError: () => {
96
+ onError: (error) => {
97
+ trackEntityCreateError(
98
+ ANALYTICS_EVENTS.BUYING_POLICY_CREATE_ERROR,
99
+ error,
100
+ {
101
+ org_unit_id: orgUnitId,
102
+ contract_id: contractId,
103
+ }
104
+ );
105
+
64
106
  pushToast({
65
107
  message: "An error occurred. Please try again.",
66
108
  title: "Error",
@@ -73,15 +115,16 @@ export const AddBuyingPolicyDrawer = ({
73
115
  <BasicBuyingPolicyDrawer
74
116
  close={close}
75
117
  isLoading={isAddBuyingPolicyLoading}
76
- onConfirm={(form) =>
118
+ onConfirm={(form) => {
119
+ formDataRef.current = form;
77
120
  addBuyingPolicy({
78
121
  buyingPolicy: {
79
122
  ...form,
80
123
  },
81
124
  orgUnitId,
82
125
  contractId,
83
- })
84
- }
126
+ });
127
+ }}
85
128
  orgUnitId={orgUnitId}
86
129
  contractId={contractId}
87
130
  initialValues={defaultBuyingPolicyValues}
@@ -7,7 +7,8 @@ import {
7
7
  InputText,
8
8
  type BasicDrawerProps,
9
9
  } from "../../../shared/components";
10
- import { useBuyerPortal } from "../../../shared/hooks";
10
+ import { useAnalytics, useBuyerPortal } from "../../../shared/hooks";
11
+ import { ANALYTICS_EVENTS } from "../../../shared/services/logger/analytics/constants";
11
12
  import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
12
13
  import { useRemoveBuyingPolicy } from "../../hooks";
13
14
 
@@ -32,8 +33,22 @@ export const DeleteBuyingPolicyDrawer = ({
32
33
  const { currentContract, currentOrgUnit } = useBuyerPortal();
33
34
 
34
35
  const { pushToast } = useUI();
36
+ const { trackEvent } = useAnalytics({
37
+ entityType: "buying_policy",
38
+ entityId: buyingPolicy.id,
39
+ defaultTimerName: "buying_policy_delete",
40
+ shouldTrackDefaultTimer: true,
41
+ });
35
42
 
36
43
  const handleRemoveSuccess = () => {
44
+ trackEvent(ANALYTICS_EVENTS.BUYING_POLICY_DELETED, {
45
+ policy_id: buyingPolicy.id,
46
+ policy_name: buyingPolicy.name,
47
+ org_unit_id: currentOrgUnit?.id,
48
+ contract_id: currentContract?.id,
49
+ entity_type: "buying_policy",
50
+ });
51
+
37
52
  pushToast({
38
53
  message: "Buying policy deleted successfully",
39
54
  status: "INFO",
@@ -57,7 +72,18 @@ export const DeleteBuyingPolicyDrawer = ({
57
72
  const { removeBuyingPolicy, isRemoveBuyingPolicyLoading } =
58
73
  useRemoveBuyingPolicy({
59
74
  onSuccess: handleRemoveSuccess,
60
- onError: () => {
75
+ onError: (error) => {
76
+ const errorMessage = typeof error === "string" ? error : error.message;
77
+
78
+ trackEvent(ANALYTICS_EVENTS.BUYING_POLICY_DELETE_ERROR, {
79
+ entity_type: "buying_policy",
80
+ entity_id: buyingPolicy.id,
81
+ policy_name: buyingPolicy.name,
82
+ org_unit_id: currentOrgUnit?.id,
83
+ contract_id: currentContract?.id,
84
+ error_message: errorMessage,
85
+ });
86
+
61
87
  pushToast({
62
88
  message: "An error occurred. Please try again.",
63
89
  title: "Error",
@@ -1,11 +1,20 @@
1
+ import { useRef } from "react";
2
+
1
3
  import { useRouter } from "next/router";
2
4
 
3
5
  import { useUI } from "@faststore/ui";
4
6
 
5
7
  import { BasicBuyingPolicyDrawer, type BasicBuyingPolicyDrawerProps } from "..";
8
+ import { useAnalytics } from "../../../shared/hooks";
9
+ import { ANALYTICS_EVENTS } from "../../../shared/services/logger/analytics/constants";
6
10
  import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
7
11
  import { useGetBuyingPolicy, useUpdateBuyingPolicy } from "../../hooks";
8
- import { buyingPolicyDefault } from "../../utils";
12
+ import {
13
+ buyingPolicyDefault,
14
+ BUYING_POLICIES_WORKFLOW_TYPES,
15
+ } from "../../utils";
16
+
17
+ import type { BuyingPolicyForm } from "../BasicBuyingPolicyDrawer/BasicBuyingPolicyDrawer";
9
18
 
10
19
  export type UpdateBuyingPolicyDrawerProps = Omit<
11
20
  BasicBuyingPolicyDrawerProps,
@@ -33,8 +42,31 @@ export const UpdateBuyingPolicyDrawer = ({
33
42
 
34
43
  const { pushToast } = useUI();
35
44
  const router = useRouter();
45
+ const { trackEntityEdited, trackEntityEditError } = useAnalytics({
46
+ entityType: "buying_policy",
47
+ entityId: buyingPolicyId,
48
+ defaultTimerName: "buying_policy_edit",
49
+ shouldTrackDefaultTimer: true,
50
+ });
51
+ const formDataRef = useRef<BuyingPolicyForm | null>(null);
36
52
 
37
53
  const handleUpdateBuyingPolicySuccess = () => {
54
+ const formData = formDataRef.current;
55
+
56
+ trackEntityEdited(ANALYTICS_EVENTS.BUYING_POLICY_EDITED, {
57
+ policy_id: buyingPolicyId,
58
+ policy_name: formData?.name,
59
+ policy_type: formData?.action.type,
60
+ policy_description: formData?.description,
61
+ policy_criteria: formData?.criteria,
62
+ ...(formData?.action.type ===
63
+ BUYING_POLICIES_WORKFLOW_TYPES.SEQUENTIAL_WORKFLOW && {
64
+ approval_levels_count: formData?.action.levels?.length,
65
+ }),
66
+ org_unit_id: orgUnitId,
67
+ contract_id: contractId,
68
+ });
69
+
38
70
  pushToast({
39
71
  message: "Buying policy updated successfully",
40
72
  status: "INFO",
@@ -64,7 +96,18 @@ export const UpdateBuyingPolicyDrawer = ({
64
96
  const { updateBuyingPolicy, isUpdateBuyingPolicyLoading } =
65
97
  useUpdateBuyingPolicy({
66
98
  onSuccess: handleUpdateBuyingPolicySuccess,
67
- onError: () => {
99
+ onError: (error) => {
100
+ trackEntityEditError(
101
+ ANALYTICS_EVENTS.BUYING_POLICY_EDIT_ERROR,
102
+ "buying_policy",
103
+ buyingPolicyId,
104
+ error,
105
+ {
106
+ org_unit_id: orgUnitId,
107
+ contract_id: contractId,
108
+ }
109
+ );
110
+
68
111
  pushToast({
69
112
  message: "An error occurred. Please try again.",
70
113
  title: "Error",
@@ -80,7 +123,8 @@ export const UpdateBuyingPolicyDrawer = ({
80
123
  close={close}
81
124
  isLoading={isUpdateBuyingPolicyLoading}
82
125
  isDrawerLoading={isBuyingPolicyLoading}
83
- onConfirm={(form) =>
126
+ onConfirm={(form) => {
127
+ formDataRef.current = form;
84
128
  updateBuyingPolicy({
85
129
  buyingPolicyId,
86
130
  buyingPolicy: {
@@ -88,8 +132,8 @@ export const UpdateBuyingPolicyDrawer = ({
88
132
  },
89
133
  orgUnitId,
90
134
  contractId,
91
- })
92
- }
135
+ });
136
+ }}
93
137
  initialValues={{ ...buyingPolicyDefault, ...(buyingPolicy ?? {}) }}
94
138
  orgUnitId={orgUnitId}
95
139
  contractId={contractId}
@@ -4,12 +4,13 @@ import { useUI } from "@faststore/ui";
4
4
 
5
5
  import { BasicDrawerProps } from "../../../shared/components";
6
6
  import { CreateEntityDrawer } from "../../../shared/components/CustomField/create-custom-field/CreateCustomFieldDrawer";
7
- import { useBuyerPortal } from "../../../shared/hooks";
7
+ import { useAnalytics, useBuyerPortal } from "../../../shared/hooks";
8
8
  import {
9
9
  useCreateCustomFieldValue,
10
10
  useCustomFieldValues,
11
11
  useAddCustomFieldValueToUnitScope,
12
12
  } from "../../../shared/hooks/custom-field";
13
+ import { ANALYTICS_EVENTS } from "../../../shared/services/logger/analytics/constants";
13
14
 
14
15
  export type CustomFieldType = "Cost Center" | "PO Number" | "Release";
15
16
 
@@ -35,8 +36,14 @@ export function CreateCustomFieldValueDrawer({
35
36
  const {
36
37
  clientContext: { cookie },
37
38
  } = useBuyerPortal();
39
+ const { trackEntityCreated, trackEntityCreateError } = useAnalytics({
40
+ entityType: "custom_field",
41
+ defaultTimerName: "custom_field_creation",
42
+ shouldTrackDefaultTimer: isOpen,
43
+ });
38
44
 
39
45
  const [search, setSearch] = useState<string | null>(null);
46
+ const [createdFieldName, setCreatedFieldName] = useState<string>("");
40
47
 
41
48
  const {
42
49
  mutate: createCustomFieldValueToUnitScope,
@@ -44,6 +51,18 @@ export function CreateCustomFieldValueDrawer({
44
51
  } = useAddCustomFieldValueToUnitScope({
45
52
  options: {
46
53
  onSuccess: () => {
54
+ trackEntityCreated(
55
+ ANALYTICS_EVENTS.CUSTOM_FIELD_CREATED,
56
+ "custom_field",
57
+ {
58
+ custom_field_type: customField,
59
+ custom_field_name: createdFieldName,
60
+ is_shared: true,
61
+ org_unit_id: unitId,
62
+ contract_id: contractId,
63
+ }
64
+ );
65
+
47
66
  pushToast({
48
67
  message: `${customField} added successfully`,
49
68
  status: "INFO",
@@ -52,11 +71,22 @@ export function CreateCustomFieldValueDrawer({
52
71
  refetch();
53
72
  close();
54
73
  },
55
- onError: (error) =>
74
+ onError: (error) => {
75
+ trackEntityCreateError(
76
+ ANALYTICS_EVENTS.CUSTOM_FIELD_CREATE_ERROR,
77
+ error,
78
+ {
79
+ custom_field_type: customField,
80
+ org_unit_id: unitId,
81
+ contract_id: contractId,
82
+ }
83
+ );
84
+
56
85
  pushToast({
57
86
  message: error.message,
58
87
  status: "ERROR",
59
- }),
88
+ });
89
+ },
60
90
  },
61
91
  });
62
92
 
@@ -66,6 +96,18 @@ export function CreateCustomFieldValueDrawer({
66
96
  } = useCreateCustomFieldValue({
67
97
  options: {
68
98
  onSuccess: () => {
99
+ trackEntityCreated(
100
+ ANALYTICS_EVENTS.CUSTOM_FIELD_CREATED,
101
+ "custom_field",
102
+ {
103
+ custom_field_type: customField,
104
+ custom_field_name: createdFieldName,
105
+ is_shared: false,
106
+ org_unit_id: unitId,
107
+ contract_id: contractId,
108
+ }
109
+ );
110
+
69
111
  pushToast({
70
112
  message: `${customField} added successfully`,
71
113
  status: "INFO",
@@ -74,11 +116,22 @@ export function CreateCustomFieldValueDrawer({
74
116
  refetch();
75
117
  close();
76
118
  },
77
- onError: (error) =>
119
+ onError: (error) => {
120
+ trackEntityCreateError(
121
+ ANALYTICS_EVENTS.CUSTOM_FIELD_CREATE_ERROR,
122
+ error,
123
+ {
124
+ custom_field_type: customField,
125
+ org_unit_id: unitId,
126
+ contract_id: contractId,
127
+ }
128
+ );
129
+
78
130
  pushToast({
79
131
  message: error.message,
80
132
  status: "ERROR",
81
- }),
133
+ });
134
+ },
82
135
  },
83
136
  });
84
137
 
@@ -104,6 +157,8 @@ export function CreateCustomFieldValueDrawer({
104
157
  });
105
158
 
106
159
  function create(name: string, customFieldValueId?: string) {
160
+ setCreatedFieldName(name);
161
+
107
162
  if (customFieldValueId) {
108
163
  return createCustomFieldValueToUnitScope({
109
164
  data: {
@@ -2,11 +2,12 @@ import { useUI } from "@faststore/ui";
2
2
 
3
3
  import { BasicDrawerProps } from "../../../shared/components";
4
4
  import { DeleteEntityDrawer } from "../../../shared/components/CustomField/delete-custom-field/DeleteCustomFieldDrawer";
5
- import { useBuyerPortal } from "../../../shared/hooks";
5
+ import { useAnalytics, useBuyerPortal } from "../../../shared/hooks";
6
6
  import {
7
7
  useDeleteCustomFieldValue,
8
8
  useDeleteCustomFieldValueToUnitScope,
9
9
  } from "../../../shared/hooks/custom-field";
10
+ import { ANALYTICS_EVENTS } from "../../../shared/services/logger/analytics/constants";
10
11
  import { CustomFieldData } from "../../types";
11
12
 
12
13
  export interface DeleteCustomFieldValueDrawerProps
@@ -36,12 +37,29 @@ export function DeleteCustomFieldValueDrawer({
36
37
  const {
37
38
  clientContext: { cookie },
38
39
  } = useBuyerPortal();
40
+ const { trackEvent } = useAnalytics({
41
+ entityType: "custom_field",
42
+ entityId: currentData?.id,
43
+ defaultTimerName: "custom_field_delete",
44
+ shouldTrackDefaultTimer: !!currentData,
45
+ });
46
+
39
47
  const {
40
48
  mutate: deleteCustomFieldValueToUnitScope,
41
49
  isLoading: isLoadingDeleteCustomFieldValueToUnitScope,
42
50
  } = useDeleteCustomFieldValueToUnitScope({
43
51
  options: {
44
52
  onSuccess: () => {
53
+ trackEvent(ANALYTICS_EVENTS.CUSTOM_FIELD_DELETED, {
54
+ custom_field_type: customField,
55
+ custom_field_id: currentData?.id,
56
+ custom_field_name: currentData?.value,
57
+ delete_mode: "unitScope",
58
+ org_unit_id: unitId,
59
+ contract_id: contractId,
60
+ entity_type: "custom_field",
61
+ });
62
+
45
63
  pushToast({
46
64
  message: `${customField} removed successfully`,
47
65
  status: "INFO",
@@ -50,11 +68,25 @@ export function DeleteCustomFieldValueDrawer({
50
68
  close();
51
69
  refetch();
52
70
  },
53
- onError: (error) =>
71
+ onError: (error) => {
72
+ const errorMessage = typeof error === "string" ? error : error.message;
73
+
74
+ trackEvent(ANALYTICS_EVENTS.CUSTOM_FIELD_DELETE_ERROR, {
75
+ entity_type: "custom_field",
76
+ entity_id: currentData?.id,
77
+ custom_field_type: customField,
78
+ custom_field_name: currentData?.value,
79
+ delete_mode: "unitScope",
80
+ org_unit_id: unitId,
81
+ contract_id: contractId,
82
+ error_message: errorMessage,
83
+ });
84
+
54
85
  pushToast({
55
86
  message: error.message,
56
87
  status: "ERROR",
57
- }),
88
+ });
89
+ },
58
90
  },
59
91
  });
60
92
 
@@ -64,6 +96,16 @@ export function DeleteCustomFieldValueDrawer({
64
96
  } = useDeleteCustomFieldValue({
65
97
  options: {
66
98
  onSuccess: () => {
99
+ trackEvent(ANALYTICS_EVENTS.CUSTOM_FIELD_DELETED, {
100
+ custom_field_type: customField,
101
+ custom_field_id: currentData?.id,
102
+ custom_field_name: currentData?.value,
103
+ delete_mode: "contract",
104
+ org_unit_id: unitId,
105
+ contract_id: contractId,
106
+ entity_type: "custom_field",
107
+ });
108
+
67
109
  pushToast({
68
110
  message: `${customField} deleted successfully`,
69
111
  status: "INFO",
@@ -72,11 +114,25 @@ export function DeleteCustomFieldValueDrawer({
72
114
  close();
73
115
  refetch();
74
116
  },
75
- onError: (error) =>
117
+ onError: (error) => {
118
+ const errorMessage = typeof error === "string" ? error : error.message;
119
+
120
+ trackEvent(ANALYTICS_EVENTS.CUSTOM_FIELD_DELETE_ERROR, {
121
+ entity_type: "custom_field",
122
+ entity_id: currentData?.id,
123
+ custom_field_type: customField,
124
+ custom_field_name: currentData?.value,
125
+ delete_mode: "contract",
126
+ org_unit_id: unitId,
127
+ contract_id: contractId,
128
+ error_message: errorMessage,
129
+ });
130
+
76
131
  pushToast({
77
132
  message: error.message,
78
133
  status: "ERROR",
79
- }),
134
+ });
135
+ },
80
136
  },
81
137
  });
82
138