@burdenoff/microfe-organization 2026.624.1 → 2026.625.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 (45) hide show
  1. package/dist/organization-management/AdminOrganizationRoot.js +4 -4
  2. package/dist/organization-management/AdminOrganizationRoot.js.map +1 -1
  3. package/dist/organization-management/UserOrganizationRoot.js +4 -4
  4. package/dist/organization-management/UserOrganizationRoot.js.map +1 -1
  5. package/dist/organization-management/modules/members/components/BulkInviteForm.js +155 -174
  6. package/dist/organization-management/modules/members/components/BulkInviteForm.js.map +1 -1
  7. package/dist/organization-management/modules/members/components/PendingInvitesList.js +78 -101
  8. package/dist/organization-management/modules/members/components/PendingInvitesList.js.map +1 -1
  9. package/dist/organization-management/modules/members/pages/InviteMemberPage.js +58 -52
  10. package/dist/organization-management/modules/members/pages/InviteMemberPage.js.map +1 -1
  11. package/dist/organization-management/modules/members/pages/InvitePeoplePage.js +42 -40
  12. package/dist/organization-management/modules/members/pages/InvitePeoplePage.js.map +1 -1
  13. package/dist/organization-management/modules/members/pages/MemberDetailPage.js +71 -69
  14. package/dist/organization-management/modules/members/pages/MemberDetailPage.js.map +1 -1
  15. package/dist/organization-management/modules/members/pages/MembersListPage.js +233 -204
  16. package/dist/organization-management/modules/members/pages/MembersListPage.js.map +1 -1
  17. package/dist/organization-management/modules/members/pages/MyInvitesPage.js +38 -37
  18. package/dist/organization-management/modules/members/pages/MyInvitesPage.js.map +1 -1
  19. package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js +134 -132
  20. package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js.map +1 -1
  21. package/dist/organization-management/modules/organizations/pages/OrganizationCreatePage.js +39 -37
  22. package/dist/organization-management/modules/organizations/pages/OrganizationCreatePage.js.map +1 -1
  23. package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js +164 -167
  24. package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js.map +1 -1
  25. package/dist/organization-management/modules/organizations/pages/OrganizationEditPage.js +49 -47
  26. package/dist/organization-management/modules/organizations/pages/OrganizationEditPage.js.map +1 -1
  27. package/dist/organization-management/modules/organizations/pages/OrganizationsListPage.js +258 -230
  28. package/dist/organization-management/modules/organizations/pages/OrganizationsListPage.js.map +1 -1
  29. package/dist/organization-management/modules/workspaces/components/WorkspaceCard.js +43 -50
  30. package/dist/organization-management/modules/workspaces/components/WorkspaceCard.js.map +1 -1
  31. package/dist/organization-management/modules/workspaces/pages/WorkspaceCreatePage.js +40 -38
  32. package/dist/organization-management/modules/workspaces/pages/WorkspaceCreatePage.js.map +1 -1
  33. package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js +230 -299
  34. package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js.map +1 -1
  35. package/dist/organization-management/modules/workspaces/pages/WorkspaceEditPage.js +47 -45
  36. package/dist/organization-management/modules/workspaces/pages/WorkspaceEditPage.js.map +1 -1
  37. package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js +117 -74
  38. package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js.map +1 -1
  39. package/dist/organization-management/shared/components/feedback/EmptyState.js +1 -1
  40. package/dist/organization-management/shared/components/feedback/EmptyState.js.map +1 -1
  41. package/dist/organization-management/shared/components/feedback/ErrorState.js +1 -1
  42. package/dist/organization-management/shared/components/feedback/ErrorState.js.map +1 -1
  43. package/dist/organization-management/shared/components/feedback/LoadingState.js +1 -1
  44. package/dist/organization-management/shared/components/feedback/LoadingState.js.map +1 -1
  45. package/package.json +2 -2
@@ -8,78 +8,80 @@ import { useOrganizationPageView as o } from "../../../hooks/useOrganizationPage
8
8
  import { useOrgsWithPermission as s } from "../../organizations/hooks/useOrgsWithPermission.js";
9
9
  import { useEffect as c, useMemo as l, useState as u } from "react";
10
10
  import { Building as d, ChevronRight as f, UserPlus as p } from "lucide-react";
11
- import { jsx as m, jsxs as h } from "react/jsx-runtime";
11
+ import { GlassCard as m } from "@burdenoff/fe-libs/ui";
12
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
12
13
  //#region src/organization-management/modules/members/pages/InvitePeoplePage.tsx
