@burdenoff/microfe-organization 2026.608.1 → 2026.624.1

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 (51) hide show
  1. package/dist/generated/global-operations.js +78 -63
  2. package/dist/generated/global-operations.js.map +1 -1
  3. package/dist/generated/global-types.js.map +1 -1
  4. package/dist/organization-management/UserOrganizationRoutes.js +13 -9
  5. package/dist/organization-management/UserOrganizationRoutes.js.map +1 -1
  6. package/dist/organization-management/modules/members/components/BulkInviteForm.js +2 -2
  7. package/dist/organization-management/modules/members/components/BulkInviteForm.js.map +1 -1
  8. package/dist/organization-management/modules/members/components/InviteMemberForm.js +2 -2
  9. package/dist/organization-management/modules/members/components/InviteMemberForm.js.map +1 -1
  10. package/dist/organization-management/modules/members/components/MyInviteCard.js +2 -2
  11. package/dist/organization-management/modules/members/components/MyInviteCard.js.map +1 -1
  12. package/dist/organization-management/modules/members/hooks/useInvites.js +79 -65
  13. package/dist/organization-management/modules/members/hooks/useInvites.js.map +1 -1
  14. package/dist/organization-management/modules/members/pages/MemberDetailPage.js +1 -1
  15. package/dist/organization-management/modules/members/pages/MemberDetailPage.js.map +1 -1
  16. package/dist/organization-management/modules/members/pages/MembersListPage.js +2 -2
  17. package/dist/organization-management/modules/members/pages/MembersListPage.js.map +1 -1
  18. package/dist/organization-management/modules/members/pages/MyInvitesPage.js +2 -2
  19. package/dist/organization-management/modules/members/pages/MyInvitesPage.js.map +1 -1
  20. package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js +287 -0
  21. package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js.map +1 -0
  22. package/dist/organization-management/modules/organizations/components/OrganizationForm.js +114 -114
  23. package/dist/organization-management/modules/organizations/components/OrganizationForm.js.map +1 -1
  24. package/dist/organization-management/modules/organizations/pages/OrganizationCreatePage.js +9 -8
  25. package/dist/organization-management/modules/organizations/pages/OrganizationCreatePage.js.map +1 -1
  26. package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js +3 -3
  27. package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js.map +1 -1
  28. package/dist/organization-management/modules/organizations/pages/OrganizationEditPage.js +1 -1
  29. package/dist/organization-management/modules/organizations/pages/OrganizationEditPage.js.map +1 -1
  30. package/dist/organization-management/modules/organizations/pages/OrganizationsListPage.js +3 -3
  31. package/dist/organization-management/modules/organizations/pages/OrganizationsListPage.js.map +1 -1
  32. package/dist/organization-management/modules/workspaces/components/WorkspaceCard.js +5 -8
  33. package/dist/organization-management/modules/workspaces/components/WorkspaceCard.js.map +1 -1
  34. package/dist/organization-management/modules/workspaces/components/WorkspaceForm.js +88 -136
  35. package/dist/organization-management/modules/workspaces/components/WorkspaceForm.js.map +1 -1
  36. package/dist/organization-management/modules/workspaces/hooks/useWorkspaces.js.map +1 -1
  37. package/dist/organization-management/modules/workspaces/pages/WorkspaceCreatePage.js +1 -1
  38. package/dist/organization-management/modules/workspaces/pages/WorkspaceCreatePage.js.map +1 -1
  39. package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js +7 -21
  40. package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js.map +1 -1
  41. package/dist/organization-management/modules/workspaces/pages/WorkspaceEditPage.js +1 -1
  42. package/dist/organization-management/modules/workspaces/pages/WorkspaceEditPage.js.map +1 -1
  43. package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js +6 -24
  44. package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js.map +1 -1
  45. package/dist/organization-management/shared/components/feedback/EmptyState.js +1 -1
  46. package/dist/organization-management/shared/components/feedback/EmptyState.js.map +1 -1
  47. package/dist/organization-management/shared/components/feedback/ErrorState.js +1 -1
  48. package/dist/organization-management/shared/components/feedback/ErrorState.js.map +1 -1
  49. package/dist/organization-management/shared/components/input/SearchInput.js +1 -1
  50. package/dist/organization-management/shared/components/input/SearchInput.js.map +1 -1
  51. package/package.json +1 -1
@@ -1,11 +1,11 @@
1
- import { GetMembersDocument as e, GetMyOrganizationInvitesDocument as t, GetOrganizationInvitesDocument as n, useCancelOrganizationInviteMutation as r, useGetMyOrganizationInvitesQuery as i, useGetOrganizationInvitesQuery as a, useInviteOrganizationMemberMutation as o, useRejectOrganizationInviteMutation as s, useResendOrganizationInviteMutation as c } from "../../../../generated/global-operations.js";
2
- import { useOrganizationEventEmitter as l } from "../../../hooks/useOrganizationEventEmitter.js";
3
- import { logger as u, redactId as d } from "../../../shared/logger.js";
4
- import { executeRecaptcha as f } from "../../../shared/recaptcha.js";
5
- import { gql as p } from "@apollo/client";
6
- import { useMutation as m } from "@apollo/client/react";
1
+ import { GetMembersDocument as e, GetMyOrganizationInvitesDocument as t, GetOrganizationInvitesDocument as n, useCancelOrganizationInviteMutation as r, useGetMyOrganizationInviteQuery as i, useGetMyOrganizationInvitesQuery as a, useGetOrganizationInvitesQuery as o, useInviteOrganizationMemberMutation as s, useRejectOrganizationInviteMutation as c, useResendOrganizationInviteMutation as l } from "../../../../generated/global-operations.js";
2
+ import { useOrganizationEventEmitter as u } from "../../../hooks/useOrganizationEventEmitter.js";
3
+ import { logger as d, redactId as f } from "../../../shared/logger.js";
4
+ import { executeRecaptcha as p } from "../../../shared/recaptcha.js";
5
+ import { gql as m } from "@apollo/client";
6
+ import { useMutation as h } from "@apollo/client/react";
7
7
  //#region src/organization-management/modules/members/hooks/useInvites.ts
