@burdenoff/microfe-organization 2026.625.2 → 2026.625.3

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 (23) hide show
  1. package/dist/organization-management/modules/members/components/InviteStatusBadge.js +6 -2
  2. package/dist/organization-management/modules/members/components/InviteStatusBadge.js.map +1 -1
  3. package/dist/organization-management/modules/members/pages/InvitePeoplePage.js +16 -19
  4. package/dist/organization-management/modules/members/pages/InvitePeoplePage.js.map +1 -1
  5. package/dist/organization-management/modules/members/pages/MembersListPage.js +219 -220
  6. package/dist/organization-management/modules/members/pages/MembersListPage.js.map +1 -1
  7. package/dist/organization-management/modules/members/pages/MyInvitesPage.js +40 -56
  8. package/dist/organization-management/modules/members/pages/MyInvitesPage.js.map +1 -1
  9. package/dist/organization-management/modules/organizations/components/OrganizationStatusBadge.js +5 -1
  10. package/dist/organization-management/modules/organizations/components/OrganizationStatusBadge.js.map +1 -1
  11. package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js +36 -38
  12. package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js.map +1 -1
  13. package/dist/organization-management/modules/organizations/pages/OrganizationsListPage.js +118 -113
  14. package/dist/organization-management/modules/organizations/pages/OrganizationsListPage.js.map +1 -1
  15. package/dist/organization-management/modules/workspaces/components/WorkspaceStatusBadge.js +5 -1
  16. package/dist/organization-management/modules/workspaces/components/WorkspaceStatusBadge.js.map +1 -1
  17. package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js +168 -170
  18. package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js.map +1 -1
  19. package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js +245 -243
  20. package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js.map +1 -1
  21. package/package.json +2 -2
  22. package/dist/organization-management/shared/components/feedback/EmptyState.js +0 -31
  23. package/dist/organization-management/shared/components/feedback/EmptyState.js.map +0 -1
@@ -8,7 +8,8 @@ var l = {
8
8
  labelKey: "members.inviteStatus.pending",
9
9
  defaultLabel: "Pending",
10
10
  className: "bg-[var(--color-status-warning-bgSubtle)] text-[var(--color-status-warning-text)] border border-[var(--color-status-warning-border)]",
11
- icon: i
11
+ icon: i,
12
+ pulse: !0
12
13
  },
13
14
  ACCEPTED: {
14
15
  labelKey: "members.inviteStatus.accepted",
@@ -42,7 +43,10 @@ function u({ status: t }) {
42
43
  }, [n]), i = l[t] ?? l.PENDING, a = i.icon;
43
44
  return /* @__PURE__ */ s("span", {
44
45
  className: `inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-medium ${i.className}`,
45
- children: [/* @__PURE__ */ o(a, { size: 12 }), r(i.labelKey, i.defaultLabel)]
46
+ children: [/* @__PURE__ */ o(a, {
47
+ size: 12,
48
+ className: i.pulse ? "motion-safe:animate-vc-glow-pulse" : ""
49
+ }), r(i.labelKey, i.defaultLabel)]
46
50
  });
47
51
  }