13
- function g() {
14
+ function _() {
14
15
  o("organizations.invite-people");
15
- let g = n(), { navigate: _, basePath: v = "/organizations" } = e(), { organizations: y, loading: b, error: x } = t(100, 0), { allowedIds: S, loading: C, isError: w } = s(l(() => y.map((e) => e.id), [y]), "member", "create"), T = l(() => y.filter((e) => S.has(e.id)), [y, S]), [E, D] = u(!1);
16
+ let _ = n(), { navigate: v, basePath: y = "/organizations" } = e(), { organizations: b, loading: x, error: S } = t(100, 0), { allowedIds: C, loading: w, isError: T } = s(l(() => b.map((e) => e.id), [b]), "member", "create"), E = l(() => b.filter((e) => C.has(e.id)), [b, C]), [D, O] = u(!1);
16
17
  return c(() => {
17
- E || b || C || T.length === 1 && (D(!0), _(`${v}/${T[0].id}/members/invite`));
18
+ D || x || w || E.length === 1 && (O(!0), v(`${y}/${E[0].id}/members/invite`));
18
19
  }, [
20
+ D,
21
+ x,
22
+ w,
19
23
  E,
20
- b,
21
- C,
22
- T,
23
- _,
24
- v
25
- ]), b || C ? /* @__PURE__ */ m("div", {
24
+ v,
25
+ y
26
+ ]), x || w ? /* @__PURE__ */ h("div", {
26
27
  className: "min-h-full bg-[var(--color-bg-canvas)] p-6",
27
- children: /* @__PURE__ */ m(r, { message: g("common.loading", "Loading...") })
28
- }) : x || w ? /* @__PURE__ */ m("div", {
28
+ children: /* @__PURE__ */ h(r, { message: _("common.loading", "Loading...") })
29
+ }) : S || T ? /* @__PURE__ */ h("div", {
29
30
  className: "min-h-full bg-[var(--color-bg-canvas)] p-6",
30
- children: /* @__PURE__ */ m(i, { message: x?.message || g("members.invitePeople.error", "Failed to load organizations for invite.") })
31
- }) : /* @__PURE__ */ m("div", {
32
- className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-300",
33
- children: /* @__PURE__ */ h("div", {
31
+ children: /* @__PURE__ */ h(i, { message: S?.message || _("members.invitePeople.error", "Failed to load organizations for invite.") })
32
+ }) : /* @__PURE__ */ h("div", {
33
+ className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-200",
34
+ children: /* @__PURE__ */ g("div", {
34
35
  className: "mx-auto max-w-3xl space-y-6",
35
- children: [/* @__PURE__ */ h("div", {
36
+ children: [/* @__PURE__ */ g("div", {
36
37
  className: "flex items-center gap-3",
37
- children: [/* @__PURE__ */ m(p, {
38
+ children: [/* @__PURE__ */ h(p, {
38
39
  size: 24,
39
40
  className: "text-[var(--color-text-primary)]",
40
41
  "aria-hidden": "true"
41
- }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h1", {
42
+ }), /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h1", {
42
43
  className: "text-2xl font-bold text-[var(--color-text-primary)]",
43
- children: g("members.invitePeople.title", "Invite People")
44
- }), /* @__PURE__ */ m("p", {
44
+ children: _("members.invitePeople.title", "Invite People")
45
+ }), /* @__PURE__ */ h("p", {
45
46
  className: "mt-1 text-sm text-[var(--color-text-secondary)]",
46
- children: g("members.invitePeople.subtitle", "Pick an organization to send an invite into. You can also invite from any organization or workspace detail page.")
47
+ children: _("members.invitePeople.subtitle", "Pick an organization to send an invite into. You can also invite from any organization or workspace detail page.")
47
48
  })] })]
48
- }), T.length === 0 ? /* @__PURE__ */ m("div", {
49
- className: "rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-6",
50
- children: /* @__PURE__ */ m(a, {
51
- icon: /* @__PURE__ */ m(p, {
49
+ }), E.length === 0 ? /* @__PURE__ */ h(m, {
50
+ treatment: "plain",
51
+ className: "border-border-seam p-6",
52
+ children: /* @__PURE__ */ h(a, {
53
+ icon: /* @__PURE__ */ h(p, {
52
54
  size: 40,
53
55
  "aria-hidden": "true"
54
56
  }),
55
- title: g("members.invitePeople.emptyTitle", "No organizations where you can invite"),
56
- description: g("members.invitePeople.emptyDescription", "You don't currently have permission to invite members into any organization. Ask an organization admin to grant you invite access.")
57
+ title: _("members.invitePeople.emptyTitle", "No organizations where you can invite"),
58
+ description: _("members.invitePeople.emptyDescription", "You don't currently have permission to invite members into any organization. Ask an organization admin to grant you invite access.")
57
59
  })
58
- }) : /* @__PURE__ */ m("ul", {
59
- className: "divide-y divide-[var(--color-border-default)] rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-[var(--shadow-elevation-1)]",
60
- children: T.map((e) => /* @__PURE__ */ m("li", { children: /* @__PURE__ */ h("button", {
60
+ }) : /* @__PURE__ */ h("ul", {
61
+ className: "divide-y divide-[var(--color-border-seam)] overflow-hidden rounded-card border border-border-seam bg-bg-surface shadow-elevation-1",
62
+ children: E.map((e) => /* @__PURE__ */ h("li", { children: /* @__PURE__ */ g("button", {
61
63
  type: "button",
62
- onClick: () => _(`${v}/${e.id}/members/invite`),
64
+ onClick: () => v(`${y}/${e.id}/members/invite`),
63
65
  className: "flex w-full items-center justify-between gap-4 px-5 py-4 text-left transition-colors hover:bg-[var(--color-bg-subtle)]",
64
- children: [/* @__PURE__ */ h("div", {
66
+ children: [/* @__PURE__ */ g("div", {
65
67
  className: "flex min-w-0 items-center gap-3",
66
- children: [/* @__PURE__ */ m("div", {
68
+ children: [/* @__PURE__ */ h("div", {
67
69
  className: "flex size-10 items-center justify-center rounded-lg bg-[var(--color-status-info-bgSubtle)] text-[var(--color-status-info-text)]",
68
- children: /* @__PURE__ */ m(d, {
70
+ children: /* @__PURE__ */ h(d, {
69
71
  size: 20,
70
72
  "aria-hidden": "true"
71
73
  })
72
- }), /* @__PURE__ */ h("div", {
74
+ }), /* @__PURE__ */ g("div", {
73
75
  className: "min-w-0",
74
- children: [/* @__PURE__ */ m("p", {
76
+ children: [/* @__PURE__ */ h("p", {
75
77
  className: "truncate text-sm font-semibold text-[var(--color-text-primary)]",
76
78
  children: e.name
77
- }), /* @__PURE__ */ h("p", {
79
+ }), /* @__PURE__ */ g("p", {
78
80
  className: "truncate font-mono text-xs text-[var(--color-text-secondary)]",
79
81
  children: ["/", e.slug]
80
82
  })]
81
83
  })]
82
- }), /* @__PURE__ */ m(f, {
84
+ }), /* @__PURE__ */ h(f, {
83
85
  size: 18,
84
86
  className: "shrink-0 text-[var(--color-text-secondary)]",
85
87
  "aria-hidden": "true"
@@ -90,6 +92,6 @@ function g() {
90
92
  });
91
93
  }
92
94
  //#endregion
93
- export { g as InvitePeoplePage };
95
+ export { _ as InvitePeoplePage };
94
96
 
95
97
  //# sourceMappingURL=InvitePeoplePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InvitePeoplePage.js","names":[],"sources":["../../../../../src/organization-management/modules/members/pages/InvitePeoplePage.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { Building, ChevronRight, UserPlus } from 'lucide-react';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useMyOrganizations } from '../../organizations/hooks/useOrganizations';\nimport { useOrgsWithPermission } from '../../organizations/hooks/useOrgsWithPermission';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { ErrorState } from '../../../shared/components/feedback/ErrorState';\nimport { EmptyState } from '../../../shared/components/feedback/EmptyState';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport { useOrganizationPageView } from '../../../hooks/useOrganizationPageView';\n\n/**\n * InvitePeoplePage\n *\n * Globally-reachable entry point (sidebar nav item) for inviting users.\n * Lists the orgs the current user can invite into, then deep-links into\n * each org's existing `members/invite` page so the invite flow itself\n * remains a single source of truth.\n *\n * If the user has exactly one org with invite permission, redirect\n * straight to that org's invite page — saves a click for the common case.\n */\nexport function InvitePeoplePage() {\n useOrganizationPageView('organizations.invite-people');\n const tr = useTr();\n const { navigate, basePath = '/organizations' } = useOrgConsole();\n const { organizations, loading, error } = useMyOrganizations(100, 0);\n\n const orgIds = useMemo(() => organizations.map((o) => o.id), [organizations]);\n const {\n allowedIds,\n loading: permLoading,\n isError: permError,\n } = useOrgsWithPermission(orgIds, 'member', 'create');\n\n const invitable = useMemo(\n () => organizations.filter((o) => allowedIds.has(o.id)),\n [organizations, allowedIds]\n );\n\n const [autoRedirected, setAutoRedirected] = useState(false);\n useEffect(() => {\n if (autoRedirected) return;\n if (loading || permLoading) return;\n if (invitable.length === 1) {\n setAutoRedirected(true);\n navigate(`${basePath}/${invitable[0].id}/members/invite`);\n }\n }, [autoRedirected, loading, permLoading, invitable, navigate, basePath]);\n\n if (loading || permLoading) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <LoadingState message={tr('common.loading', 'Loading...')} />\n </div>\n );\n }\n\n if (error || permError) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <ErrorState\n message={\n error?.message ||\n tr('members.invitePeople.error', 'Failed to load organizations for invite.')\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 <div className=\"mx-auto max-w-3xl space-y-6\">\n <div className=\"flex items-center gap-3\">\n <UserPlus size={24} className=\"text-[var(--color-text-primary)]\" aria-hidden=\"true\" />\n <div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.invitePeople.title', 'Invite People')}\n </h1>\n <p className=\"mt-1 text-sm text-[var(--color-text-secondary)]\">\n {tr(\n 'members.invitePeople.subtitle',\n 'Pick an organization to send an invite into. You can also invite from any organization or workspace detail page.'\n )}\n </p>\n </div>\n </div>\n\n {invitable.length === 0 ? (\n <div className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-6\">\n <EmptyState\n icon={<UserPlus size={40} aria-hidden=\"true\" />}\n title={tr('members.invitePeople.emptyTitle', 'No organizations where you can invite')}\n description={tr(\n 'members.invitePeople.emptyDescription',\n \"You don't currently have permission to invite members into any organization. Ask an organization admin to grant you invite access.\"\n )}\n />\n </div>\n ) : (\n <ul className=\"divide-y divide-[var(--color-border-default)] rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-[var(--shadow-elevation-1)]\">\n {invitable.map((org) => (\n <li key={org.id}>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${org.id}/members/invite`)}\n className=\"flex w-full items-center justify-between gap-4 px-5 py-4 text-left transition-colors hover:bg-[var(--color-bg-subtle)]\"\n >\n <div className=\"flex min-w-0 items-center gap-3\">\n <div className=\"flex size-10 items-center justify-center rounded-lg bg-[var(--color-status-info-bgSubtle)] text-[var(--color-status-info-text)]\">\n <Building size={20} aria-hidden=\"true\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-semibold text-[var(--color-text-primary)]\">\n {org.name}\n </p>\n <p className=\"truncate font-mono text-xs text-[var(--color-text-secondary)]\">\n /{org.slug}\n </p>\n </div>\n </div>\n <ChevronRight\n size={18}\n className=\"shrink-0 text-[var(--color-text-secondary)]\"\n aria-hidden=\"true\"\n />\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAsBA,SAAgB,IAAmB;AACjC,GAAwB,8BAA8B;CACtD,IAAM,IAAK,GAAO,EACZ,EAAE,aAAU,cAAW,qBAAqB,GAAe,EAC3D,EAAE,kBAAe,YAAS,aAAU,EAAmB,KAAK,EAAE,EAG9D,EACJ,eACA,SAAS,GACT,SAAS,MACP,EALW,QAAc,EAAc,KAAK,MAAM,EAAE,GAAG,EAAE,CAAC,EAAc,CAAC,EAK3C,UAAU,SAAS,EAE/C,IAAY,QACV,EAAc,QAAQ,MAAM,EAAW,IAAI,EAAE,GAAG,CAAC,EACvD,CAAC,GAAe,EAAW,CAC5B,EAEK,CAAC,GAAgB,KAAqB,EAAS,GAAM;AA+B3D,QA9BA,QAAgB;AACV,OACA,KAAW,KACX,EAAU,WAAW,MACvB,EAAkB,GAAK,EACvB,EAAS,GAAG,EAAS,GAAG,EAAU,GAAG,GAAG,iBAAiB;IAE1D;EAAC;EAAgB;EAAS;EAAa;EAAW;EAAU;EAAS,CAAC,EAErE,KAAW,IAEX,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EAAc,SAAS,EAAG,kBAAkB,aAAa,EAAI,CAAA;EACzD,CAAA,GAIN,KAAS,IAET,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EACE,SACE,GAAO,WACP,EAAG,8BAA8B,2CAA2C,EAE9E,CAAA;EACE,CAAA,GAKR,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAU,MAAM;KAAI,WAAU;KAAmC,eAAY;KAAS,CAAA,EACtF,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAG,8BAA8B,gBAAgB;KAC/C,CAAA,EACL,kBAAC,KAAD;KAAG,WAAU;eACV,EACC,iCACA,mHACD;KACC,CAAA,CACA,EAAA,CAAA,CACF;OAEL,EAAU,WAAW,IACpB,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KACE,MAAM,kBAAC,GAAD;MAAU,MAAM;MAAI,eAAY;MAAS,CAAA;KAC/C,OAAO,EAAG,mCAAmC,wCAAwC;KACrF,aAAa,EACX,yCACA,qIACD;KACD,CAAA;IACE,CAAA,GAEN,kBAAC,MAAD;IAAI,WAAU;cACX,EAAU,KAAK,MACd,kBAAC,MAAD,EAAA,UACE,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAS,GAAG,EAAS,GAAG,EAAI,GAAG,iBAAiB;KAC/D,WAAU;eAHZ,CAKE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD;QAAU,MAAM;QAAI,eAAY;QAAS,CAAA;OACrC,CAAA,EACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAI;QACH,CAAA,EACJ,kBAAC,KAAD;QAAG,WAAU;kBAAb,CAA6E,KACzE,EAAI,KACJ;UACA;SACF;SACN,kBAAC,GAAD;MACE,MAAM;MACN,WAAU;MACV,eAAY;MACZ,CAAA,CACK;QACN,EAzBI,EAAI,GAyBR,CACL;IACC,CAAA,CAEH;;EACF,CAAA"}
1
+ {"version":3,"file":"InvitePeoplePage.js","names":[],"sources":["../../../../../src/organization-management/modules/members/pages/InvitePeoplePage.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { Building, ChevronRight, UserPlus } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useMyOrganizations } from '../../organizations/hooks/useOrganizations';\nimport { useOrgsWithPermission } from '../../organizations/hooks/useOrgsWithPermission';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { ErrorState } from '../../../shared/components/feedback/ErrorState';\nimport { EmptyState } from '../../../shared/components/feedback/EmptyState';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport { useOrganizationPageView } from '../../../hooks/useOrganizationPageView';\n\n/**\n * InvitePeoplePage\n *\n * Globally-reachable entry point (sidebar nav item) for inviting users.\n * Lists the orgs the current user can invite into, then deep-links into\n * each org's existing `members/invite` page so the invite flow itself\n * remains a single source of truth.\n *\n * If the user has exactly one org with invite permission, redirect\n * straight to that org's invite page — saves a click for the common case.\n */\nexport function InvitePeoplePage() {\n useOrganizationPageView('organizations.invite-people');\n const tr = useTr();\n const { navigate, basePath = '/organizations' } = useOrgConsole();\n const { organizations, loading, error } = useMyOrganizations(100, 0);\n\n const orgIds = useMemo(() => organizations.map((o) => o.id), [organizations]);\n const {\n allowedIds,\n loading: permLoading,\n isError: permError,\n } = useOrgsWithPermission(orgIds, 'member', 'create');\n\n const invitable = useMemo(\n () => organizations.filter((o) => allowedIds.has(o.id)),\n [organizations, allowedIds]\n );\n\n const [autoRedirected, setAutoRedirected] = useState(false);\n useEffect(() => {\n if (autoRedirected) return;\n if (loading || permLoading) return;\n if (invitable.length === 1) {\n setAutoRedirected(true);\n navigate(`${basePath}/${invitable[0].id}/members/invite`);\n }\n }, [autoRedirected, loading, permLoading, invitable, navigate, basePath]);\n\n if (loading || permLoading) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <LoadingState message={tr('common.loading', 'Loading...')} />\n </div>\n );\n }\n\n if (error || permError) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <ErrorState\n message={\n error?.message ||\n tr('members.invitePeople.error', 'Failed to load organizations for invite.')\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-200\">\n <div className=\"mx-auto max-w-3xl space-y-6\">\n <div className=\"flex items-center gap-3\">\n <UserPlus size={24} className=\"text-[var(--color-text-primary)]\" aria-hidden=\"true\" />\n <div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.invitePeople.title', 'Invite People')}\n </h1>\n <p className=\"mt-1 text-sm text-[var(--color-text-secondary)]\">\n {tr(\n 'members.invitePeople.subtitle',\n 'Pick an organization to send an invite into. You can also invite from any organization or workspace detail page.'\n )}\n </p>\n </div>\n </div>\n\n {invitable.length === 0 ? (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-6\">\n <EmptyState\n icon={<UserPlus size={40} aria-hidden=\"true\" />}\n title={tr('members.invitePeople.emptyTitle', 'No organizations where you can invite')}\n description={tr(\n 'members.invitePeople.emptyDescription',\n \"You don't currently have permission to invite members into any organization. Ask an organization admin to grant you invite access.\"\n )}\n />\n </GlassCard>\n ) : (\n <ul className=\"divide-y divide-[var(--color-border-seam)] overflow-hidden rounded-card border border-border-seam bg-bg-surface shadow-elevation-1\">\n {invitable.map((org) => (\n <li key={org.id}>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${org.id}/members/invite`)}\n className=\"flex w-full items-center justify-between gap-4 px-5 py-4 text-left transition-colors hover:bg-[var(--color-bg-subtle)]\"\n >\n <div className=\"flex min-w-0 items-center gap-3\">\n <div className=\"flex size-10 items-center justify-center rounded-lg bg-[var(--color-status-info-bgSubtle)] text-[var(--color-status-info-text)]\">\n <Building size={20} aria-hidden=\"true\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-semibold text-[var(--color-text-primary)]\">\n {org.name}\n </p>\n <p className=\"truncate font-mono text-xs text-[var(--color-text-secondary)]\">\n /{org.slug}\n </p>\n </div>\n </div>\n <ChevronRight\n size={18}\n className=\"shrink-0 text-[var(--color-text-secondary)]\"\n aria-hidden=\"true\"\n />\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAuBA,SAAgB,IAAmB;AACjC,GAAwB,8BAA8B;CACtD,IAAM,IAAK,GAAO,EACZ,EAAE,aAAU,cAAW,qBAAqB,GAAe,EAC3D,EAAE,kBAAe,YAAS,aAAU,EAAmB,KAAK,EAAE,EAG9D,EACJ,eACA,SAAS,GACT,SAAS,MACP,EALW,QAAc,EAAc,KAAK,MAAM,EAAE,GAAG,EAAE,CAAC,EAAc,CAAC,EAK3C,UAAU,SAAS,EAE/C,IAAY,QACV,EAAc,QAAQ,MAAM,EAAW,IAAI,EAAE,GAAG,CAAC,EACvD,CAAC,GAAe,EAAW,CAC5B,EAEK,CAAC,GAAgB,KAAqB,EAAS,GAAM;AA+B3D,QA9BA,QAAgB;AACV,OACA,KAAW,KACX,EAAU,WAAW,MACvB,EAAkB,GAAK,EACvB,EAAS,GAAG,EAAS,GAAG,EAAU,GAAG,GAAG,iBAAiB;IAE1D;EAAC;EAAgB;EAAS;EAAa;EAAW;EAAU;EAAS,CAAC,EAErE,KAAW,IAEX,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EAAc,SAAS,EAAG,kBAAkB,aAAa,EAAI,CAAA;EACzD,CAAA,GAIN,KAAS,IAET,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EACE,SACE,GAAO,WACP,EAAG,8BAA8B,2CAA2C,EAE9E,CAAA;EACE,CAAA,GAKR,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAU,MAAM;KAAI,WAAU;KAAmC,eAAY;KAAS,CAAA,EACtF,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAG,8BAA8B,gBAAgB;KAC/C,CAAA,EACL,kBAAC,KAAD;KAAG,WAAU;eACV,EACC,iCACA,mHACD;KACC,CAAA,CACA,EAAA,CAAA,CACF;OAEL,EAAU,WAAW,IACpB,kBAAC,GAAD;IAAW,WAAU;IAAQ,WAAU;cACrC,kBAAC,GAAD;KACE,MAAM,kBAAC,GAAD;MAAU,MAAM;MAAI,eAAY;MAAS,CAAA;KAC/C,OAAO,EAAG,mCAAmC,wCAAwC;KACrF,aAAa,EACX,yCACA,qIACD;KACD,CAAA;IACQ,CAAA,GAEZ,kBAAC,MAAD;IAAI,WAAU;cACX,EAAU,KAAK,MACd,kBAAC,MAAD,EAAA,UACE,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAS,GAAG,EAAS,GAAG,EAAI,GAAG,iBAAiB;KAC/D,WAAU;eAHZ,CAKE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD;QAAU,MAAM;QAAI,eAAY;QAAS,CAAA;OACrC,CAAA,EACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAI;QACH,CAAA,EACJ,kBAAC,KAAD;QAAG,WAAU;kBAAb,CAA6E,KACzE,EAAI,KACJ;UACA;SACF;SACN,kBAAC,GAAD;MACE,MAAM;MACN,WAAU;MACV,eAAY;MACZ,CAAA,CACK;QACN,EAzBI,EAAI,GAyBR,CACL;IACC,CAAA,CAEH;;EACF,CAAA"}
@@ -7,132 +7,134 @@ import { MemberRoleBadge as a } from "../components/MemberRoleBadge.js";
7
7
  import { useMember as o } from "../hooks/useMembers.js";
8
8
  import { useMemo as s } from "react";
9
9
  import { ArrowLeft as c, Shield as l } from "lucide-react";
10
- import { usePermissions as u } from "@burdenoff/fe-libs/shared/providers/shell";
11
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
12
- import { useParams as p } from "react-router-dom";
13
- import { buildActorFallback as m, useActorProfiles as h } from "@burdenoff/fe-libs/shared";
10
+ import { EmphasisPanel as u, GlassCard as d } from "@burdenoff/fe-libs/ui";
11
+ import { usePermissions as f } from "@burdenoff/fe-libs/shared/providers/shell";
12
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
13
+ import { useParams as h } from "react-router-dom";
14
+ import { buildActorFallback as g, useActorProfiles as _ } from "@burdenoff/fe-libs/shared";
14
15
  //#region src/organization-management/modules/members/pages/MemberDetailPage.tsx
15
- function g() {
16
- let g = t(), { organizationId: _, userId: v } = p(), { navigate: y, basePath: b = "/organizations", apiGatewayUrl: x, authToken: S } = e(), { hasPermission: C, isLoading: w } = u(), { member: T, loading: E, error: D } = o(_, v), O = h(s(() => v ? [{
17
- actorId: v,
16
+ function v() {
17
+ let v = t(), { organizationId: y, userId: b } = h(), { navigate: x, basePath: S = "/organizations", apiGatewayUrl: C, authToken: w } = e(), { hasPermission: T, isLoading: E } = f(), { member: D, loading: O, error: k } = o(y, b), A = _(s(() => b ? [{
18
+ actorId: b,
18
19
  actorType: "user"
19
- }] : [], [v]), {
20
- apiGatewayUrl: x,
21
- authToken: S,
22
- orgId: _
23
- }), k = v && T ? O[T.userId] ?? m({
24
- actorId: T.userId,
20
+ }] : [], [b]), {
21
+ apiGatewayUrl: C,
22
+ authToken: w,
23
+ orgId: y
24
+ }), j = b && D ? A[D.userId] ?? g({
25
+ actorId: D.userId,
25
26
  actorType: "user"
26
27
  }) : null;
27
- return w ? /* @__PURE__ */ d("div", {
28
+ return E ? /* @__PURE__ */ p("div", {
28
29
  className: "min-h-full bg-[var(--color-bg-canvas)] p-6",
29
- children: /* @__PURE__ */ d(n, { message: g("common.loadingPermissions", "Loading permissions...") })
30
- }) : C(i.MEMBER_READ) ? E ? /* @__PURE__ */ d("div", {
30
+ children: /* @__PURE__ */ p(n, { message: v("common.loadingPermissions", "Loading permissions...") })
31
+ }) : T(i.MEMBER_READ) ? O ? /* @__PURE__ */ p("div", {
31
32
  className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6",
32
- children: /* @__PURE__ */ d(n, { message: g("members.detail.loading", "Loading member...") })
33
- }) : D || !T ? /* @__PURE__ */ d("div", {
33
+ children: /* @__PURE__ */ p(n, { message: v("members.detail.loading", "Loading member...") })
34
+ }) : k || !D ? /* @__PURE__ */ p("div", {
34
35
  className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6",
35
- children: /* @__PURE__ */ d(r, {
36
- message: D?.message || g("members.detail.notFound", "Member not found"),
36
+ children: /* @__PURE__ */ p(r, {
37
+ message: k?.message || v("members.detail.notFound", "Member not found"),
37
38
  action: {
38
- label: g("common.goBack", "Go Back"),
39
- onClick: () => y(`${b}/${_}/members`)
39
+ label: v("common.goBack", "Go Back"),
40
+ onClick: () => x(`${S}/${y}/members`)
40
41
  }
41
42
  })
42
- }) : /* @__PURE__ */ f("div", {
43
- className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-300",
44
- children: [/* @__PURE__ */ f("div", {
43
+ }) : /* @__PURE__ */ m("div", {
44
+ className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-200",
45
+ children: [/* @__PURE__ */ m("div", {
45
46
  className: "mb-6",
46
- children: [/* @__PURE__ */ f("button", {
47
+ children: [/* @__PURE__ */ m("button", {
47
48
  type: "button",
48
- onClick: () => y(`${b}/${_}/members`),
49
+ onClick: () => x(`${S}/${y}/members`),
49
50
  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
- children: [/* @__PURE__ */ d(c, { size: 20 }), g("members.detail.backToMembers", "Back to Members")]
51
- }), /* @__PURE__ */ f("div", {
51
+ children: [/* @__PURE__ */ p(c, { size: 20 }), v("members.detail.backToMembers", "Back to Members")]
52
+ }), /* @__PURE__ */ m(u, {
52
53
  className: "flex items-start gap-4",
53
- children: [/* @__PURE__ */ d("div", {
54
+ children: [/* @__PURE__ */ p("div", {
54
55
  className: "size-16 rounded-full bg-[var(--color-status-info-muted)] flex items-center justify-center",
55
- children: /* @__PURE__ */ d(l, {
56
+ children: /* @__PURE__ */ p(l, {
56
57
  size: 32,
57
58
  className: "text-[var(--color-status-info)]"
58
59
  })
59
- }), /* @__PURE__ */ f("div", { children: [
60
- /* @__PURE__ */ d("h1", {
60
+ }), /* @__PURE__ */ m("div", { children: [
61
+ /* @__PURE__ */ p("h1", {
61
62
  className: "text-3xl font-bold text-[var(--color-text-primary)]",
62
- children: k?.displayName ?? g("members.detail.titlePrefix", "Member")
63
+ children: j?.displayName ?? v("members.detail.titlePrefix", "Member")
63
64
  }),
64
- k?.email ? /* @__PURE__ */ d("p", {
65
+ j?.email ? /* @__PURE__ */ p("p", {
65
66
  className: "text-[var(--color-text-secondary)] mt-1 break-all",
66
- children: k.email
67
+ children: j.email
67
68
  }) : null,
68
- /* @__PURE__ */ d("p", {
69
+ /* @__PURE__ */ p("p", {
69
70
  className: "text-[var(--color-text-secondary)] mt-1",
70
- children: T.role
71
+ children: D.role
71
72
  }),
72
- /* @__PURE__ */ f("details", {
73
+ /* @__PURE__ */ m("details", {
73
74
  className: "mt-2 text-xs text-[var(--color-text-secondary)]",
74
- children: [/* @__PURE__ */ d("summary", {
75
+ children: [/* @__PURE__ */ p("summary", {
75
76
  className: "cursor-pointer",
76
- children: g("members.detail.showIds", "Show technical IDs")
77
- }), /* @__PURE__ */ f("dl", {
77
+ children: v("members.detail.showIds", "Show technical IDs")
78
+ }), /* @__PURE__ */ m("dl", {
78
79
  className: "mt-1 grid grid-cols-[auto_1fr] gap-x-3 gap-y-1",
79
80
  children: [
80
- /* @__PURE__ */ d("dt", { children: g("members.detail.userId", "User ID") }),
81
- /* @__PURE__ */ d("dd", {
81
+ /* @__PURE__ */ p("dt", { children: v("members.detail.userId", "User ID") }),
82
+ /* @__PURE__ */ p("dd", {
82
83
  className: "break-all font-mono",
83
- children: T.userId
84
+ children: D.userId
84
85
  }),
85
- /* @__PURE__ */ d("dt", { children: g("members.list.memberId", "Member ID") }),
86
- /* @__PURE__ */ d("dd", {
86
+ /* @__PURE__ */ p("dt", { children: v("members.list.memberId", "Member ID") }),
87
+ /* @__PURE__ */ p("dd", {
87
88
  className: "break-all font-mono",
88
- children: T.id
89
+ children: D.id
89
90
  })
90
91
  ]
91
92
  })]
92
93
  })
93
94
  ] })]
94
95
  })]
95
- }), /* @__PURE__ */ f("div", {
96
- className: "bg-[var(--color-bg-surface)] border border-[var(--color-border-default)] rounded-lg p-6",
97
- children: [/* @__PURE__ */ d("h2", {
96
+ }), /* @__PURE__ */ m(d, {
97
+ treatment: "plain",
98
+ className: "border-border-seam p-6",
99
+ children: [/* @__PURE__ */ p("h2", {
98
100
  className: "text-lg font-semibold text-[var(--color-text-primary)] mb-4",
99
- children: g("members.detail.info", "Member Information")
100
- }), /* @__PURE__ */ f("div", {
101
+ children: v("members.detail.info", "Member Information")
102
+ }), /* @__PURE__ */ m("div", {
101
103
  className: "space-y-4",
102
104
  children: [
103
- /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("p", {
105
+ /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
104
106
  className: "text-sm text-[var(--color-text-secondary)]",
105
- children: g("members.list.column.role", "Role")
106
- }), /* @__PURE__ */ d("div", {
107
+ children: v("members.list.column.role", "Role")
108
+ }), /* @__PURE__ */ p("div", {
107
109
  className: "mt-1",
108
- children: /* @__PURE__ */ d(a, { role: T.role })
110
+ children: /* @__PURE__ */ p(a, { role: D.role })
109
111
  })] }),
110
- T.invitedBy && /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("p", {
112
+ D.invitedBy && /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
111
113
  className: "text-sm text-[var(--color-text-secondary)]",
112
- children: g("members.detail.invitedBy", "Invited By")
113
- }), /* @__PURE__ */ d("p", {
114
+ children: v("members.detail.invitedBy", "Invited By")
115
+ }), /* @__PURE__ */ p("p", {
114
116
  className: "text-[var(--color-text-primary)] font-medium",
115
- children: T.invitedBy
117
+ children: D.invitedBy
116
118
  })] }),
117
- T.joinedAt && /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("p", {
119
+ D.joinedAt && /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
118
120
  className: "text-sm text-[var(--color-text-secondary)]",
119
- children: g("members.detail.joinedAt", "Joined At")
120
- }), /* @__PURE__ */ d("p", {
121
+ children: v("members.detail.joinedAt", "Joined At")
122
+ }), /* @__PURE__ */ p("p", {
121
123
  className: "text-[var(--color-text-primary)] font-medium",
122
- children: new Date(T.joinedAt).toLocaleString()
124
+ children: new Date(D.joinedAt).toLocaleString()
123
125
  })] })
124
126
  ]
125
127
  })]
126
128
  })]
127
- }) : /* @__PURE__ */ d("div", {
129
+ }) : /* @__PURE__ */ p("div", {
128
130
  className: "min-h-full bg-[var(--color-bg-canvas)] p-6",
129
- children: /* @__PURE__ */ d("div", {
131
+ children: /* @__PURE__ */ p("div", {
130
132
  className: "p-8 text-center text-[var(--color-text-secondary)]",
131
- children: g("members.detail.noPermission", "You don't have permission to view member details.")
133
+ children: v("members.detail.noPermission", "You don't have permission to view member details.")
132
134
  })
133
135
  });
134
136
  }
135
137
  //#endregion
136
- export { g as MemberDetailPage };
138
+ export { v as MemberDetailPage };
137
139
 
138
140
  //# sourceMappingURL=MemberDetailPage.js.map
@@ -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)] 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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"}
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 { EmphasisPanel, GlassCard } from '@burdenoff/fe-libs/ui';\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-200\">\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 <EmphasisPanel 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 </EmphasisPanel>\n </div>\n\n {/* Details */}\n <GlassCard treatment=\"plain\" className=\"border-border-seam 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 </GlassCard>\n </div>\n );\n}\n"],"mappings":"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"}