8
- var h = p`
8
+ var g = m`
9
9
  mutation AcceptOrganizationInviteWithCaptcha($inviteId: ID!, $recaptchaToken: String) {
10
10
  acceptOrganizationInvite(inviteId: $inviteId, recaptchaToken: $recaptchaToken) {
11
11
  id
@@ -16,14 +16,14 @@ var h = p`
16
16
  }
17
17
  }
18
18
  `;
19
- function g(e) {
19
+ function _(e) {
20
20
  return e?.graphQLErrors?.[0]?.extensions?.code;
21
21
  }
22
- function _(e) {
22
+ function v(e) {
23
23
  return e instanceof Error ? e.message : e?.message ?? "Unknown error";
24
24
  }
25
- function v(e, t, n = 20, r = 0) {
26
- let { data: i, loading: o, error: s, refetch: c } = a({
25
+ function y(e, t, n = 20, r = 0) {
26
+ let { data: i, loading: a, error: s, refetch: c } = o({
27
27
  variables: {
28
28
  organizationId: e,
29
29
  filter: t,
@@ -38,13 +38,13 @@ function v(e, t, n = 20, r = 0) {
38
38
  invites: i?.organizationInvites?.items ?? [],
39
39
  total: i?.organizationInvites?.total ?? 0,
40
40
  hasMore: i?.organizationInvites?.hasMore ?? !1,
41
- loading: o,
41
+ loading: a,
42
42
  error: s,
43
43
  refetch: c
44
44
  };
45
45
  }
46
- function y(e, t = 20, n = 0, r = !0) {
47
- let { data: a, loading: o, error: s, refetch: c } = i({
46
+ function b(e, t = 20, n = 0, r = !0) {
47
+ let { data: i, loading: o, error: s, refetch: c } = a({
48
48
  variables: {
49
49
  status: e,
50
50
  limit: t,
@@ -55,21 +55,35 @@ function y(e, t = 20, n = 0, r = !0) {
55
55
  nextFetchPolicy: "cache-first"
56
56
  });
57
57
  return {
58
- invites: a?.myOrganizationInvites?.items ?? [],
59
- total: a?.myOrganizationInvites?.total ?? 0,
60
- hasMore: a?.myOrganizationInvites?.hasMore ?? !1,
58
+ invites: i?.myOrganizationInvites?.items ?? [],
59
+ total: i?.myOrganizationInvites?.total ?? 0,
60
+ hasMore: i?.myOrganizationInvites?.hasMore ?? !1,
61
61
  loading: o,
62
62
  error: s,
63
63
  refetch: c
64
64
  };
65
65
  }
66
- function b() {
67
- let { emit: e } = l(), [t, { loading: r, error: i }] = o({ refetchQueries: [n] });
66
+ function x(e, t = !0) {
67
+ let { data: n, loading: r, error: a, refetch: o } = i({
68
+ variables: { id: e },
69
+ skip: !t || !e,
70
+ fetchPolicy: "network-only",
71
+ nextFetchPolicy: "cache-first"
72
+ });
73
+ return {
74
+ invite: n?.myOrganizationInvite ?? null,
75
+ loading: r,
76
+ error: a,
77
+ refetch: o
78
+ };
79
+ }
80
+ function S() {
81
+ let { emit: e } = u(), [t, { loading: r, error: i }] = s({ refetchQueries: [n] });
68
82
  return {
69
83
  inviteMember: async (n) => {
70
- u.info("mutation.start", {
84
+ d.info("mutation.start", {
71
85
  name: "inviteMember",
72
- organizationId: d(n.organizationId)
86
+ organizationId: f(n.organizationId)
73
87
  });
74
88
  try {
75
89
  let r = await t({ variables: { input: n } }), i = r.data?.inviteOrganizationMember?.id;
@@ -77,21 +91,21 @@ function b() {
77
91
  organizationId: n.organizationId,
78
92
  inviteId: i,
79
93
  source: "microfe-organization"
80
- }), u.info("mutation.success", {
94
+ }), d.info("mutation.success", {
81
95
  name: "inviteMember",
82
- organizationId: d(n.organizationId),
83
- inviteId: d(i)
96
+ organizationId: f(n.organizationId),
97
+ inviteId: f(i)
84
98
  }), r;
85
99
  } catch (t) {
86
- let r = g(t), i = _(t);
100
+ let r = _(t), i = v(t);
87
101
  throw e("organization.invite.create_failed", {
88
102
  organizationId: n.organizationId,
89
103
  source: "microfe-organization",
90
104
  errorCode: r,
91
105
  errorMessage: i
92
- }), u.error("mutation.failed", {
106
+ }), d.error("mutation.failed", {
93
107
  name: "inviteMember",
94
- organizationId: d(n.organizationId),
108
+ organizationId: f(n.organizationId),
95
109
  errorCode: r,
96
110
  errorMessage: i
97
111
  }, t), t;
@@ -101,36 +115,36 @@ function b() {
101
115
  error: i
102
116
  };
103
117
  }
104
- function x() {
105
- let { emit: n } = l(), [r, { loading: i, error: a }] = m(h, { refetchQueries: [t, e] });
118
+ function C() {
119
+ let { emit: n } = u(), [r, { loading: i, error: a }] = h(g, { refetchQueries: [t, e] });
106
120
  return {
107
121
  acceptInvite: async (e) => {
108
- u.info("mutation.start", {
122
+ d.info("mutation.start", {
109
123
  name: "acceptInvite",
110
- inviteId: d(e)
124
+ inviteId: f(e)
111
125
  });
112
126
  try {
113
- let t = await f("invite_accept"), i = await r({ variables: {
127
+ let t = await p("invite_accept"), i = await r({ variables: {
114
128
  inviteId: e,
115
129
  ...t ? { recaptchaToken: t } : {}
116
130
  } });
117
131
  return n("organization.invite.accepted", {
118
132
  inviteId: e,
119
133
  source: "microfe-organization"
120
- }), u.info("mutation.success", {
134
+ }), d.info("mutation.success", {
121
135
  name: "acceptInvite",
122
- inviteId: d(e)
136
+ inviteId: f(e)
123
137
  }), i;
124
138
  } catch (t) {
125
- let r = g(t), i = _(t);
139
+ let r = _(t), i = v(t);
126
140
  throw n("organization.invite.accept_failed", {
127
141
  inviteId: e,
128
142
  source: "microfe-organization",
129
143
  errorCode: r,
130
144
  errorMessage: i
131
- }), u.error("mutation.failed", {
145
+ }), d.error("mutation.failed", {
132
146
  name: "acceptInvite",
133
- inviteId: d(e),
147
+ inviteId: f(e),
134
148
  errorCode: r,
135
149
  errorMessage: i
136
150
  }, t), t;
@@ -140,33 +154,33 @@ function x() {
140
154
  error: a
141
155
  };
142
156
  }
143
- function S() {
144
- let { emit: e } = l(), [n, { loading: r, error: i }] = s({ refetchQueries: [t] });
157
+ function w() {
158
+ let { emit: e } = u(), [n, { loading: r, error: i }] = c({ refetchQueries: [t] });
145
159
  return {
146
160
  rejectInvite: async (t) => {
147
- u.info("mutation.start", {
161
+ d.info("mutation.start", {
148
162
  name: "rejectInvite",
149
- inviteId: d(t)
163
+ inviteId: f(t)
150
164
  });
151
165
  try {
152
166
  let r = await n({ variables: { inviteId: t } });
153
167
  return e("organization.invite.rejected", {
154
168
  inviteId: t,
155
169
  source: "microfe-organization"
156
- }), u.info("mutation.success", {
170
+ }), d.info("mutation.success", {
157
171
  name: "rejectInvite",
158
- inviteId: d(t)
172
+ inviteId: f(t)
159
173
  }), r;
160
174
  } catch (n) {
161
- let r = g(n), i = _(n);
175
+ let r = _(n), i = v(n);
162
176
  throw e("organization.invite.reject_failed", {
163
177
  inviteId: t,
164
178
  source: "microfe-organization",
165
179
  errorCode: r,
166
180
  errorMessage: i
167
- }), u.error("mutation.failed", {
181
+ }), d.error("mutation.failed", {
168
182
  name: "rejectInvite",
169
- inviteId: d(t),
183
+ inviteId: f(t),
170
184
  errorCode: r,
171
185
  errorMessage: i
172
186
  }, n), n;
@@ -176,33 +190,33 @@ function S() {
176
190
  error: i
177
191
  };
178
192
  }
179
- function C() {
180
- let { emit: e } = l(), [t, { loading: i, error: a }] = r({ refetchQueries: [n] });
193
+ function T() {
194
+ let { emit: e } = u(), [t, { loading: i, error: a }] = r({ refetchQueries: [n] });
181
195
  return {
182
196
  cancelInvite: async (n) => {
183
- u.info("mutation.start", {
197
+ d.info("mutation.start", {
184
198
  name: "cancelInvite",
185
- inviteId: d(n)
199
+ inviteId: f(n)
186
200
  });
187
201
  try {
188
202
  let r = await t({ variables: { inviteId: n } });
189
203
  return e("organization.invite.cancelled", {
190
204
  inviteId: n,
191
205
  source: "microfe-organization"
192
- }), u.info("mutation.success", {
206
+ }), d.info("mutation.success", {
193
207
  name: "cancelInvite",
194
- inviteId: d(n)
208
+ inviteId: f(n)
195
209
  }), r;
196
210
  } catch (t) {
197
- let r = g(t), i = _(t);
211
+ let r = _(t), i = v(t);
198
212
  throw e("organization.invite.cancel_failed", {
199
213
  inviteId: n,
200
214
  source: "microfe-organization",
201
215
  errorCode: r,
202
216
  errorMessage: i
203
- }), u.error("mutation.failed", {
217
+ }), d.error("mutation.failed", {
204
218
  name: "cancelInvite",
205
- inviteId: d(n),
219
+ inviteId: f(n),
206
220
  errorCode: r,
207
221
  errorMessage: i
208
222
  }, t), t;
@@ -212,33 +226,33 @@ function C() {
212
226
  error: a
213
227
  };
214
228
  }
215
- function w() {
216
- let { emit: e } = l(), [t, { loading: r, error: i }] = c({ refetchQueries: [n] });
229
+ function E() {
230
+ let { emit: e } = u(), [t, { loading: r, error: i }] = l({ refetchQueries: [n] });
217
231
  return {
218
232
  resendInvite: async (n) => {
219
- u.info("mutation.start", {
233
+ d.info("mutation.start", {
220
234
  name: "resendInvite",
221
- inviteId: d(n)
235
+ inviteId: f(n)
222
236
  });
223
237
  try {
224
238
  let r = await t({ variables: { inviteId: n } });
225
239
  return e("organization.invite.resent", {
226
240
  inviteId: n,
227
241
  source: "microfe-organization"
228
- }), u.info("mutation.success", {
242
+ }), d.info("mutation.success", {
229
243
  name: "resendInvite",
230
- inviteId: d(n)
244
+ inviteId: f(n)
231
245
  }), r;
232
246
  } catch (t) {
233
- let r = g(t), i = _(t);
247
+ let r = _(t), i = v(t);
234
248
  throw e("organization.invite.resend_failed", {
235
249
  inviteId: n,
236
250
  source: "microfe-organization",
237
251
  errorCode: r,
238
252
  errorMessage: i
239
- }), u.error("mutation.failed", {
253
+ }), d.error("mutation.failed", {
240
254
  name: "resendInvite",
241
- inviteId: d(n),
255
+ inviteId: f(n),
242
256
  errorCode: r,
243
257
  errorMessage: i
244
258
  }, t), t;
@@ -249,6 +263,6 @@ function w() {
249
263
  };
250
264
  }
251
265
  //#endregion
252
- export { x as useAcceptInvite, C as useCancelInvite, b as useInviteMember, y as useMyInvites, v as useOrganizationInvites, S as useRejectInvite, w as useResendInvite };
266
+ export { C as useAcceptInvite, T as useCancelInvite, S as useInviteMember, b as useMyInvites, x as useOrganizationInvite, y as useOrganizationInvites, w as useRejectInvite, E as useResendInvite };
253
267
 
254
268
  //# sourceMappingURL=useInvites.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useInvites.js","names":[],"sources":["../../../../../src/organization-management/modules/members/hooks/useInvites.ts"],"sourcesContent":["import { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport {\n useInviteOrganizationMemberMutation,\n useRejectOrganizationInviteMutation,\n useCancelOrganizationInviteMutation,\n useResendOrganizationInviteMutation,\n useGetOrganizationInvitesQuery,\n useGetMyOrganizationInvitesQuery,\n GetOrganizationInvitesDocument,\n GetMyOrganizationInvitesDocument,\n GetMembersDocument,\n} from '../../../../generated/global-operations';\nimport type {\n InviteStatus,\n OrganizationInvite,\n OrganizationMember,\n} from '../../../../generated/global-types';\nimport { useOrganizationEventEmitter } from '../../../hooks/useOrganizationEventEmitter';\nimport { logger, redactId } from '../../../shared/logger';\nimport { executeRecaptcha } from '../../../shared/recaptcha';\n\nconst ACCEPT_ORGANIZATION_INVITE_WITH_CAPTCHA = gql`\n mutation AcceptOrganizationInviteWithCaptcha($inviteId: ID!, $recaptchaToken: String) {\n acceptOrganizationInvite(inviteId: $inviteId, recaptchaToken: $recaptchaToken) {\n id\n userId\n organizationId\n role\n joinedAt\n }\n }\n`;\n\ninterface AcceptOrganizationInviteData {\n acceptOrganizationInvite: OrganizationMember;\n}\n\ninterface AcceptOrganizationInviteVariables {\n inviteId: string;\n recaptchaToken?: string;\n}\n\ninterface GraphqlExtensions {\n code?: string;\n}\n\ninterface GraphqlError {\n message?: string;\n extensions?: GraphqlExtensions;\n}\n\ninterface ApolloLikeError {\n message?: string;\n graphQLErrors?: ReadonlyArray<GraphqlError>;\n}\n\nfunction extractErrorCode(error: unknown): string | undefined {\n const apolloError = error as ApolloLikeError | undefined;\n return apolloError?.graphQLErrors?.[0]?.extensions?.code;\n}\n\nfunction extractErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n const apolloError = error as ApolloLikeError | undefined;\n return apolloError?.message ?? 'Unknown error';\n}\n\n/**\n * Hook to fetch organization invites (admin view)\n */\nexport function useOrganizationInvites(\n organizationId: string,\n filter?: { status?: InviteStatus },\n limit: number = 20,\n offset: number = 0\n) {\n const { data, loading, error, refetch } = useGetOrganizationInvitesQuery({\n variables: { organizationId, filter, limit, offset },\n skip: !organizationId,\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n\n return {\n invites: (data?.organizationInvites?.items ?? []) as OrganizationInvite[],\n total: data?.organizationInvites?.total ?? 0,\n hasMore: data?.organizationInvites?.hasMore ?? false,\n loading,\n error,\n refetch,\n };\n}\n\n/**\n * Hook to fetch invites for the current user (invitee view).\n *\n * `enabled` defaults to `true` for backward compat. Callers in admin /\n * service contexts (e.g. OrganizationsListPage in `mode=\"admin\"`) should\n * pass `false` to skip the network round-trip and avoid surfacing\n * authorization errors for actors that don't hold the self-scope.\n */\nexport function useMyInvites(\n status?: InviteStatus,\n limit: number = 20,\n offset: number = 0,\n enabled: boolean = true\n) {\n const { data, loading, error, refetch } = useGetMyOrganizationInvitesQuery({\n variables: { status, limit, offset },\n skip: !enabled,\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n\n return {\n invites: (data?.myOrganizationInvites?.items ?? []) as OrganizationInvite[],\n total: data?.myOrganizationInvites?.total ?? 0,\n hasMore: data?.myOrganizationInvites?.hasMore ?? false,\n loading,\n error,\n refetch,\n };\n}\n\n/**\n * Hook to invite a member by email\n */\nexport function useInviteMember() {\n const { emit } = useOrganizationEventEmitter();\n const [inviteMember, { loading, error }] = useInviteOrganizationMemberMutation({\n refetchQueries: [GetOrganizationInvitesDocument],\n });\n\n return {\n inviteMember: async (input: { organizationId: string; email: string; message?: string }) => {\n logger.info('mutation.start', {\n name: 'inviteMember',\n organizationId: redactId(input.organizationId),\n });\n try {\n const result = await inviteMember({ variables: { input } });\n const inviteId = result.data?.inviteOrganizationMember?.id;\n emit('organization.invite.created', {\n organizationId: input.organizationId,\n inviteId,\n source: 'microfe-organization',\n });\n logger.info('mutation.success', {\n name: 'inviteMember',\n organizationId: redactId(input.organizationId),\n inviteId: redactId(inviteId),\n });\n return result;\n } catch (mutationError) {\n const errorCode = extractErrorCode(mutationError);\n const errorMessage = extractErrorMessage(mutationError);\n emit('organization.invite.create_failed', {\n organizationId: input.organizationId,\n source: 'microfe-organization',\n errorCode,\n errorMessage,\n });\n logger.error(\n 'mutation.failed',\n {\n name: 'inviteMember',\n organizationId: redactId(input.organizationId),\n errorCode,\n errorMessage,\n },\n mutationError\n );\n throw mutationError;\n }\n },\n loading,\n error,\n };\n}\n\n/**\n * Hook to accept an organization invite\n */\nexport function useAcceptInvite() {\n const { emit } = useOrganizationEventEmitter();\n const [acceptInvite, { loading, error }] = useMutation<\n AcceptOrganizationInviteData,\n AcceptOrganizationInviteVariables\n >(ACCEPT_ORGANIZATION_INVITE_WITH_CAPTCHA, {\n refetchQueries: [GetMyOrganizationInvitesDocument, GetMembersDocument],\n });\n\n return {\n acceptInvite: async (inviteId: string) => {\n logger.info('mutation.start', {\n name: 'acceptInvite',\n inviteId: redactId(inviteId),\n });\n try {\n const recaptchaToken = await executeRecaptcha('invite_accept');\n const result = await acceptInvite({\n variables: { inviteId, ...(recaptchaToken ? { recaptchaToken } : {}) },\n });\n emit('organization.invite.accepted', { inviteId, source: 'microfe-organization' });\n logger.info('mutation.success', {\n name: 'acceptInvite',\n inviteId: redactId(inviteId),\n });\n return result;\n } catch (mutationError) {\n const errorCode = extractErrorCode(mutationError);\n const errorMessage = extractErrorMessage(mutationError);\n emit('organization.invite.accept_failed', {\n inviteId,\n source: 'microfe-organization',\n errorCode,\n errorMessage,\n });\n logger.error(\n 'mutation.failed',\n {\n name: 'acceptInvite',\n inviteId: redactId(inviteId),\n errorCode,\n errorMessage,\n },\n mutationError\n );\n throw mutationError;\n }\n },\n loading,\n error,\n };\n}\n\n/**\n * Hook to reject an organization invite\n */\nexport function useRejectInvite() {\n const { emit } = useOrganizationEventEmitter();\n const [rejectInvite, { loading, error }] = useRejectOrganizationInviteMutation({\n refetchQueries: [GetMyOrganizationInvitesDocument],\n });\n\n return {\n rejectInvite: async (inviteId: string) => {\n logger.info('mutation.start', {\n name: 'rejectInvite',\n inviteId: redactId(inviteId),\n });\n try {\n const result = await rejectInvite({ variables: { inviteId } });\n emit('organization.invite.rejected', { inviteId, source: 'microfe-organization' });\n logger.info('mutation.success', {\n name: 'rejectInvite',\n inviteId: redactId(inviteId),\n });\n return result;\n } catch (mutationError) {\n const errorCode = extractErrorCode(mutationError);\n const errorMessage = extractErrorMessage(mutationError);\n emit('organization.invite.reject_failed', {\n inviteId,\n source: 'microfe-organization',\n errorCode,\n errorMessage,\n });\n logger.error(\n 'mutation.failed',\n {\n name: 'rejectInvite',\n inviteId: redactId(inviteId),\n errorCode,\n errorMessage,\n },\n mutationError\n );\n throw mutationError;\n }\n },\n loading,\n error,\n };\n}\n\n/**\n * Hook to cancel an organization invite\n */\nexport function useCancelInvite() {\n const { emit } = useOrganizationEventEmitter();\n const [cancelInvite, { loading, error }] = useCancelOrganizationInviteMutation({\n refetchQueries: [GetOrganizationInvitesDocument],\n });\n\n return {\n cancelInvite: async (inviteId: string) => {\n logger.info('mutation.start', {\n name: 'cancelInvite',\n inviteId: redactId(inviteId),\n });\n try {\n const result = await cancelInvite({ variables: { inviteId } });\n emit('organization.invite.cancelled', { inviteId, source: 'microfe-organization' });\n logger.info('mutation.success', {\n name: 'cancelInvite',\n inviteId: redactId(inviteId),\n });\n return result;\n } catch (mutationError) {\n const errorCode = extractErrorCode(mutationError);\n const errorMessage = extractErrorMessage(mutationError);\n emit('organization.invite.cancel_failed', {\n inviteId,\n source: 'microfe-organization',\n errorCode,\n errorMessage,\n });\n logger.error(\n 'mutation.failed',\n {\n name: 'cancelInvite',\n inviteId: redactId(inviteId),\n errorCode,\n errorMessage,\n },\n mutationError\n );\n throw mutationError;\n }\n },\n loading,\n error,\n };\n}\n\n/**\n * Hook to resend an organization invite\n */\nexport function useResendInvite() {\n const { emit } = useOrganizationEventEmitter();\n const [resendInvite, { loading, error }] = useResendOrganizationInviteMutation({\n refetchQueries: [GetOrganizationInvitesDocument],\n });\n\n return {\n resendInvite: async (inviteId: string) => {\n logger.info('mutation.start', {\n name: 'resendInvite',\n inviteId: redactId(inviteId),\n });\n try {\n const result = await resendInvite({ variables: { inviteId } });\n emit('organization.invite.resent', { inviteId, source: 'microfe-organization' });\n logger.info('mutation.success', {\n name: 'resendInvite',\n inviteId: redactId(inviteId),\n });\n return result;\n } catch (mutationError) {\n const errorCode = extractErrorCode(mutationError);\n const errorMessage = extractErrorMessage(mutationError);\n emit('organization.invite.resend_failed', {\n inviteId,\n source: 'microfe-organization',\n errorCode,\n errorMessage,\n });\n logger.error(\n 'mutation.failed',\n {\n name: 'resendInvite',\n inviteId: redactId(inviteId),\n errorCode,\n errorMessage,\n },\n mutationError\n );\n throw mutationError;\n }\n },\n loading,\n error,\n };\n}\n"],"mappings":";;;;;;;AAsBA,IAAM,IAA0C,CAAG;;;;;;;;;;;AAmCnD,SAAS,EAAiB,GAAoC;AAE5D,QADoB,GACA,gBAAgB,IAAI,YAAY;;AAGtD,SAAS,EAAoB,GAAwB;AAGnD,QAFI,aAAiB,QAAc,EAAM,UACrB,GACA,WAAW;;AAMjC,SAAgB,EACd,GACA,GACA,IAAgB,IAChB,IAAiB,GACjB;CACA,IAAM,EAAE,SAAM,YAAS,UAAO,eAAY,EAA+B;EACvE,WAAW;GAAE;GAAgB;GAAQ;GAAO;GAAQ;EACpD,MAAM,CAAC;EACP,aAAa;EACb,iBAAiB;EAClB,CAAC;AAEF,QAAO;EACL,SAAU,GAAM,qBAAqB,SAAS,EAAE;EAChD,OAAO,GAAM,qBAAqB,SAAS;EAC3C,SAAS,GAAM,qBAAqB,WAAW;EAC/C;EACA;EACA;EACD;;AAWH,SAAgB,EACd,GACA,IAAgB,IAChB,IAAiB,GACjB,IAAmB,IACnB;CACA,IAAM,EAAE,SAAM,YAAS,UAAO,eAAY,EAAiC;EACzE,WAAW;GAAE;GAAQ;GAAO;GAAQ;EACpC,MAAM,CAAC;EACP,aAAa;EACb,iBAAiB;EAClB,CAAC;AAEF,QAAO;EACL,SAAU,GAAM,uBAAuB,SAAS,EAAE;EAClD,OAAO,GAAM,uBAAuB,SAAS;EAC7C,SAAS,GAAM,uBAAuB,WAAW;EACjD;EACA;EACA;EACD;;AAMH,SAAgB,IAAkB;CAChC,IAAM,EAAE,YAAS,GAA6B,EACxC,CAAC,GAAc,EAAE,YAAS,cAAW,EAAoC,EAC7E,gBAAgB,CAAC,EAA+B,EACjD,CAAC;AAEF,QAAO;EACL,cAAc,OAAO,MAAuE;AAC1F,KAAO,KAAK,kBAAkB;IAC5B,MAAM;IACN,gBAAgB,EAAS,EAAM,eAAe;IAC/C,CAAC;AACF,OAAI;IACF,IAAM,IAAS,MAAM,EAAa,EAAE,WAAW,EAAE,UAAO,EAAE,CAAC,EACrD,IAAW,EAAO,MAAM,0BAA0B;AAWxD,WAVA,EAAK,+BAA+B;KAClC,gBAAgB,EAAM;KACtB;KACA,QAAQ;KACT,CAAC,EACF,EAAO,KAAK,oBAAoB;KAC9B,MAAM;KACN,gBAAgB,EAAS,EAAM,eAAe;KAC9C,UAAU,EAAS,EAAS;KAC7B,CAAC,EACK;YACA,GAAe;IACtB,IAAM,IAAY,EAAiB,EAAc,EAC3C,IAAe,EAAoB,EAAc;AAiBvD,UAhBA,EAAK,qCAAqC;KACxC,gBAAgB,EAAM;KACtB,QAAQ;KACR;KACA;KACD,CAAC,EACF,EAAO,MACL,mBACA;KACE,MAAM;KACN,gBAAgB,EAAS,EAAM,eAAe;KAC9C;KACA;KACD,EACD,EACD,EACK;;;EAGV;EACA;EACD;;AAMH,SAAgB,IAAkB;CAChC,IAAM,EAAE,YAAS,GAA6B,EACxC,CAAC,GAAc,EAAE,YAAS,cAAW,EAGzC,GAAyC,EACzC,gBAAgB,CAAC,GAAkC,EAAmB,EACvE,CAAC;AAEF,QAAO;EACL,cAAc,OAAO,MAAqB;AACxC,KAAO,KAAK,kBAAkB;IAC5B,MAAM;IACN,UAAU,EAAS,EAAS;IAC7B,CAAC;AACF,OAAI;IACF,IAAM,IAAiB,MAAM,EAAiB,gBAAgB,EACxD,IAAS,MAAM,EAAa,EAChC,WAAW;KAAE;KAAU,GAAI,IAAiB,EAAE,mBAAgB,GAAG,EAAE;KAAG,EACvE,CAAC;AAMF,WALA,EAAK,gCAAgC;KAAE;KAAU,QAAQ;KAAwB,CAAC,EAClF,EAAO,KAAK,oBAAoB;KAC9B,MAAM;KACN,UAAU,EAAS,EAAS;KAC7B,CAAC,EACK;YACA,GAAe;IACtB,IAAM,IAAY,EAAiB,EAAc,EAC3C,IAAe,EAAoB,EAAc;AAiBvD,UAhBA,EAAK,qCAAqC;KACxC;KACA,QAAQ;KACR;KACA;KACD,CAAC,EACF,EAAO,MACL,mBACA;KACE,MAAM;KACN,UAAU,EAAS,EAAS;KAC5B;KACA;KACD,EACD,EACD,EACK;;;EAGV;EACA;EACD;;AAMH,SAAgB,IAAkB;CAChC,IAAM,EAAE,YAAS,GAA6B,EACxC,CAAC,GAAc,EAAE,YAAS,cAAW,EAAoC,EAC7E,gBAAgB,CAAC,EAAiC,EACnD,CAAC;AAEF,QAAO;EACL,cAAc,OAAO,MAAqB;AACxC,KAAO,KAAK,kBAAkB;IAC5B,MAAM;IACN,UAAU,EAAS,EAAS;IAC7B,CAAC;AACF,OAAI;IACF,IAAM,IAAS,MAAM,EAAa,EAAE,WAAW,EAAE,aAAU,EAAE,CAAC;AAM9D,WALA,EAAK,gCAAgC;KAAE;KAAU,QAAQ;KAAwB,CAAC,EAClF,EAAO,KAAK,oBAAoB;KAC9B,MAAM;KACN,UAAU,EAAS,EAAS;KAC7B,CAAC,EACK;YACA,GAAe;IACtB,IAAM,IAAY,EAAiB,EAAc,EAC3C,IAAe,EAAoB,EAAc;AAiBvD,UAhBA,EAAK,qCAAqC;KACxC;KACA,QAAQ;KACR;KACA;KACD,CAAC,EACF,EAAO,MACL,mBACA;KACE,MAAM;KACN,UAAU,EAAS,EAAS;KAC5B;KACA;KACD,EACD,EACD,EACK;;;EAGV;EACA;EACD;;AAMH,SAAgB,IAAkB;CAChC,IAAM,EAAE,YAAS,GAA6B,EACxC,CAAC,GAAc,EAAE,YAAS,cAAW,EAAoC,EAC7E,gBAAgB,CAAC,EAA+B,EACjD,CAAC;AAEF,QAAO;EACL,cAAc,OAAO,MAAqB;AACxC,KAAO,KAAK,kBAAkB;IAC5B,MAAM;IACN,UAAU,EAAS,EAAS;IAC7B,CAAC;AACF,OAAI;IACF,IAAM,IAAS,MAAM,EAAa,EAAE,WAAW,EAAE,aAAU,EAAE,CAAC;AAM9D,WALA,EAAK,iCAAiC;KAAE;KAAU,QAAQ;KAAwB,CAAC,EACnF,EAAO,KAAK,oBAAoB;KAC9B,MAAM;KACN,UAAU,EAAS,EAAS;KAC7B,CAAC,EACK;YACA,GAAe;IACtB,IAAM,IAAY,EAAiB,EAAc,EAC3C,IAAe,EAAoB,EAAc;AAiBvD,UAhBA,EAAK,qCAAqC;KACxC;KACA,QAAQ;KACR;KACA;KACD,CAAC,EACF,EAAO,MACL,mBACA;KACE,MAAM;KACN,UAAU,EAAS,EAAS;KAC5B;KACA;KACD,EACD,EACD,EACK;;;EAGV;EACA;EACD;;AAMH,SAAgB,IAAkB;CAChC,IAAM,EAAE,YAAS,GAA6B,EACxC,CAAC,GAAc,EAAE,YAAS,cAAW,EAAoC,EAC7E,gBAAgB,CAAC,EAA+B,EACjD,CAAC;AAEF,QAAO;EACL,cAAc,OAAO,MAAqB;AACxC,KAAO,KAAK,kBAAkB;IAC5B,MAAM;IACN,UAAU,EAAS,EAAS;IAC7B,CAAC;AACF,OAAI;IACF,IAAM,IAAS,MAAM,EAAa,EAAE,WAAW,EAAE,aAAU,EAAE,CAAC;AAM9D,WALA,EAAK,8BAA8B;KAAE;KAAU,QAAQ;KAAwB,CAAC,EAChF,EAAO,KAAK,oBAAoB;KAC9B,MAAM;KACN,UAAU,EAAS,EAAS;KAC7B,CAAC,EACK;YACA,GAAe;IACtB,IAAM,IAAY,EAAiB,EAAc,EAC3C,IAAe,EAAoB,EAAc;AAiBvD,UAhBA,EAAK,qCAAqC;KACxC;KACA,QAAQ;KACR;KACA;KACD,CAAC,EACF,EAAO,MACL,mBACA;KACE,MAAM;KACN,UAAU,EAAS,EAAS;KAC5B;KACA;KACD,EACD,EACD,EACK;;;EAGV;EACA;EACD"}
1
+ {"version":3,"file":"useInvites.js","names":[],"sources":["../../../../../src/organization-management/modules/members/hooks/useInvites.ts"],"sourcesContent":["import { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport {\n useInviteOrganizationMemberMutation,\n useRejectOrganizationInviteMutation,\n useCancelOrganizationInviteMutation,\n useResendOrganizationInviteMutation,\n useGetOrganizationInvitesQuery,\n useGetMyOrganizationInvitesQuery,\n useGetMyOrganizationInviteQuery,\n GetOrganizationInvitesDocument,\n GetMyOrganizationInvitesDocument,\n GetMembersDocument,\n} from '../../../../generated/global-operations';\nimport type {\n InviteStatus,\n OrganizationInvite,\n OrganizationMember,\n} from '../../../../generated/global-types';\nimport { useOrganizationEventEmitter } from '../../../hooks/useOrganizationEventEmitter';\nimport { logger, redactId } from '../../../shared/logger';\nimport { executeRecaptcha } from '../../../shared/recaptcha';\n\nconst ACCEPT_ORGANIZATION_INVITE_WITH_CAPTCHA = gql`\n mutation AcceptOrganizationInviteWithCaptcha($inviteId: ID!, $recaptchaToken: String) {\n acceptOrganizationInvite(inviteId: $inviteId, recaptchaToken: $recaptchaToken) {\n id\n userId\n organizationId\n role\n joinedAt\n }\n }\n`;\n\ninterface AcceptOrganizationInviteData {\n acceptOrganizationInvite: OrganizationMember;\n}\n\ninterface AcceptOrganizationInviteVariables {\n inviteId: string;\n recaptchaToken?: string;\n}\n\ninterface GraphqlExtensions {\n code?: string;\n}\n\ninterface GraphqlError {\n message?: string;\n extensions?: GraphqlExtensions;\n}\n\ninterface ApolloLikeError {\n message?: string;\n graphQLErrors?: ReadonlyArray<GraphqlError>;\n}\n\nfunction extractErrorCode(error: unknown): string | undefined {\n const apolloError = error as ApolloLikeError | undefined;\n return apolloError?.graphQLErrors?.[0]?.extensions?.code;\n}\n\nfunction extractErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n const apolloError = error as ApolloLikeError | undefined;\n return apolloError?.message ?? 'Unknown error';\n}\n\n/**\n * Hook to fetch organization invites (admin view)\n */\nexport function useOrganizationInvites(\n organizationId: string,\n filter?: { status?: InviteStatus },\n limit: number = 20,\n offset: number = 0\n) {\n const { data, loading, error, refetch } = useGetOrganizationInvitesQuery({\n variables: { organizationId, filter, limit, offset },\n skip: !organizationId,\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n\n return {\n invites: (data?.organizationInvites?.items ?? []) as OrganizationInvite[],\n total: data?.organizationInvites?.total ?? 0,\n hasMore: data?.organizationInvites?.hasMore ?? false,\n loading,\n error,\n refetch,\n };\n}\n\n/**\n * Hook to fetch invites for the current user (invitee view).\n *\n * `enabled` defaults to `true` for backward compat. Callers in admin /\n * service contexts (e.g. OrganizationsListPage in `mode=\"admin\"`) should\n * pass `false` to skip the network round-trip and avoid surfacing\n * authorization errors for actors that don't hold the self-scope.\n */\nexport function useMyInvites(\n status?: InviteStatus,\n limit: number = 20,\n offset: number = 0,\n enabled: boolean = true\n) {\n const { data, loading, error, refetch } = useGetMyOrganizationInvitesQuery({\n variables: { status, limit, offset },\n skip: !enabled,\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n\n return {\n invites: (data?.myOrganizationInvites?.items ?? []) as OrganizationInvite[],\n total: data?.myOrganizationInvites?.total ?? 0,\n hasMore: data?.myOrganizationInvites?.hasMore ?? false,\n loading,\n error,\n refetch,\n };\n}\n\n/**\n * Hook to fetch a SINGLE invite addressed to the current user, by id.\n * Backs the per-invite acceptance page reached from the invite email link.\n * `enabled` defaults to true; pass false to defer until the user is\n * authenticated (the query is self-scoped and 401s for anonymous callers).\n */\nexport function useOrganizationInvite(inviteId: string, enabled: boolean = true) {\n const { data, loading, error, refetch } = useGetMyOrganizationInviteQuery({\n variables: { id: inviteId },\n skip: !enabled || !inviteId,\n fetchPolicy: 'network-only',\n nextFetchPolicy: 'cache-first',\n });\n\n return {\n invite: (data?.myOrganizationInvite ?? null) as OrganizationInvite | null,\n loading,\n error,\n refetch,\n };\n}\n\n/**\n * Hook to invite a member by email\n */\nexport function useInviteMember() {\n const { emit } = useOrganizationEventEmitter();\n const [inviteMember, { loading, error }] = useInviteOrganizationMemberMutation({\n refetchQueries: [GetOrganizationInvitesDocument],\n });\n\n return {\n inviteMember: async (input: { organizationId: string; email: string; message?: string }) => {\n logger.info('mutation.start', {\n name: 'inviteMember',\n organizationId: redactId(input.organizationId),\n });\n try {\n const result = await inviteMember({ variables: { input } });\n const inviteId = result.data?.inviteOrganizationMember?.id;\n emit('organization.invite.created', {\n organizationId: input.organizationId,\n inviteId,\n source: 'microfe-organization',\n });\n logger.info('mutation.success', {\n name: 'inviteMember',\n organizationId: redactId(input.organizationId),\n inviteId: redactId(inviteId),\n });\n return result;\n } catch (mutationError) {\n const errorCode = extractErrorCode(mutationError);\n const errorMessage = extractErrorMessage(mutationError);\n emit('organization.invite.create_failed', {\n organizationId: input.organizationId,\n source: 'microfe-organization',\n errorCode,\n errorMessage,\n });\n logger.error(\n 'mutation.failed',\n {\n name: 'inviteMember',\n organizationId: redactId(input.organizationId),\n errorCode,\n errorMessage,\n },\n mutationError\n );\n throw mutationError;\n }\n },\n loading,\n error,\n };\n}\n\n/**\n * Hook to accept an organization invite\n */\nexport function useAcceptInvite() {\n const { emit } = useOrganizationEventEmitter();\n const [acceptInvite, { loading, error }] = useMutation<\n AcceptOrganizationInviteData,\n AcceptOrganizationInviteVariables\n >(ACCEPT_ORGANIZATION_INVITE_WITH_CAPTCHA, {\n refetchQueries: [GetMyOrganizationInvitesDocument, GetMembersDocument],\n });\n\n return {\n acceptInvite: async (inviteId: string) => {\n logger.info('mutation.start', {\n name: 'acceptInvite',\n inviteId: redactId(inviteId),\n });\n try {\n const recaptchaToken = await executeRecaptcha('invite_accept');\n const result = await acceptInvite({\n variables: { inviteId, ...(recaptchaToken ? { recaptchaToken } : {}) },\n });\n emit('organization.invite.accepted', { inviteId, source: 'microfe-organization' });\n logger.info('mutation.success', {\n name: 'acceptInvite',\n inviteId: redactId(inviteId),\n });\n return result;\n } catch (mutationError) {\n const errorCode = extractErrorCode(mutationError);\n const errorMessage = extractErrorMessage(mutationError);\n emit('organization.invite.accept_failed', {\n inviteId,\n source: 'microfe-organization',\n errorCode,\n errorMessage,\n });\n logger.error(\n 'mutation.failed',\n {\n name: 'acceptInvite',\n inviteId: redactId(inviteId),\n errorCode,\n errorMessage,\n },\n mutationError\n );\n throw mutationError;\n }\n },\n loading,\n error,\n };\n}\n\n/**\n * Hook to reject an organization invite\n */\nexport function useRejectInvite() {\n const { emit } = useOrganizationEventEmitter();\n const [rejectInvite, { loading, error }] = useRejectOrganizationInviteMutation({\n refetchQueries: [GetMyOrganizationInvitesDocument],\n });\n\n return {\n rejectInvite: async (inviteId: string) => {\n logger.info('mutation.start', {\n name: 'rejectInvite',\n inviteId: redactId(inviteId),\n });\n try {\n const result = await rejectInvite({ variables: { inviteId } });\n emit('organization.invite.rejected', { inviteId, source: 'microfe-organization' });\n logger.info('mutation.success', {\n name: 'rejectInvite',\n inviteId: redactId(inviteId),\n });\n return result;\n } catch (mutationError) {\n const errorCode = extractErrorCode(mutationError);\n const errorMessage = extractErrorMessage(mutationError);\n emit('organization.invite.reject_failed', {\n inviteId,\n source: 'microfe-organization',\n errorCode,\n errorMessage,\n });\n logger.error(\n 'mutation.failed',\n {\n name: 'rejectInvite',\n inviteId: redactId(inviteId),\n errorCode,\n errorMessage,\n },\n mutationError\n );\n throw mutationError;\n }\n },\n loading,\n error,\n };\n}\n\n/**\n * Hook to cancel an organization invite\n */\nexport function useCancelInvite() {\n const { emit } = useOrganizationEventEmitter();\n const [cancelInvite, { loading, error }] = useCancelOrganizationInviteMutation({\n refetchQueries: [GetOrganizationInvitesDocument],\n });\n\n return {\n cancelInvite: async (inviteId: string) => {\n logger.info('mutation.start', {\n name: 'cancelInvite',\n inviteId: redactId(inviteId),\n });\n try {\n const result = await cancelInvite({ variables: { inviteId } });\n emit('organization.invite.cancelled', { inviteId, source: 'microfe-organization' });\n logger.info('mutation.success', {\n name: 'cancelInvite',\n inviteId: redactId(inviteId),\n });\n return result;\n } catch (mutationError) {\n const errorCode = extractErrorCode(mutationError);\n const errorMessage = extractErrorMessage(mutationError);\n emit('organization.invite.cancel_failed', {\n inviteId,\n source: 'microfe-organization',\n errorCode,\n errorMessage,\n });\n logger.error(\n 'mutation.failed',\n {\n name: 'cancelInvite',\n inviteId: redactId(inviteId),\n errorCode,\n errorMessage,\n },\n mutationError\n );\n throw mutationError;\n }\n },\n loading,\n error,\n };\n}\n\n/**\n * Hook to resend an organization invite\n */\nexport function useResendInvite() {\n const { emit } = useOrganizationEventEmitter();\n const [resendInvite, { loading, error }] = useResendOrganizationInviteMutation({\n refetchQueries: [GetOrganizationInvitesDocument],\n });\n\n return {\n resendInvite: async (inviteId: string) => {\n logger.info('mutation.start', {\n name: 'resendInvite',\n inviteId: redactId(inviteId),\n });\n try {\n const result = await resendInvite({ variables: { inviteId } });\n emit('organization.invite.resent', { inviteId, source: 'microfe-organization' });\n logger.info('mutation.success', {\n name: 'resendInvite',\n inviteId: redactId(inviteId),\n });\n return result;\n } catch (mutationError) {\n const errorCode = extractErrorCode(mutationError);\n const errorMessage = extractErrorMessage(mutationError);\n emit('organization.invite.resend_failed', {\n inviteId,\n source: 'microfe-organization',\n errorCode,\n errorMessage,\n });\n logger.error(\n 'mutation.failed',\n {\n name: 'resendInvite',\n inviteId: redactId(inviteId),\n errorCode,\n errorMessage,\n },\n mutationError\n );\n throw mutationError;\n }\n },\n loading,\n error,\n };\n}\n"],"mappings":"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"}
@@ -46,7 +46,7 @@ function g() {
46
46
  children: [/* @__PURE__ */ f("button", {
47
47
  type: "button",
48
48
  onClick: () => y(`${b}/${_}/members`),
49
- className: "inline-flex items-center gap-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] active:scale-[0.98] transition-all duration-200 mb-4",
49
+ className: "inline-flex items-center gap-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-all duration-200 mb-4",
50
50
  children: [/* @__PURE__ */ d(c, { size: 20 }), g("members.detail.backToMembers", "Back to Members")]
51
51
  }), /* @__PURE__ */ f("div", {
52
52
  className: "flex items-start gap-4",
@@ -1 +1 @@
1
- {"version":3,"file":"MemberDetailPage.js","names":[],"sources":["../../../../../src/organization-management/modules/members/pages/MemberDetailPage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, Shield } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { buildActorFallback, useActorProfiles, type ActorInput } from '@burdenoff/fe-libs/shared';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useMember } from '../hooks/useMembers';\nimport { MemberRoleBadge } from '../components/MemberRoleBadge';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { ErrorState } from '../../../shared/components/feedback/ErrorState';\nimport { PERMISSIONS } from '../../../constants/permissions';\nimport { useTr } from '../../../shared/hooks/useTr';\n\n/**\n * Member Detail Page\n * Simplified version showing available member fields\n */\nexport function MemberDetailPage() {\n const tr = useTr();\n const { organizationId, userId } = useParams<{ organizationId: string; userId: string }>();\n const { navigate, basePath = '/organizations', apiGatewayUrl, authToken } = useOrgConsole();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const { member, loading, error } = useMember(organizationId!, userId!);\n\n const memberActors = useMemo<ActorInput[]>(\n () => (userId ? [{ actorId: userId, actorType: 'user' }] : []),\n [userId]\n );\n const profileMap = useActorProfiles(memberActors, {\n apiGatewayUrl,\n authToken,\n orgId: organizationId,\n });\n const memberProfile =\n userId && member\n ? (profileMap[member.userId] ??\n buildActorFallback({ actorId: member.userId, actorType: 'user' }))\n : null;\n\n if (permissionsLoading) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <LoadingState message={tr('common.loadingPermissions', 'Loading permissions...')} />\n </div>\n );\n }\n\n if (!hasPermission(PERMISSIONS.MEMBER_READ)) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <div className=\"p-8 text-center text-[var(--color-text-secondary)]\">\n {tr('members.detail.noPermission', \"You don't have permission to view member details.\")}\n </div>\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <LoadingState message={tr('members.detail.loading', 'Loading member...')} />\n </div>\n );\n }\n\n if (error || !member) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <ErrorState\n message={error?.message || tr('members.detail.notFound', 'Member not found')}\n action={{\n label: tr('common.goBack', 'Go Back'),\n onClick: () => navigate(`${basePath}/${organizationId}/members`),\n }}\n />\n </div>\n );\n }\n\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-300\">\n {/* Header */}\n <div className=\"mb-6\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${organizationId}/members`)}\n className=\"inline-flex items-center gap-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] active:scale-[0.98] transition-all duration-200 mb-4\"\n >\n <ArrowLeft size={20} />\n {tr('members.detail.backToMembers', 'Back to Members')}\n </button>\n\n <div className=\"flex items-start gap-4\">\n <div className=\"size-16 rounded-full bg-[var(--color-status-info-muted)] flex items-center justify-center\">\n <Shield size={32} className=\"text-[var(--color-status-info)]\" />\n </div>\n <div>\n <h1 className=\"text-3xl font-bold text-[var(--color-text-primary)]\">\n {memberProfile?.displayName ?? tr('members.detail.titlePrefix', 'Member')}\n </h1>\n {memberProfile?.email ? (\n <p className=\"text-[var(--color-text-secondary)] mt-1 break-all\">\n {memberProfile.email}\n </p>\n ) : null}\n <p className=\"text-[var(--color-text-secondary)] mt-1\">{member.role}</p>\n <details className=\"mt-2 text-xs text-[var(--color-text-secondary)]\">\n <summary className=\"cursor-pointer\">\n {tr('members.detail.showIds', 'Show technical IDs')}\n </summary>\n <dl className=\"mt-1 grid grid-cols-[auto_1fr] gap-x-3 gap-y-1\">\n <dt>{tr('members.detail.userId', 'User ID')}</dt>\n <dd className=\"break-all font-mono\">{member.userId}</dd>\n <dt>{tr('members.list.memberId', 'Member ID')}</dt>\n <dd className=\"break-all font-mono\">{member.id}</dd>\n </dl>\n </details>\n </div>\n </div>\n </div>\n\n {/* Details */}\n <div className=\"bg-[var(--color-bg-surface)] border border-[var(--color-border-default)] rounded-lg p-6\">\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)] mb-4\">\n {tr('members.detail.info', 'Member Information')}\n </h2>\n\n <div className=\"space-y-4\">\n <div>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr('members.list.column.role', 'Role')}\n </p>\n <div className=\"mt-1\">\n <MemberRoleBadge role={member.role} />\n </div>\n </div>\n\n {member.invitedBy && (\n <div>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr('members.detail.invitedBy', 'Invited By')}\n </p>\n <p className=\"text-[var(--color-text-primary)] font-medium\">{member.invitedBy}</p>\n </div>\n )}\n\n {member.joinedAt && (\n <div>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr('members.detail.joinedAt', 'Joined At')}\n </p>\n <p className=\"text-[var(--color-text-primary)] font-medium\">\n {new Date(member.joinedAt).toLocaleString()}\n </p>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAiBA,SAAgB,IAAmB;CACjC,IAAM,IAAK,GAAO,EACZ,EAAE,mBAAgB,cAAW,GAAuD,EACpF,EAAE,aAAU,cAAW,kBAAkB,kBAAe,iBAAc,GAAe,EACrF,EAAE,kBAAe,WAAW,MAAuB,GAAgB,EACnE,EAAE,WAAQ,YAAS,aAAU,EAAU,GAAiB,EAAQ,EAMhE,IAAa,EAJE,QACZ,IAAS,CAAC;EAAE,SAAS;EAAQ,WAAW;EAAQ,CAAC,GAAG,EAAE,EAC7D,CAAC,EAAO,CACT,EACiD;EAChD;EACA;EACA,OAAO;EACR,CAAC,EACI,IACJ,KAAU,IACL,EAAW,EAAO,WACnB,EAAmB;EAAE,SAAS,EAAO;EAAQ,WAAW;EAAQ,CAAC,GACjE;AA0CN,QAxCI,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EAAc,SAAS,EAAG,6BAA6B,yBAAyB,EAAI,CAAA;EAChF,CAAA,GAIL,EAAc,EAAY,YAAY,GAUvC,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EAAc,SAAS,EAAG,0BAA0B,oBAAoB,EAAI,CAAA;EACxE,CAAA,GAIN,KAAS,CAAC,IAEV,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD;GACE,SAAS,GAAO,WAAW,EAAG,2BAA2B,mBAAmB;GAC5E,QAAQ;IACN,OAAO,EAAG,iBAAiB,UAAU;IACrC,eAAe,EAAS,GAAG,EAAS,GAAG,EAAe,UAAU;IACjE;GACD,CAAA;EACE,CAAA,GAKR,kBAAC,OAAD;EAAK,WAAU;YAAf,CAEE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAS,GAAG,EAAS,GAAG,EAAe,UAAU;IAChE,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA,EACtB,EAAG,gCAAgC,kBAAkB,CAC/C;OAET,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD;MAAQ,MAAM;MAAI,WAAU;MAAoC,CAAA;KAC5D,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA;KACE,kBAAC,MAAD;MAAI,WAAU;gBACX,GAAe,eAAe,EAAG,8BAA8B,SAAS;MACtE,CAAA;KACJ,GAAe,QACd,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAc;MACb,CAAA,GACF;KACJ,kBAAC,KAAD;MAAG,WAAU;gBAA2C,EAAO;MAAS,CAAA;KACxE,kBAAC,WAAD;MAAS,WAAU;gBAAnB,CACE,kBAAC,WAAD;OAAS,WAAU;iBAChB,EAAG,0BAA0B,qBAAqB;OAC3C,CAAA,EACV,kBAAC,MAAD;OAAI,WAAU;iBAAd;QACE,kBAAC,MAAD,EAAA,UAAK,EAAG,yBAAyB,UAAU,EAAM,CAAA;QACjD,kBAAC,MAAD;SAAI,WAAU;mBAAuB,EAAO;SAAY,CAAA;QACxD,kBAAC,MAAD,EAAA,UAAK,EAAG,yBAAyB,YAAY,EAAM,CAAA;QACnD,kBAAC,MAAD;SAAI,WAAU;mBAAuB,EAAO;SAAQ,CAAA;QACjD;SACG;;KACN,EAAA,CAAA,CACF;MACF;MAGN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,MAAD;IAAI,WAAU;cACX,EAAG,uBAAuB,qBAAqB;IAC7C,CAAA,EAEL,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAG,4BAA4B,OAAO;MACrC,CAAA,EACJ,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAiB,MAAM,EAAO,MAAQ,CAAA;MAClC,CAAA,CACF,EAAA,CAAA;KAEL,EAAO,aACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAG,4BAA4B,aAAa;MAC3C,CAAA,EACJ,kBAAC,KAAD;MAAG,WAAU;gBAAgD,EAAO;MAAc,CAAA,CAC9E,EAAA,CAAA;KAGP,EAAO,YACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAG,2BAA2B,YAAY;MACzC,CAAA,EACJ,kBAAC,KAAD;MAAG,WAAU;gBACV,IAAI,KAAK,EAAO,SAAS,CAAC,gBAAgB;MACzC,CAAA,CACA,EAAA,CAAA;KAEJ;MACF;KACF;MA7GJ,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAG,+BAA+B,oDAAoD;GACnF,CAAA;EACF,CAAA"}
1
+ {"version":3,"file":"MemberDetailPage.js","names":[],"sources":["../../../../../src/organization-management/modules/members/pages/MemberDetailPage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, Shield } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { buildActorFallback, useActorProfiles, type ActorInput } from '@burdenoff/fe-libs/shared';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useMember } from '../hooks/useMembers';\nimport { MemberRoleBadge } from '../components/MemberRoleBadge';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { ErrorState } from '../../../shared/components/feedback/ErrorState';\nimport { PERMISSIONS } from '../../../constants/permissions';\nimport { useTr } from '../../../shared/hooks/useTr';\n\n/**\n * Member Detail Page\n * Simplified version showing available member fields\n */\nexport function MemberDetailPage() {\n const tr = useTr();\n const { organizationId, userId } = useParams<{ organizationId: string; userId: string }>();\n const { navigate, basePath = '/organizations', apiGatewayUrl, authToken } = useOrgConsole();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const { member, loading, error } = useMember(organizationId!, userId!);\n\n const memberActors = useMemo<ActorInput[]>(\n () => (userId ? [{ actorId: userId, actorType: 'user' }] : []),\n [userId]\n );\n const profileMap = useActorProfiles(memberActors, {\n apiGatewayUrl,\n authToken,\n orgId: organizationId,\n });\n const memberProfile =\n userId && member\n ? (profileMap[member.userId] ??\n buildActorFallback({ actorId: member.userId, actorType: 'user' }))\n : null;\n\n if (permissionsLoading) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <LoadingState message={tr('common.loadingPermissions', 'Loading permissions...')} />\n </div>\n );\n }\n\n if (!hasPermission(PERMISSIONS.MEMBER_READ)) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <div className=\"p-8 text-center text-[var(--color-text-secondary)]\">\n {tr('members.detail.noPermission', \"You don't have permission to view member details.\")}\n </div>\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <LoadingState message={tr('members.detail.loading', 'Loading member...')} />\n </div>\n );\n }\n\n if (error || !member) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <ErrorState\n message={error?.message || tr('members.detail.notFound', 'Member not found')}\n action={{\n label: tr('common.goBack', 'Go Back'),\n onClick: () => navigate(`${basePath}/${organizationId}/members`),\n }}\n />\n </div>\n );\n }\n\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-300\">\n {/* Header */}\n <div className=\"mb-6\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${organizationId}/members`)}\n className=\"inline-flex items-center gap-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-all duration-200 mb-4\"\n >\n <ArrowLeft size={20} />\n {tr('members.detail.backToMembers', 'Back to Members')}\n </button>\n\n <div className=\"flex items-start gap-4\">\n <div className=\"size-16 rounded-full bg-[var(--color-status-info-muted)] flex items-center justify-center\">\n <Shield size={32} className=\"text-[var(--color-status-info)]\" />\n </div>\n <div>\n <h1 className=\"text-3xl font-bold text-[var(--color-text-primary)]\">\n {memberProfile?.displayName ?? tr('members.detail.titlePrefix', 'Member')}\n </h1>\n {memberProfile?.email ? (\n <p className=\"text-[var(--color-text-secondary)] mt-1 break-all\">\n {memberProfile.email}\n </p>\n ) : null}\n <p className=\"text-[var(--color-text-secondary)] mt-1\">{member.role}</p>\n <details className=\"mt-2 text-xs text-[var(--color-text-secondary)]\">\n <summary className=\"cursor-pointer\">\n {tr('members.detail.showIds', 'Show technical IDs')}\n </summary>\n <dl className=\"mt-1 grid grid-cols-[auto_1fr] gap-x-3 gap-y-1\">\n <dt>{tr('members.detail.userId', 'User ID')}</dt>\n <dd className=\"break-all font-mono\">{member.userId}</dd>\n <dt>{tr('members.list.memberId', 'Member ID')}</dt>\n <dd className=\"break-all font-mono\">{member.id}</dd>\n </dl>\n </details>\n </div>\n </div>\n </div>\n\n {/* Details */}\n <div className=\"bg-[var(--color-bg-surface)] border border-[var(--color-border-default)] rounded-lg p-6\">\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)] mb-4\">\n {tr('members.detail.info', 'Member Information')}\n </h2>\n\n <div className=\"space-y-4\">\n <div>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr('members.list.column.role', 'Role')}\n </p>\n <div className=\"mt-1\">\n <MemberRoleBadge role={member.role} />\n </div>\n </div>\n\n {member.invitedBy && (\n <div>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr('members.detail.invitedBy', 'Invited By')}\n </p>\n <p className=\"text-[var(--color-text-primary)] font-medium\">{member.invitedBy}</p>\n </div>\n )}\n\n {member.joinedAt && (\n <div>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr('members.detail.joinedAt', 'Joined At')}\n </p>\n <p className=\"text-[var(--color-text-primary)] font-medium\">\n {new Date(member.joinedAt).toLocaleString()}\n </p>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -129,7 +129,7 @@ function w() {
129
129
  }), A && O(l.MEMBER_INVITE) && /* @__PURE__ */ S("button", {
130
130
  type: "button",
131
131
  onClick: () => E(`${D}/${j}/members/invite`),
132
- className: "inline-flex min-h-11 items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-4 py-2.5 text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90 active:scale-[0.98]",
132
+ className: "inline-flex min-h-11 items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-4 py-2.5 text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90",
133
133
  children: [/* @__PURE__ */ x(te, {
134
134
  size: 18,
135
135
  "aria-hidden": "true"
@@ -155,7 +155,7 @@ function w() {
155
155
  onClick: () => {
156
156
  H();
157
157
  },
158
- className: "inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-4 py-2 text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)] active:scale-95",
158
+ className: "inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-4 py-2 text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]",
159
159
  "aria-label": w("members.list.refresh", "Refresh members"),
160
160
  title: w("members.list.refresh", "Refresh members"),
161
161
  children: /* @__PURE__ */ x(_, {