48
52
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"InviteStatusBadge.js","names":[],"sources":["../../../../../src/organization-management/modules/members/components/InviteStatusBadge.tsx"],"sourcesContent":["import { Clock, Check, X, AlertTriangle, Ban } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface InviteStatusBadgeProps {\n status: string;\n}\n\nconst STATUS_CONFIG: Record<\n string,\n { labelKey: string; defaultLabel: string; className: string; icon: typeof Clock }\n> = {\n PENDING: {\n labelKey: 'members.inviteStatus.pending',\n defaultLabel: 'Pending',\n className:\n 'bg-[var(--color-status-warning-bgSubtle)] text-[var(--color-status-warning-text)] border border-[var(--color-status-warning-border)]',\n icon: Clock,\n },\n ACCEPTED: {\n labelKey: 'members.inviteStatus.accepted',\n defaultLabel: 'Accepted',\n className:\n 'bg-[var(--color-status-success-bgSubtle)] text-[var(--color-status-success-text)] border border-[var(--color-status-success-border)]',\n icon: Check,\n },\n REJECTED: {\n labelKey: 'members.inviteStatus.rejected',\n defaultLabel: 'Rejected',\n className:\n 'bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)] border border-[var(--color-status-error-border)]',\n icon: X,\n },\n EXPIRED: {\n labelKey: 'members.inviteStatus.expired',\n defaultLabel: 'Expired',\n className:\n 'bg-[var(--color-bg-muted)] text-[var(--color-text-secondary)] border border-[var(--color-border-default)]',\n icon: AlertTriangle,\n },\n CANCELLED: {\n labelKey: 'members.inviteStatus.cancelled',\n defaultLabel: 'Cancelled',\n className:\n 'bg-[var(--color-bg-muted)] text-[var(--color-text-secondary)] border border-[var(--color-border-default)]',\n icon: Ban,\n },\n};\n\nexport function InviteStatusBadge({ status }: InviteStatusBadgeProps) {\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string) => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n },\n [t]\n );\n const config = STATUS_CONFIG[status] ?? STATUS_CONFIG.PENDING;\n const Icon = config.icon;\n\n return (\n <span\n className={`inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-medium ${config.className}`}\n >\n <Icon size={12} />\n {tr(config.labelKey, config.defaultLabel)}\n </span>\n );\n}\n"],"mappings":";;;;;AAQA,IAAM,IAGF;CACF,SAAS;EACP,UAAU;EACV,cAAc;EACd,WACE;EACF,MAAM;EACP;CACD,UAAU;EACR,UAAU;EACV,cAAc;EACd,WACE;EACF,MAAM;EACP;CACD,UAAU;EACR,UAAU;EACV,cAAc;EACd,WACE;EACF,MAAM;EACP;CACD,SAAS;EACP,UAAU;EACV,cAAc;EACd,WACE;EACF,MAAM;EACP;CACD,WAAW;EACT,UAAU;EACV,cAAc;EACd,WACE;EACF,MAAM;EACP;CACF;AAED,SAAgB,EAAkB,EAAE,aAAkC;CACpE,IAAM,EAAE,SAAM,GAAS,EACjB,IAAK,GACR,GAAa,MAAqB;EACjC,IAAM,IAAa,EAAE,EAAI;AACzB,SAAO,MAAe,IAAM,IAAW;IAEzC,CAAC,EAAE,CACJ,EACK,IAAS,EAAc,MAAW,EAAc,SAChD,IAAO,EAAO;AAEpB,QACE,kBAAC,QAAD;EACE,WAAW,iFAAiF,EAAO;YADrG,CAGE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,EAAG,EAAO,UAAU,EAAO,aAAa,CACpC"}
1
+ {"version":3,"file":"InviteStatusBadge.js","names":[],"sources":["../../../../../src/organization-management/modules/members/components/InviteStatusBadge.tsx"],"sourcesContent":["import { Clock, Check, X, AlertTriangle, Ban } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface InviteStatusBadgeProps {\n status: string;\n}\n\nconst STATUS_CONFIG: Record<\n string,\n { labelKey: string; defaultLabel: string; className: string; icon: typeof Clock; pulse?: boolean }\n> = {\n PENDING: {\n labelKey: 'members.inviteStatus.pending',\n defaultLabel: 'Pending',\n className:\n 'bg-[var(--color-status-warning-bgSubtle)] text-[var(--color-status-warning-text)] border border-[var(--color-status-warning-border)]',\n icon: Clock,\n pulse: true,\n },\n ACCEPTED: {\n labelKey: 'members.inviteStatus.accepted',\n defaultLabel: 'Accepted',\n className:\n 'bg-[var(--color-status-success-bgSubtle)] text-[var(--color-status-success-text)] border border-[var(--color-status-success-border)]',\n icon: Check,\n },\n REJECTED: {\n labelKey: 'members.inviteStatus.rejected',\n defaultLabel: 'Rejected',\n className:\n 'bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)] border border-[var(--color-status-error-border)]',\n icon: X,\n },\n EXPIRED: {\n labelKey: 'members.inviteStatus.expired',\n defaultLabel: 'Expired',\n className:\n 'bg-[var(--color-bg-muted)] text-[var(--color-text-secondary)] border border-[var(--color-border-default)]',\n icon: AlertTriangle,\n },\n CANCELLED: {\n labelKey: 'members.inviteStatus.cancelled',\n defaultLabel: 'Cancelled',\n className:\n 'bg-[var(--color-bg-muted)] text-[var(--color-text-secondary)] border border-[var(--color-border-default)]',\n icon: Ban,\n },\n};\n\nexport function InviteStatusBadge({ status }: InviteStatusBadgeProps) {\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string) => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n },\n [t]\n );\n const config = STATUS_CONFIG[status] ?? STATUS_CONFIG.PENDING;\n const Icon = config.icon;\n\n return (\n <span\n className={`inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-medium ${config.className}`}\n >\n <Icon size={12} className={config.pulse ? 'motion-safe:animate-vc-glow-pulse' : ''} />\n {tr(config.labelKey, config.defaultLabel)}\n </span>\n );\n}\n"],"mappings":";;;;;AAQA,IAAM,IAGF;CACF,SAAS;EACP,UAAU;EACV,cAAc;EACd,WACE;EACF,MAAM;EACN,OAAO;EACR;CACD,UAAU;EACR,UAAU;EACV,cAAc;EACd,WACE;EACF,MAAM;EACP;CACD,UAAU;EACR,UAAU;EACV,cAAc;EACd,WACE;EACF,MAAM;EACP;CACD,SAAS;EACP,UAAU;EACV,cAAc;EACd,WACE;EACF,MAAM;EACP;CACD,WAAW;EACT,UAAU;EACV,cAAc;EACd,WACE;EACF,MAAM;EACP;CACF;AAED,SAAgB,EAAkB,EAAE,aAAkC;CACpE,IAAM,EAAE,SAAM,GAAS,EACjB,IAAK,GACR,GAAa,MAAqB;EACjC,IAAM,IAAa,EAAE,EAAI;AACzB,SAAO,MAAe,IAAM,IAAW;IAEzC,CAAC,EAAE,CACJ,EACK,IAAS,EAAc,MAAW,EAAc,SAChD,IAAO,EAAO;AAEpB,QACE,kBAAC,QAAD;EACE,WAAW,iFAAiF,EAAO;YADrG,CAGE,kBAAC,GAAD;GAAM,MAAM;GAAI,WAAW,EAAO,QAAQ,sCAAsC;GAAM,CAAA,EACrF,EAAG,EAAO,UAAU,EAAO,aAAa,CACpC"}
@@ -3,18 +3,17 @@ import { useMyOrganizations as t } from "../../organizations/hooks/useOrganizati
3
3
  import { useTr as n } from "../../../shared/hooks/useTr.js";
4
4
  import { LoadingState as r } from "../../../shared/components/feedback/LoadingState.js";
5
5
  import { ErrorState as i } from "../../../shared/components/feedback/ErrorState.js";
6
- import { EmptyState as a } from "../../../shared/components/feedback/EmptyState.js";
7
- import { useOrganizationPageView as o } from "../../../hooks/useOrganizationPageView.js";
8
- import { useOrgsWithPermission as s } from "../../organizations/hooks/useOrgsWithPermission.js";
9
- import { useEffect as c, useMemo as l, useState as u } from "react";
10
- import { Building as d, ChevronRight as f, UserPlus as p } from "lucide-react";
11
- import { GlassCard as m } from "@burdenoff/fe-libs/ui";
6
+ import { useOrganizationPageView as a } from "../../../hooks/useOrganizationPageView.js";
7
+ import { useOrgsWithPermission as o } from "../../organizations/hooks/useOrgsWithPermission.js";
8
+ import { useEffect as s, useMemo as c, useState as l } from "react";
9
+ import { Building as u, ChevronRight as d, UserPlus as f } from "lucide-react";
10
+ import { GlassCard as p, IllustratedEmptyState as m } from "@burdenoff/fe-libs/ui";
12
11
  import { jsx as h, jsxs as g } from "react/jsx-runtime";
13
12
  //#region src/organization-management/modules/members/pages/InvitePeoplePage.tsx
14
13
  function _() {
15
- o("organizations.invite-people");
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);
17
- return c(() => {
14
+ a("organizations.invite-people");
15
+ let _ = n(), { navigate: v, basePath: y = "/organizations" } = e(), { organizations: b, loading: x, error: S } = t(100, 0), { allowedIds: C, loading: w, isError: T } = o(c(() => b.map((e) => e.id), [b]), "member", "create"), E = c(() => b.filter((e) => C.has(e.id)), [b, C]), [D, O] = l(!1);
16
+ return s(() => {
18
17
  D || x || w || E.length === 1 && (O(!0), v(`${y}/${E[0].id}/members/invite`));
19
18
  }, [
20
19
  D,
@@ -35,7 +34,7 @@ function _() {
35
34
  className: "mx-auto max-w-3xl space-y-6",
36
35
  children: [/* @__PURE__ */ g("div", {
37
36
  className: "flex items-center gap-3",
38
- children: [/* @__PURE__ */ h(p, {
37
+ children: [/* @__PURE__ */ h(f, {
39
38
  size: 24,
40
39
  className: "text-[var(--color-text-primary)]",
41
40
  "aria-hidden": "true"
@@ -46,14 +45,12 @@ function _() {
46
45
  className: "mt-1 text-sm text-[var(--color-text-secondary)]",
47
46
  children: _("members.invitePeople.subtitle", "Pick an organization to send an invite into. You can also invite from any organization or workspace detail page.")
48
47
  })] })]
49
- }), E.length === 0 ? /* @__PURE__ */ h(m, {
50
- treatment: "plain",
48
+ }), E.length === 0 ? /* @__PURE__ */ h(p, {
49
+ treatment: "glass",
50
+ glow: !0,
51
51
  className: "border-border-seam p-6",
52
- children: /* @__PURE__ */ h(a, {
53
- icon: /* @__PURE__ */ h(p, {
54
- size: 40,
55
- "aria-hidden": "true"
56
- }),
52
+ children: /* @__PURE__ */ h(m, {
53
+ illustration: "empty-people",
57
54
  title: _("members.invitePeople.emptyTitle", "No organizations where you can invite"),
58
55
  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.")
59
56
  })
@@ -67,7 +64,7 @@ function _() {
67
64
  className: "flex min-w-0 items-center gap-3",
68
65
  children: [/* @__PURE__ */ h("div", {
69
66
  className: "flex size-10 items-center justify-center rounded-lg bg-[var(--color-status-info-bgSubtle)] text-[var(--color-status-info-text)]",
70
- children: /* @__PURE__ */ h(d, {
67
+ children: /* @__PURE__ */ h(u, {
71
68
  size: 20,
72
69
  "aria-hidden": "true"
73
70
  })
@@ -81,7 +78,7 @@ function _() {
81
78
  children: ["/", e.slug]
82
79
  })]
83
80
  })]
84
- }), /* @__PURE__ */ h(f, {
81
+ }), /* @__PURE__ */ h(d, {
85
82
  size: 18,
86
83
  className: "shrink-0 text-[var(--color-text-secondary)]",
87
84
  "aria-hidden": "true"
@@ -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 { 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"}
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, IllustratedEmptyState } 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 { 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=\"glass\" glow className=\"border-border-seam p-6\">\n <IllustratedEmptyState\n illustration=\"empty-people\"\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":";;;;;;;;;;;;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,GAAD;IAAW,WAAU;IAAQ,MAAA;IAAK,WAAU;cAC1C,kBAAC,GAAD;KACE,cAAa;KACb,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"}