@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,24 +8,25 @@ import { LoadingState as a } from "../../../shared/components/feedback/LoadingSt
8
8
  import { ErrorState as te } from "../../../shared/components/feedback/ErrorState.js";
9
9
  import { EmptyState as o } from "../../../shared/components/feedback/EmptyState.js";
10
10
  import { useDebouncedValue as s } from "../../../shared/hooks/useDebouncedValue.js";
11
- import { useConfirmDialog as c } from "../../../shared/components/dialog/ConfirmDialog.js";
12
- import { PERMISSIONS as l } from "../../../constants/permissions.js";
13
- import { isNative as u, nativeConfirm as d, nativeImpact as f, nativeNotify as p, nativeToast as m } from "../../../../utils/nativeBridge.js";
14
- import { useDeleteWorkspace as ne, useWorkspaces as re } from "../hooks/useWorkspaces.js";
15
- import { WorkspaceStatusBadge as h } from "../components/WorkspaceStatusBadge.js";
16
- import { useEffect as ie, useMemo as g, useState as _ } from "react";
17
- import { Briefcase as ae, Eye as v, Plus as y, RefreshCw as oe, SquarePen as b, Trash2 as x } from "lucide-react";
18
- import { usePermissions as S } from "@burdenoff/fe-libs/shared/providers/shell";
19
- import { Fragment as se, jsx as C, jsxs as w } from "react/jsx-runtime";
11
+ import { useConfirmDialog as ne } from "../../../shared/components/dialog/ConfirmDialog.js";
12
+ import { PERMISSIONS as c } from "../../../constants/permissions.js";
13
+ import { isNative as l, nativeConfirm as re, nativeImpact as ie, nativeNotify as u, nativeToast as d } from "../../../../utils/nativeBridge.js";
14
+ import { useDeleteWorkspace as f, useWorkspaces as p } from "../hooks/useWorkspaces.js";
15
+ import { WorkspaceStatusBadge as m } from "../components/WorkspaceStatusBadge.js";
16
+ import { useEffect as ae, useMemo as h, useState as g } from "react";
17
+ import { Briefcase as oe, Eye as _, Plus as se, RefreshCw as ce, SquarePen as v, Trash2 as y } from "lucide-react";
18
+ import { GlassCard as b } from "@burdenoff/fe-libs/ui";
19
+ import { usePermissions as x } from "@burdenoff/fe-libs/shared/providers/shell";
20
+ import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
20
21
  //#region src/organization-management/modules/workspaces/pages/WorkspacesListPage.tsx
21
22
  function T(e) {
22
23
  return new Date(e).toLocaleDateString();
23
24
  }
24
25
  function E({ mode: E = "my" } = {}) {
25
- let D = r(), { navigate: O, basePath: k = "/organizations" } = e(), { hasPermission: A, isLoading: ce } = S(), [j, le] = _(""), M = s(j, 300), [N, P] = _({}), [F, I] = _(/* @__PURE__ */ new Set()), { openConfirmDialog: L, ConfirmDialog: R } = c(), z = E === "admin" ? "all" : "my", { workspaces: B, loading: V, error: H, refetch: U } = re({
26
+ let D = r(), { navigate: O, basePath: k = "/organizations" } = e(), { hasPermission: A, isLoading: le } = x(), [j, ue] = g(""), M = s(j, 300), [N, P] = g({}), [F, I] = g(/* @__PURE__ */ new Set()), { openConfirmDialog: L, ConfirmDialog: R } = ne(), z = E === "admin" ? "all" : "my", { workspaces: B, loading: V, error: H, refetch: U } = p({
26
27
  ...N,
27
28
  search: M || void 0
28
- }, z === "my" ? 100 : 20, 0, z), W = g(() => {
29
+ }, z === "my" ? 100 : 20, 0, z), W = h(() => {
29
30
  if (z !== "my") return B;
30
31
  let e = M.trim().toLowerCase();
31
32
  return B.filter((t) => {
@@ -37,31 +38,31 @@ function E({ mode: E = "my" } = {}) {
37
38
  z,
38
39
  M,
39
40
  N.status
40
- ]), { deleteWorkspace: G, loading: K } = ne();
41
- ie(() => {
41
+ ]), { deleteWorkspace: de, loading: G } = f();
42
+ ae(() => {
42
43
  I((e) => {
43
44
  let t = new Set(W.map((e) => e.id)), n = new Set([...e].filter((e) => t.has(e)));
44
45
  return n.size === e.size ? e : n;
45
46
  });
46
47
  }, [W]);
47
- let q = g(() => W.filter((e) => F.has(e.id)), [F, W]), J = W.length > 0 && W.every((e) => F.has(e.id)), Y = W.some((e) => F.has(e.id)) && !J, X = async (e) => {
48
+ let K = h(() => W.filter((e) => F.has(e.id)), [F, W]), q = W.length > 0 && W.every((e) => F.has(e.id)), J = W.some((e) => F.has(e.id)) && !q, Y = async (e) => {
48
49
  try {
49
50
  let n = (await Promise.allSettled(e.map(async (e) => {
50
- let t = await G(e);
51
+ let t = await de(e);
51
52
  if (t.errors?.length) throw Error(t.errors[0]?.message ?? D("workspaces.suspend.failed", "Failed to suspend workspace"));
52
53
  }))).find((e) => e.status === "rejected");
53
54
  if (n?.status === "rejected") throw n.reason;
54
55
  I(/* @__PURE__ */ new Set()), await U();
55
56
  let r = e.length === 1 ? D("workspaces.suspend.successSingle", "Workspace suspended successfully") : `${e.length} ${D("workspaces.suspend.successMany", "workspaces suspended successfully")}`;
56
- t.success(r), p("success"), u() && m(r);
57
+ t.success(r), u("success"), l() && d(r);
57
58
  } catch (e) {
58
59
  let n = e instanceof Error ? e.message : D("workspaces.suspend.failed", "Failed to suspend workspace");
59
- t.error(n), p("error"), u() && m(n);
60
+ t.error(n), u("error"), l() && d(n);
60
61
  }
61
- }, Z = (e, t) => {
62
- f("medium");
62
+ }, X = (e, t) => {
63
+ ie("medium");
63
64
  let n = D("workspaces.suspend.title", "Suspend workspace"), r = `${D("workspaces.suspend.prefix", "Suspend")} ${t}? ${D("workspaces.suspend.suffix", "Workspace members will lose access until it is reactivated.")}`;
64
- d({
65
+ re({
65
66
  title: n,
66
67
  message: r,
67
68
  okButtonTitle: D("workspaces.suspend.confirm", "Suspend")
@@ -72,18 +73,18 @@ function E({ mode: E = "my" } = {}) {
72
73
  confirmText: D("workspaces.suspend.confirm", "Suspend"),
73
74
  variant: "warning",
74
75
  onConfirm: () => {
75
- X([e]);
76
+ Y([e]);
76
77
  }
77
- }) : t && X([e]);
78
+ }) : t && Y([e]);
78
79
  });
79
- }, ue = () => {
80
- q.length !== 0 && L({
80
+ }, Z = () => {
81
+ K.length !== 0 && L({
81
82
  title: D("workspaces.suspend.bulkTitle", "Suspend selected workspaces"),
82
- description: `${D("workspaces.suspend.prefix", "Suspend")} ${q.length} ${D(q.length === 1 ? "workspaces.suspend.bulkSuffixSingle" : "workspaces.suspend.bulkSuffixMany", q.length === 1 ? "selected workspace?" : "selected workspaces?")}`,
83
- confirmText: `${D("workspaces.suspend.confirm", "Suspend")} ${q.length}`,
83
+ description: `${D("workspaces.suspend.prefix", "Suspend")} ${K.length} ${D(K.length === 1 ? "workspaces.suspend.bulkSuffixSingle" : "workspaces.suspend.bulkSuffixMany", K.length === 1 ? "selected workspace?" : "selected workspaces?")}`,
84
+ confirmText: `${D("workspaces.suspend.confirm", "Suspend")} ${K.length}`,
84
85
  variant: "warning",
85
86
  onConfirm: () => {
86
- X(q.map((e) => e.id));
87
+ Y(K.map((e) => e.id));
87
88
  }
88
89
  });
89
90
  }, Q = (e, t) => {
@@ -99,10 +100,10 @@ function E({ mode: E = "my" } = {}) {
99
100
  }), n;
100
101
  });
101
102
  };
102
- return ce ? /* @__PURE__ */ C("div", {
103
+ return le ? /* @__PURE__ */ C("div", {
103
104
  className: "min-h-full bg-[var(--color-bg-canvas)] p-6",
104
105
  children: /* @__PURE__ */ C(a, { message: D("common.loadingPermissions", "Loading permissions...") })
105
- }) : A(l.WORKSPACE_LIST) ? V ? /* @__PURE__ */ C("div", {
106
+ }) : A(c.WORKSPACE_LIST) ? V ? /* @__PURE__ */ C("div", {
106
107
  className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6",
107
108
  children: /* @__PURE__ */ C(a, { message: D("workspaces.list.loading", "Loading workspaces...") })
108
109
  }) : H ? /* @__PURE__ */ C("div", {
@@ -117,7 +118,7 @@ function E({ mode: E = "my" } = {}) {
117
118
  }
118
119
  })
119
120
  }) : /* @__PURE__ */ w("div", {
120
- className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-300",
121
+ className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-200",
121
122
  children: [/* @__PURE__ */ w("div", {
122
123
  className: "mx-auto flex w-full max-w-7xl flex-col gap-6",
123
124
  children: [
@@ -132,11 +133,11 @@ function E({ mode: E = "my" } = {}) {
132
133
  className: "max-w-2xl text-[var(--color-text-secondary)]",
133
134
  children: D("workspaces.list.subtitle", "Manage organization workspaces, review their status, and open the workspace detail flow.")
134
135
  })]
135
- }), A(l.WORKSPACE_CREATE) && /* @__PURE__ */ w("button", {
136
+ }), A(c.WORKSPACE_CREATE) && /* @__PURE__ */ w("button", {
136
137
  type: "button",
137
138
  onClick: () => O(`${k}/workspaces/new`),
138
139
  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",
139
- children: [/* @__PURE__ */ C(y, {
140
+ children: [/* @__PURE__ */ C(se, {
140
141
  size: 18,
141
142
  "aria-hidden": "true"
142
143
  }), /* @__PURE__ */ C("span", {
@@ -145,14 +146,53 @@ function E({ mode: E = "my" } = {}) {
145
146
  })]
146
147
  })]
147
148
  }),
148
- /* @__PURE__ */ w("div", {
149
- className: "rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-4 shadow-[var(--shadow-elevation-1)]",
149
+ B.length > 0 ? /* @__PURE__ */ w("div", {
150
+ className: "grid grid-cols-2 gap-4 sm:grid-cols-3",
151
+ children: [
152
+ /* @__PURE__ */ w(b, {
153
+ treatment: "metric",
154
+ className: "p-4",
155
+ children: [/* @__PURE__ */ C("p", {
156
+ className: "text-sm text-text-secondary",
157
+ children: D("workspaces.list.title", "Workspaces")
158
+ }), /* @__PURE__ */ C("p", {
159
+ className: "mt-1 text-2xl font-semibold tabular-nums text-text-primary",
160
+ children: B.length
161
+ })]
162
+ }),
163
+ /* @__PURE__ */ w(b, {
164
+ treatment: "metric",
165
+ className: "p-4",
166
+ children: [/* @__PURE__ */ C("p", {
167
+ className: "text-sm text-text-secondary",
168
+ children: D("workspaces.status.active", "Active")
169
+ }), /* @__PURE__ */ C("p", {
170
+ className: "mt-1 text-2xl font-semibold tabular-nums text-text-primary",
171
+ children: B.filter((e) => e.status === n.ACTIVE).length
172
+ })]
173
+ }),
174
+ /* @__PURE__ */ w(b, {
175
+ treatment: "metric",
176
+ className: "col-span-2 p-4 sm:col-span-1",
177
+ children: [/* @__PURE__ */ C("p", {
178
+ className: "text-sm text-text-secondary",
179
+ children: D("workspaces.list.members", "Members")
180
+ }), /* @__PURE__ */ C("p", {
181
+ className: "mt-1 text-2xl font-semibold tabular-nums text-text-primary",
182
+ children: B.reduce((e, t) => e + (t.memberCount ?? 0), 0)
183
+ })]
184
+ })
185
+ ]
186
+ }) : null,
187
+ /* @__PURE__ */ w(b, {
188
+ treatment: "plain",
189
+ className: "border-border-seam p-4",
150
190
  children: [/* @__PURE__ */ w("div", {
151
191
  className: "flex flex-col gap-3 lg:flex-row lg:items-center",
152
192
  children: [
153
193
  /* @__PURE__ */ C(ee, {
154
194
  value: j,
155
- onChange: le,
195
+ onChange: ue,
156
196
  placeholder: D("workspaces.list.searchPlaceholder", "Search workspaces..."),
157
197
  label: D("workspaces.list.searchLabel", "Search workspaces"),
158
198
  inputId: "workspaces-search",
@@ -169,7 +209,7 @@ function E({ mode: E = "my" } = {}) {
169
209
  ...N,
170
210
  status: e.target.value ? e.target.value : void 0
171
211
  }),
172
- className: "bg-transparent text-[var(--color-text-primary)] focus:outline-none",
212
+ className: "bg-transparent text-[var(--color-text-primary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]",
173
213
  "aria-label": D("workspaces.list.filterByStatus", "Filter by workspace status"),
174
214
  children: [
175
215
  /* @__PURE__ */ C("option", {
@@ -199,7 +239,7 @@ function E({ mode: E = "my" } = {}) {
199
239
  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)]",
200
240
  "aria-label": D("workspaces.list.refresh", "Refresh workspaces"),
201
241
  title: D("workspaces.list.refresh", "Refresh workspaces"),
202
- children: /* @__PURE__ */ C(oe, {
242
+ children: /* @__PURE__ */ C(ce, {
203
243
  size: 18,
204
244
  "aria-hidden": "true"
205
245
  })
@@ -212,8 +252,8 @@ function E({ mode: E = "my" } = {}) {
212
252
  children: [/* @__PURE__ */ w("label", {
213
253
  className: "flex items-center gap-2 text-sm text-[var(--color-text-primary)]",
214
254
  children: [/* @__PURE__ */ C(i, {
215
- checked: J,
216
- indeterminate: Y,
255
+ checked: q,
256
+ indeterminate: J,
217
257
  onChange: $,
218
258
  ariaLabel: D("workspaces.list.selectAll", "Select all workspaces")
219
259
  }), /* @__PURE__ */ C("span", { children: D("common.selectAllVisible", "Select all visible") })]
@@ -232,20 +272,20 @@ function E({ mode: E = "my" } = {}) {
232
272
  " ",
233
273
  D("common.selected", "selected")
234
274
  ]
235
- }), A(l.WORKSPACE_DELETE) && /* @__PURE__ */ w("button", {
275
+ }), A(c.WORKSPACE_DELETE) && /* @__PURE__ */ w("button", {
236
276
  type: "button",
237
- onClick: ue,
238
- disabled: q.length === 0 || K,
277
+ onClick: Z,
278
+ disabled: K.length === 0 || G,
239
279
  className: "inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border border-[var(--color-status-warning-border)] px-3 py-2 text-[var(--color-status-warning-text)] transition-all duration-200 hover:bg-[var(--color-status-warning-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50",
240
280
  children: [
241
- /* @__PURE__ */ C(x, {
281
+ /* @__PURE__ */ C(y, {
242
282
  size: 16,
243
283
  "aria-hidden": "true"
244
284
  }),
245
285
  /* @__PURE__ */ C("span", { children: D("workspaces.list.suspendSelected", "Suspend Selected") }),
246
- q.length > 0 ? /* @__PURE__ */ w("span", { children: [
286
+ K.length > 0 ? /* @__PURE__ */ w("span", { children: [
247
287
  "(",
248
- q.length,
288
+ K.length,
249
289
  ")"
250
290
  ] }) : null
251
291
  ]
@@ -253,24 +293,26 @@ function E({ mode: E = "my" } = {}) {
253
293
  })]
254
294
  }) : null]
255
295
  }),
256
- W.length === 0 ? /* @__PURE__ */ C("div", {
257
- className: "rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-6 shadow-[var(--shadow-elevation-1)]",
296
+ W.length === 0 ? /* @__PURE__ */ C(b, {
297
+ treatment: "plain",
298
+ className: "border-border-seam p-6",
258
299
  children: /* @__PURE__ */ C(o, {
259
- icon: /* @__PURE__ */ C(ae, {
300
+ icon: /* @__PURE__ */ C(oe, {
260
301
  size: 40,
261
302
  "aria-hidden": "true"
262
303
  }),
263
304
  title: D("workspaces.list.emptyNoneTitle", "No workspaces found"),
264
- description: A(l.WORKSPACE_CREATE) ? D("workspaces.list.emptyNoneDescription", "Create a workspace to start mapping members, organization ownership, and collaboration settings.") : D("workspaces.list.emptyNoneDescriptionViewer", "No workspaces have been created yet."),
265
- action: A(l.WORKSPACE_CREATE) ? {
305
+ description: A(c.WORKSPACE_CREATE) ? D("workspaces.list.emptyNoneDescription", "Create a workspace to start mapping members, organization ownership, and collaboration settings.") : D("workspaces.list.emptyNoneDescriptionViewer", "No workspaces have been created yet."),
306
+ action: A(c.WORKSPACE_CREATE) ? {
266
307
  label: D("workspaces.create.button", "Create Workspace"),
267
308
  onClick: () => O(`${k}/workspaces/new`)
268
309
  } : void 0
269
310
  })
270
- }) : /* @__PURE__ */ w(se, { children: [/* @__PURE__ */ C("div", {
311
+ }) : /* @__PURE__ */ w(S, { children: [/* @__PURE__ */ C("div", {
271
312
  className: "grid gap-4 md:hidden",
272
- children: W.map((e) => /* @__PURE__ */ w("article", {
273
- className: "rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-4 shadow-[var(--shadow-elevation-1)]",
313
+ children: W.map((e) => /* @__PURE__ */ w(b, {
314
+ treatment: "insight",
315
+ className: "border-border-seam p-4",
274
316
  children: [/* @__PURE__ */ w("div", {
275
317
  className: "flex items-start gap-3",
276
318
  children: [/* @__PURE__ */ C(i, {
@@ -284,7 +326,7 @@ function E({ mode: E = "my" } = {}) {
284
326
  children: [/* @__PURE__ */ C("h2", {
285
327
  className: "text-base font-semibold text-[var(--color-text-primary)]",
286
328
  children: e.name
287
- }), /* @__PURE__ */ C(h, { status: e.status })]
329
+ }), /* @__PURE__ */ C(m, { status: e.status })]
288
330
  }), /* @__PURE__ */ w("p", {
289
331
  className: "mt-1 break-all font-mono text-sm text-[var(--color-text-muted)]",
290
332
  children: ["/", e.slug]
@@ -312,26 +354,26 @@ function E({ mode: E = "my" } = {}) {
312
354
  type: "button",
313
355
  onClick: () => O(`${k}/workspaces/${e.id}`),
314
356
  className: "inline-flex min-h-10 items-center gap-2 rounded-lg border border-[var(--color-border-default)] px-3 py-2 text-sm text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]",
315
- children: [/* @__PURE__ */ C(v, {
357
+ children: [/* @__PURE__ */ C(_, {
316
358
  size: 16,
317
359
  "aria-hidden": "true"
318
360
  }), D("common.view", "View")]
319
361
  }),
320
- A(l.WORKSPACE_UPDATE) && /* @__PURE__ */ w("button", {
362
+ A(c.WORKSPACE_UPDATE) && /* @__PURE__ */ w("button", {
321
363
  type: "button",
322
364
  onClick: () => O(`${k}/workspaces/${e.id}/edit`),
323
365
  className: "inline-flex min-h-10 items-center gap-2 rounded-lg border border-[var(--color-border-default)] px-3 py-2 text-sm text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]",
324
- children: [/* @__PURE__ */ C(b, {
366
+ children: [/* @__PURE__ */ C(v, {
325
367
  size: 16,
326
368
  "aria-hidden": "true"
327
369
  }), D("common.edit", "Edit")]
328
370
  }),
329
- A(l.WORKSPACE_DELETE) && /* @__PURE__ */ w("button", {
371
+ A(c.WORKSPACE_DELETE) && /* @__PURE__ */ w("button", {
330
372
  type: "button",
331
- onClick: () => Z(e.id, e.name),
332
- disabled: K,
373
+ onClick: () => X(e.id, e.name),
374
+ disabled: G,
333
375
  className: "inline-flex min-h-10 items-center gap-2 rounded-lg border border-[var(--color-status-warning-border)] px-3 py-2 text-sm text-[var(--color-status-warning-text)] transition-all duration-200 hover:bg-[var(--color-status-warning-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50",
334
- children: [/* @__PURE__ */ C(x, {
376
+ children: [/* @__PURE__ */ C(y, {
335
377
  size: 16,
336
378
  "aria-hidden": "true"
337
379
  }), D("workspaces.suspend.confirm", "Suspend")]
@@ -339,8 +381,9 @@ function E({ mode: E = "my" } = {}) {
339
381
  ]
340
382
  })]
341
383
  }, e.id))
342
- }), /* @__PURE__ */ C("div", {
343
- className: "hidden overflow-hidden rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-[var(--shadow-elevation-1)] md:block",
384
+ }), /* @__PURE__ */ C(b, {
385
+ treatment: "plain",
386
+ className: "hidden overflow-hidden border-border-seam p-0 md:block",
344
387
  children: /* @__PURE__ */ C("div", {
345
388
  className: "overflow-x-auto",
346
389
  children: /* @__PURE__ */ w("table", {
@@ -351,8 +394,8 @@ function E({ mode: E = "my" } = {}) {
351
394
  /* @__PURE__ */ C("th", {
352
395
  className: "w-12 px-6 py-3 text-left text-xs font-semibold uppercase tracking-wide text-[var(--color-text-secondary)]",
353
396
  children: /* @__PURE__ */ C(i, {
354
- checked: J,
355
- indeterminate: Y,
397
+ checked: q,
398
+ indeterminate: J,
356
399
  onChange: $,
357
400
  ariaLabel: D("workspaces.list.selectAll", "Select all workspaces")
358
401
  })
@@ -375,7 +418,7 @@ function E({ mode: E = "my" } = {}) {
375
418
  })
376
419
  ] })
377
420
  }), /* @__PURE__ */ C("tbody", {
378
- className: "divide-y divide-[var(--color-border-default)]",
421
+ className: "divide-y divide-[var(--color-border-seam)]",
379
422
  children: W.map((e) => /* @__PURE__ */ w("tr", {
380
423
  className: "transition-colors hover:bg-[var(--color-bg-subtle)]",
381
424
  children: [
@@ -399,7 +442,7 @@ function E({ mode: E = "my" } = {}) {
399
442
  }),
400
443
  /* @__PURE__ */ C("td", {
401
444
  className: "px-6 py-4 align-top",
402
- children: /* @__PURE__ */ C(h, { status: e.status })
445
+ children: /* @__PURE__ */ C(m, { status: e.status })
403
446
  }),
404
447
  /* @__PURE__ */ C("td", {
405
448
  className: "px-6 py-4 align-top text-sm text-[var(--color-text-secondary)]",
@@ -416,30 +459,30 @@ function E({ mode: E = "my" } = {}) {
416
459
  className: "rounded-lg p-2 text-[var(--color-text-secondary)] transition-all duration-200 hover:bg-[var(--color-bg-muted)] hover:text-[var(--color-text-primary)]",
417
460
  title: `${D("common.view", "View")} ${e.name}`,
418
461
  "aria-label": `${D("common.view", "View")} ${e.name}`,
419
- children: /* @__PURE__ */ C(v, {
462
+ children: /* @__PURE__ */ C(_, {
420
463
  size: 18,
421
464
  "aria-hidden": "true"
422
465
  })
423
466
  }),
424
- A(l.WORKSPACE_UPDATE) && /* @__PURE__ */ C("button", {
467
+ A(c.WORKSPACE_UPDATE) && /* @__PURE__ */ C("button", {
425
468
  type: "button",
426
469
  onClick: () => O(`${k}/workspaces/${e.id}/edit`),
427
470
  className: "rounded-lg p-2 text-[var(--color-text-secondary)] transition-all duration-200 hover:bg-[var(--color-bg-muted)] hover:text-[var(--color-text-primary)]",
428
471
  title: `${D("common.edit", "Edit")} ${e.name}`,
429
472
  "aria-label": `${D("common.edit", "Edit")} ${e.name}`,
430
- children: /* @__PURE__ */ C(b, {
473
+ children: /* @__PURE__ */ C(v, {
431
474
  size: 18,
432
475
  "aria-hidden": "true"
433
476
  })
434
477
  }),
435
- A(l.WORKSPACE_DELETE) && /* @__PURE__ */ C("button", {
478
+ A(c.WORKSPACE_DELETE) && /* @__PURE__ */ C("button", {
436
479
  type: "button",
437
- onClick: () => Z(e.id, e.name),
438
- disabled: K,
480
+ onClick: () => X(e.id, e.name),
481
+ disabled: G,
439
482
  className: "rounded-lg p-2 text-[var(--color-status-warning-text)] transition-all duration-200 hover:bg-[var(--color-status-warning-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50",
440
483
  title: `${D("workspaces.suspend.confirm", "Suspend")} ${e.name}`,
441
484
  "aria-label": `${D("workspaces.suspend.confirm", "Suspend")} ${e.name}`,
442
- children: /* @__PURE__ */ C(x, {
485
+ children: /* @__PURE__ */ C(y, {
443
486
  size: 18,
444
487
  "aria-hidden": "true"
445
488
  })
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspacesListPage.js","names":[],"sources":["../../../../../src/organization-management/modules/workspaces/pages/WorkspacesListPage.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { Briefcase, Eye, Plus, RefreshCw, SquarePen, Trash2 } from 'lucide-react';\nimport { toast } from 'sonner';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useDeleteWorkspace, useWorkspaces } from '../hooks/useWorkspaces';\nimport { WorkspaceStatusBadge } from '../components/WorkspaceStatusBadge';\nimport { SearchInput } from '../../../shared/components/input/SearchInput';\nimport { SelectionCheckbox } from '../../../shared/components/input/SelectionCheckbox';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { ErrorState } from '../../../shared/components/feedback/ErrorState';\nimport { EmptyState } from '../../../shared/components/feedback/EmptyState';\nimport { useDebouncedValue } from '../../../shared/hooks/useDebouncedValue';\nimport { useConfirmDialog } from '../../../shared/components/dialog/ConfirmDialog';\nimport { PERMISSIONS } from '../../../constants/permissions';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport type { WorkspaceFilterInput } from '../types';\nimport { WorkspaceStatus } from '../types';\nimport {\n isNative,\n nativeConfirm,\n nativeImpact,\n nativeNotify,\n nativeToast,\n} from '../../../../utils/nativeBridge';\n\nfunction formatDate(date: string) {\n return new Date(date).toLocaleDateString();\n}\n\n/**\n * `mode` controls the scope of the listing:\n * - `'my'` — membership-scoped (`myWorkspaces`); the default for user-facing\n * app shells. A regular user only sees workspaces they belong to.\n * - `'admin'` — platform-wide (`allWorkspaces`, super-admin only); the admin app.\n */\nexport interface WorkspacesListPageProps {\n mode?: 'my' | 'admin';\n}\n\nexport function WorkspacesListPage({ mode = 'my' }: WorkspacesListPageProps = {}) {\n const tr = useTr();\n const { navigate, basePath = '/organizations' } = useOrgConsole();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const [searchQuery, setSearchQuery] = useState('');\n const debouncedSearchQuery = useDebouncedValue(searchQuery, 300);\n const [filter, setFilter] = useState<WorkspaceFilterInput>({});\n const [selectedWorkspaceIds, setSelectedWorkspaceIds] = useState<Set<string>>(new Set());\n const { openConfirmDialog, ConfirmDialog } = useConfirmDialog();\n\n // 'my' shells call the self-scoped `myWorkspaces` (no server-side filter arg),\n // so we over-fetch a page and filter client-side below. The admin app keeps\n // the server-filtered, paginated `allWorkspaces`.\n const scope = mode === 'admin' ? 'all' : 'my';\n const {\n workspaces: fetchedWorkspaces,\n loading,\n error,\n refetch,\n } = useWorkspaces(\n { ...filter, search: debouncedSearchQuery || undefined },\n scope === 'my' ? 100 : 20,\n 0,\n scope\n );\n\n const workspaces = useMemo(() => {\n if (scope !== 'my') return fetchedWorkspaces;\n const query = debouncedSearchQuery.trim().toLowerCase();\n return fetchedWorkspaces.filter((workspace) => {\n const matchesSearch =\n !query ||\n workspace.name.toLowerCase().includes(query) ||\n (workspace.slug?.toLowerCase().includes(query) ?? false);\n const matchesStatus = !filter.status || workspace.status === filter.status;\n return matchesSearch && matchesStatus;\n });\n }, [fetchedWorkspaces, scope, debouncedSearchQuery, filter.status]);\n\n const { deleteWorkspace, loading: deleteLoading } = useDeleteWorkspace();\n\n useEffect(() => {\n setSelectedWorkspaceIds((previousSelection) => {\n const visibleIds = new Set(workspaces.map((workspace) => workspace.id));\n const nextSelection = new Set(\n [...previousSelection].filter((workspaceId) => visibleIds.has(workspaceId))\n );\n\n if (nextSelection.size === previousSelection.size) {\n return previousSelection;\n }\n\n return nextSelection;\n });\n }, [workspaces]);\n\n const selectedWorkspaces = useMemo(\n () => workspaces.filter((workspace) => selectedWorkspaceIds.has(workspace.id)),\n [selectedWorkspaceIds, workspaces]\n );\n\n const allVisibleSelected =\n workspaces.length > 0 &&\n workspaces.every((workspace) => selectedWorkspaceIds.has(workspace.id));\n const partiallySelected =\n workspaces.some((workspace) => selectedWorkspaceIds.has(workspace.id)) && !allVisibleSelected;\n\n const executeSuspend = async (workspaceIds: string[]) => {\n try {\n const results = await Promise.allSettled(\n workspaceIds.map(async (workspaceId) => {\n const result = await deleteWorkspace(workspaceId);\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ??\n tr('workspaces.suspend.failed', 'Failed to suspend workspace')\n );\n }\n })\n );\n\n const rejectedResult = results.find((result) => result.status === 'rejected');\n if (rejectedResult?.status === 'rejected') {\n throw rejectedResult.reason;\n }\n\n setSelectedWorkspaceIds(new Set());\n await refetch();\n const successMsg =\n workspaceIds.length === 1\n ? tr('workspaces.suspend.successSingle', 'Workspace suspended successfully')\n : `${workspaceIds.length} ${tr('workspaces.suspend.successMany', 'workspaces suspended successfully')}`;\n toast.success(successMsg);\n void nativeNotify('success');\n if (isNative()) void nativeToast(successMsg);\n } catch (suspendError) {\n const errorMsg =\n suspendError instanceof Error\n ? suspendError.message\n : tr('workspaces.suspend.failed', 'Failed to suspend workspace');\n toast.error(errorMsg);\n void nativeNotify('error');\n if (isNative()) void nativeToast(errorMsg);\n }\n };\n\n const handleDelete = (workspaceId: string, workspaceName: string) => {\n nativeImpact('medium');\n const title = tr('workspaces.suspend.title', 'Suspend workspace');\n const description = `${tr('workspaces.suspend.prefix', 'Suspend')} ${workspaceName}? ${tr(\n 'workspaces.suspend.suffix',\n 'Workspace members will lose access until it is reactivated.'\n )}`;\n void nativeConfirm({\n title,\n message: description,\n okButtonTitle: tr('workspaces.suspend.confirm', 'Suspend'),\n }).then((nativeResult) => {\n if (nativeResult === null) {\n openConfirmDialog({\n title,\n description,\n confirmText: tr('workspaces.suspend.confirm', 'Suspend'),\n variant: 'warning',\n onConfirm: () => {\n void executeSuspend([workspaceId]);\n },\n });\n } else if (nativeResult) {\n void executeSuspend([workspaceId]);\n }\n });\n };\n\n const handleBulkDelete = () => {\n if (selectedWorkspaces.length === 0) return;\n\n openConfirmDialog({\n title: tr('workspaces.suspend.bulkTitle', 'Suspend selected workspaces'),\n description: `${tr('workspaces.suspend.prefix', 'Suspend')} ${selectedWorkspaces.length} ${tr(\n selectedWorkspaces.length === 1\n ? 'workspaces.suspend.bulkSuffixSingle'\n : 'workspaces.suspend.bulkSuffixMany',\n selectedWorkspaces.length === 1 ? 'selected workspace?' : 'selected workspaces?'\n )}`,\n confirmText: `${tr('workspaces.suspend.confirm', 'Suspend')} ${selectedWorkspaces.length}`,\n variant: 'warning',\n onConfirm: () => {\n void executeSuspend(selectedWorkspaces.map((workspace) => workspace.id));\n },\n });\n };\n\n const toggleWorkspaceSelection = (workspaceId: string, checked: boolean) => {\n setSelectedWorkspaceIds((previousSelection) => {\n const nextSelection = new Set(previousSelection);\n if (checked) {\n nextSelection.add(workspaceId);\n } else {\n nextSelection.delete(workspaceId);\n }\n return nextSelection;\n });\n };\n\n const toggleAllWorkspaces = (checked: boolean) => {\n setSelectedWorkspaceIds((previousSelection) => {\n const nextSelection = new Set(previousSelection);\n workspaces.forEach((workspace) => {\n if (checked) {\n nextSelection.add(workspace.id);\n } else {\n nextSelection.delete(workspace.id);\n }\n });\n return nextSelection;\n });\n };\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.WORKSPACE_LIST)) {\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('workspaces.list.noPermission', \"You don't have permission to view workspaces.\")}\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('workspaces.list.loading', 'Loading workspaces...')} />\n </div>\n );\n }\n\n if (error) {\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}\n action={{\n label: tr('common.retry', 'Retry'),\n onClick: () => {\n void refetch();\n },\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 flex w-full max-w-7xl flex-col gap-6\">\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"space-y-2\">\n <h1 className=\"text-3xl font-bold text-[var(--color-text-primary)]\">\n {tr('workspaces.list.title', 'Workspaces')}\n </h1>\n <p className=\"max-w-2xl text-[var(--color-text-secondary)]\">\n {tr(\n 'workspaces.list.subtitle',\n 'Manage organization workspaces, review their status, and open the workspace detail flow.'\n )}\n </p>\n </div>\n\n {hasPermission(PERMISSIONS.WORKSPACE_CREATE) && (\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces/new`)}\n 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\"\n >\n <Plus size={18} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr('workspaces.create.button', 'Create Workspace')}\n </span>\n </button>\n )}\n </div>\n\n <div className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-4 shadow-[var(--shadow-elevation-1)]\">\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-center\">\n <SearchInput\n value={searchQuery}\n onChange={setSearchQuery}\n placeholder={tr('workspaces.list.searchPlaceholder', 'Search workspaces...')}\n label={tr('workspaces.list.searchLabel', 'Search workspaces')}\n inputId=\"workspaces-search\"\n className=\"flex-1\"\n />\n\n <label className=\"flex min-h-11 min-w-[180px] flex-col justify-center rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-sm text-[var(--color-text-secondary)]\">\n <span className=\"sr-only\">\n {tr('workspaces.list.filterByStatus', 'Filter by workspace status')}\n </span>\n <select\n value={filter.status || ''}\n onChange={(event) =>\n setFilter({\n ...filter,\n status: event.target.value\n ? (event.target.value as WorkspaceStatus)\n : undefined,\n })\n }\n className=\"bg-transparent text-[var(--color-text-primary)] focus:outline-none\"\n aria-label={tr('workspaces.list.filterByStatus', 'Filter by workspace status')}\n >\n <option value=\"\">{tr('workspaces.list.allStatuses', 'All statuses')}</option>\n <option value={WorkspaceStatus.ACTIVE}>\n {tr('workspaces.status.active', 'Active')}\n </option>\n <option value={WorkspaceStatus.INACTIVE}>\n {tr('workspaces.status.inactive', 'Inactive')}\n </option>\n <option value={WorkspaceStatus.ARCHIVED}>\n {tr('workspaces.status.archived', 'Archived')}\n </option>\n </select>\n </label>\n\n <button\n type=\"button\"\n onClick={() => {\n void refetch();\n }}\n 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)]\"\n aria-label={tr('workspaces.list.refresh', 'Refresh workspaces')}\n title={tr('workspaces.list.refresh', 'Refresh workspaces')}\n >\n <RefreshCw size={18} aria-hidden=\"true\" />\n </button>\n </div>\n\n {workspaces.length > 0 ? (\n <div className=\"mt-4 flex flex-col gap-3 rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <label className=\"flex items-center gap-2 text-sm text-[var(--color-text-primary)]\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={toggleAllWorkspaces}\n ariaLabel={tr('workspaces.list.selectAll', 'Select all workspaces')}\n />\n <span>{tr('common.selectAllVisible', 'Select all visible')}</span>\n </label>\n\n {selectedWorkspaceIds.size > 0 ? (\n <button\n type=\"button\"\n onClick={() => setSelectedWorkspaceIds(new Set())}\n className=\"text-sm text-[var(--color-text-secondary)] transition-colors hover:text-[var(--color-text-primary)]\"\n >\n {tr('common.clearSelection', 'Clear selection')}\n </button>\n ) : null}\n </div>\n\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center\">\n <span className=\"text-sm text-[var(--color-text-secondary)]\">\n {selectedWorkspaceIds.size} {tr('common.selected', 'selected')}\n </span>\n {hasPermission(PERMISSIONS.WORKSPACE_DELETE) && (\n <button\n type=\"button\"\n onClick={handleBulkDelete}\n disabled={selectedWorkspaces.length === 0 || deleteLoading}\n className=\"inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border border-[var(--color-status-warning-border)] px-3 py-2 text-[var(--color-status-warning-text)] transition-all duration-200 hover:bg-[var(--color-status-warning-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <Trash2 size={16} aria-hidden=\"true\" />\n <span>{tr('workspaces.list.suspendSelected', 'Suspend Selected')}</span>\n {selectedWorkspaces.length > 0 ? (\n <span>({selectedWorkspaces.length})</span>\n ) : null}\n </button>\n )}\n </div>\n </div>\n ) : null}\n </div>\n\n {workspaces.length === 0 ? (\n <div className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-6 shadow-[var(--shadow-elevation-1)]\">\n <EmptyState\n icon={<Briefcase size={40} aria-hidden=\"true\" />}\n title={tr('workspaces.list.emptyNoneTitle', 'No workspaces found')}\n description={\n hasPermission(PERMISSIONS.WORKSPACE_CREATE)\n ? tr(\n 'workspaces.list.emptyNoneDescription',\n 'Create a workspace to start mapping members, organization ownership, and collaboration settings.'\n )\n : tr(\n 'workspaces.list.emptyNoneDescriptionViewer',\n 'No workspaces have been created yet.'\n )\n }\n action={\n hasPermission(PERMISSIONS.WORKSPACE_CREATE)\n ? {\n label: tr('workspaces.create.button', 'Create Workspace'),\n onClick: () => navigate(`${basePath}/workspaces/new`),\n }\n : undefined\n }\n />\n </div>\n ) : (\n <>\n <div className=\"grid gap-4 md:hidden\">\n {workspaces.map((workspace) => (\n <article\n key={workspace.id}\n className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-4 shadow-[var(--shadow-elevation-1)]\"\n >\n <div className=\"flex items-start gap-3\">\n <SelectionCheckbox\n checked={selectedWorkspaceIds.has(workspace.id)}\n onChange={(checked) => toggleWorkspaceSelection(workspace.id, checked)}\n ariaLabel={`${tr('workspaces.list.selectOne', 'Select workspace')} ${workspace.name}`}\n />\n\n <div className=\"min-w-0 flex-1 space-y-3\">\n <div>\n <div className=\"flex flex-wrap items-start gap-2\">\n <h2 className=\"text-base font-semibold text-[var(--color-text-primary)]\">\n {workspace.name}\n </h2>\n <WorkspaceStatusBadge status={workspace.status} />\n </div>\n <p className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-muted)]\">\n /{workspace.slug}\n </p>\n </div>\n\n <dl className=\"grid grid-cols-2 gap-3 text-sm\">\n <div>\n <dt className=\"text-[var(--color-text-secondary)]\">\n {tr('workspaces.list.members', 'Members')}\n </dt>\n <dd className=\"font-medium text-[var(--color-text-primary)]\">\n {workspace.memberCount ?? 0}\n </dd>\n </div>\n <div>\n <dt className=\"text-[var(--color-text-secondary)]\">\n {tr('common.created', 'Created')}\n </dt>\n <dd className=\"font-medium text-[var(--color-text-primary)]\">\n {formatDate(workspace.createdAt)}\n </dd>\n </div>\n </dl>\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-wrap gap-2 border-t border-[var(--color-border-default)] pt-4\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces/${workspace.id}`)}\n className=\"inline-flex min-h-10 items-center gap-2 rounded-lg border border-[var(--color-border-default)] px-3 py-2 text-sm text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]\"\n >\n <Eye size={16} aria-hidden=\"true\" />\n {tr('common.view', 'View')}\n </button>\n {hasPermission(PERMISSIONS.WORKSPACE_UPDATE) && (\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces/${workspace.id}/edit`)}\n className=\"inline-flex min-h-10 items-center gap-2 rounded-lg border border-[var(--color-border-default)] px-3 py-2 text-sm text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]\"\n >\n <SquarePen size={16} aria-hidden=\"true\" />\n {tr('common.edit', 'Edit')}\n </button>\n )}\n {hasPermission(PERMISSIONS.WORKSPACE_DELETE) && (\n <button\n type=\"button\"\n onClick={() => handleDelete(workspace.id, workspace.name)}\n disabled={deleteLoading}\n className=\"inline-flex min-h-10 items-center gap-2 rounded-lg border border-[var(--color-status-warning-border)] px-3 py-2 text-sm text-[var(--color-status-warning-text)] transition-all duration-200 hover:bg-[var(--color-status-warning-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <Trash2 size={16} aria-hidden=\"true\" />\n {tr('workspaces.suspend.confirm', 'Suspend')}\n </button>\n )}\n </div>\n </article>\n ))}\n </div>\n\n <div className=\"hidden overflow-hidden rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-[var(--shadow-elevation-1)] md:block\">\n <div className=\"overflow-x-auto\">\n <table className=\"min-w-full\">\n <thead className=\"bg-[var(--color-bg-subtle)]\">\n <tr>\n <th className=\"w-12 px-6 py-3 text-left text-xs font-semibold uppercase tracking-wide text-[var(--color-text-secondary)]\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={toggleAllWorkspaces}\n ariaLabel={tr('workspaces.list.selectAll', 'Select all workspaces')}\n />\n </th>\n <th className=\"px-6 py-3 text-left text-xs font-semibold uppercase tracking-wide text-[var(--color-text-secondary)]\">\n {tr('workspaces.list.column.workspace', 'Workspace')}\n </th>\n <th className=\"px-6 py-3 text-left text-xs font-semibold uppercase tracking-wide text-[var(--color-text-secondary)]\">\n {tr('common.status', 'Status')}\n </th>\n <th className=\"px-6 py-3 text-left text-xs font-semibold uppercase tracking-wide text-[var(--color-text-secondary)]\">\n {tr('common.created', 'Created')}\n </th>\n <th className=\"px-6 py-3 text-right text-xs font-semibold uppercase tracking-wide text-[var(--color-text-secondary)]\">\n {tr('common.actions', 'Actions')}\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-[var(--color-border-default)]\">\n {workspaces.map((workspace) => (\n <tr\n key={workspace.id}\n className=\"transition-colors hover:bg-[var(--color-bg-subtle)]\"\n >\n <td className=\"px-6 py-4 align-top\">\n <SelectionCheckbox\n checked={selectedWorkspaceIds.has(workspace.id)}\n onChange={(checked) => toggleWorkspaceSelection(workspace.id, checked)}\n ariaLabel={`${tr('workspaces.list.selectOne', 'Select workspace')} ${workspace.name}`}\n />\n </td>\n <td className=\"px-6 py-4\">\n <div>\n <p className=\"font-medium text-[var(--color-text-primary)]\">\n {workspace.name}\n </p>\n <p className=\"break-all font-mono text-sm text-[var(--color-text-muted)]\">\n /{workspace.slug}\n </p>\n </div>\n </td>\n <td className=\"px-6 py-4 align-top\">\n <WorkspaceStatusBadge status={workspace.status} />\n </td>\n <td className=\"px-6 py-4 align-top text-sm text-[var(--color-text-secondary)]\">\n {formatDate(workspace.createdAt)}\n </td>\n <td className=\"px-6 py-4 align-top\">\n <div className=\"flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces/${workspace.id}`)}\n className=\"rounded-lg p-2 text-[var(--color-text-secondary)] transition-all duration-200 hover:bg-[var(--color-bg-muted)] hover:text-[var(--color-text-primary)]\"\n title={`${tr('common.view', 'View')} ${workspace.name}`}\n aria-label={`${tr('common.view', 'View')} ${workspace.name}`}\n >\n <Eye size={18} aria-hidden=\"true\" />\n </button>\n {hasPermission(PERMISSIONS.WORKSPACE_UPDATE) && (\n <button\n type=\"button\"\n onClick={() =>\n navigate(`${basePath}/workspaces/${workspace.id}/edit`)\n }\n className=\"rounded-lg p-2 text-[var(--color-text-secondary)] transition-all duration-200 hover:bg-[var(--color-bg-muted)] hover:text-[var(--color-text-primary)]\"\n title={`${tr('common.edit', 'Edit')} ${workspace.name}`}\n aria-label={`${tr('common.edit', 'Edit')} ${workspace.name}`}\n >\n <SquarePen size={18} aria-hidden=\"true\" />\n </button>\n )}\n {hasPermission(PERMISSIONS.WORKSPACE_DELETE) && (\n <button\n type=\"button\"\n onClick={() => handleDelete(workspace.id, workspace.name)}\n disabled={deleteLoading}\n className=\"rounded-lg p-2 text-[var(--color-status-warning-text)] transition-all duration-200 hover:bg-[var(--color-status-warning-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50\"\n title={`${tr('workspaces.suspend.confirm', 'Suspend')} ${workspace.name}`}\n aria-label={`${tr('workspaces.suspend.confirm', 'Suspend')} ${workspace.name}`}\n >\n <Trash2 size={18} aria-hidden=\"true\" />\n </button>\n )}\n </div>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n </>\n )}\n </div>\n\n {ConfirmDialog}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"WorkspacesListPage.js","names":[],"sources":["../../../../../src/organization-management/modules/workspaces/pages/WorkspacesListPage.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { Briefcase, Eye, Plus, RefreshCw, SquarePen, Trash2 } from 'lucide-react';\nimport { toast } from 'sonner';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useDeleteWorkspace, useWorkspaces } from '../hooks/useWorkspaces';\nimport { WorkspaceStatusBadge } from '../components/WorkspaceStatusBadge';\nimport { SearchInput } from '../../../shared/components/input/SearchInput';\nimport { SelectionCheckbox } from '../../../shared/components/input/SelectionCheckbox';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { ErrorState } from '../../../shared/components/feedback/ErrorState';\nimport { EmptyState } from '../../../shared/components/feedback/EmptyState';\nimport { useDebouncedValue } from '../../../shared/hooks/useDebouncedValue';\nimport { useConfirmDialog } from '../../../shared/components/dialog/ConfirmDialog';\nimport { PERMISSIONS } from '../../../constants/permissions';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport type { WorkspaceFilterInput } from '../types';\nimport { WorkspaceStatus } from '../types';\nimport {\n isNative,\n nativeConfirm,\n nativeImpact,\n nativeNotify,\n nativeToast,\n} from '../../../../utils/nativeBridge';\n\nfunction formatDate(date: string) {\n return new Date(date).toLocaleDateString();\n}\n\n/**\n * `mode` controls the scope of the listing:\n * - `'my'` — membership-scoped (`myWorkspaces`); the default for user-facing\n * app shells. A regular user only sees workspaces they belong to.\n * - `'admin'` — platform-wide (`allWorkspaces`, super-admin only); the admin app.\n */\nexport interface WorkspacesListPageProps {\n mode?: 'my' | 'admin';\n}\n\nexport function WorkspacesListPage({ mode = 'my' }: WorkspacesListPageProps = {}) {\n const tr = useTr();\n const { navigate, basePath = '/organizations' } = useOrgConsole();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const [searchQuery, setSearchQuery] = useState('');\n const debouncedSearchQuery = useDebouncedValue(searchQuery, 300);\n const [filter, setFilter] = useState<WorkspaceFilterInput>({});\n const [selectedWorkspaceIds, setSelectedWorkspaceIds] = useState<Set<string>>(new Set());\n const { openConfirmDialog, ConfirmDialog } = useConfirmDialog();\n\n // 'my' shells call the self-scoped `myWorkspaces` (no server-side filter arg),\n // so we over-fetch a page and filter client-side below. The admin app keeps\n // the server-filtered, paginated `allWorkspaces`.\n const scope = mode === 'admin' ? 'all' : 'my';\n const {\n workspaces: fetchedWorkspaces,\n loading,\n error,\n refetch,\n } = useWorkspaces(\n { ...filter, search: debouncedSearchQuery || undefined },\n scope === 'my' ? 100 : 20,\n 0,\n scope\n );\n\n const workspaces = useMemo(() => {\n if (scope !== 'my') return fetchedWorkspaces;\n const query = debouncedSearchQuery.trim().toLowerCase();\n return fetchedWorkspaces.filter((workspace) => {\n const matchesSearch =\n !query ||\n workspace.name.toLowerCase().includes(query) ||\n (workspace.slug?.toLowerCase().includes(query) ?? false);\n const matchesStatus = !filter.status || workspace.status === filter.status;\n return matchesSearch && matchesStatus;\n });\n }, [fetchedWorkspaces, scope, debouncedSearchQuery, filter.status]);\n\n const { deleteWorkspace, loading: deleteLoading } = useDeleteWorkspace();\n\n useEffect(() => {\n setSelectedWorkspaceIds((previousSelection) => {\n const visibleIds = new Set(workspaces.map((workspace) => workspace.id));\n const nextSelection = new Set(\n [...previousSelection].filter((workspaceId) => visibleIds.has(workspaceId))\n );\n\n if (nextSelection.size === previousSelection.size) {\n return previousSelection;\n }\n\n return nextSelection;\n });\n }, [workspaces]);\n\n const selectedWorkspaces = useMemo(\n () => workspaces.filter((workspace) => selectedWorkspaceIds.has(workspace.id)),\n [selectedWorkspaceIds, workspaces]\n );\n\n const allVisibleSelected =\n workspaces.length > 0 &&\n workspaces.every((workspace) => selectedWorkspaceIds.has(workspace.id));\n const partiallySelected =\n workspaces.some((workspace) => selectedWorkspaceIds.has(workspace.id)) && !allVisibleSelected;\n\n const executeSuspend = async (workspaceIds: string[]) => {\n try {\n const results = await Promise.allSettled(\n workspaceIds.map(async (workspaceId) => {\n const result = await deleteWorkspace(workspaceId);\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ??\n tr('workspaces.suspend.failed', 'Failed to suspend workspace')\n );\n }\n })\n );\n\n const rejectedResult = results.find((result) => result.status === 'rejected');\n if (rejectedResult?.status === 'rejected') {\n throw rejectedResult.reason;\n }\n\n setSelectedWorkspaceIds(new Set());\n await refetch();\n const successMsg =\n workspaceIds.length === 1\n ? tr('workspaces.suspend.successSingle', 'Workspace suspended successfully')\n : `${workspaceIds.length} ${tr('workspaces.suspend.successMany', 'workspaces suspended successfully')}`;\n toast.success(successMsg);\n void nativeNotify('success');\n if (isNative()) void nativeToast(successMsg);\n } catch (suspendError) {\n const errorMsg =\n suspendError instanceof Error\n ? suspendError.message\n : tr('workspaces.suspend.failed', 'Failed to suspend workspace');\n toast.error(errorMsg);\n void nativeNotify('error');\n if (isNative()) void nativeToast(errorMsg);\n }\n };\n\n const handleDelete = (workspaceId: string, workspaceName: string) => {\n nativeImpact('medium');\n const title = tr('workspaces.suspend.title', 'Suspend workspace');\n const description = `${tr('workspaces.suspend.prefix', 'Suspend')} ${workspaceName}? ${tr(\n 'workspaces.suspend.suffix',\n 'Workspace members will lose access until it is reactivated.'\n )}`;\n void nativeConfirm({\n title,\n message: description,\n okButtonTitle: tr('workspaces.suspend.confirm', 'Suspend'),\n }).then((nativeResult) => {\n if (nativeResult === null) {\n openConfirmDialog({\n title,\n description,\n confirmText: tr('workspaces.suspend.confirm', 'Suspend'),\n variant: 'warning',\n onConfirm: () => {\n void executeSuspend([workspaceId]);\n },\n });\n } else if (nativeResult) {\n void executeSuspend([workspaceId]);\n }\n });\n };\n\n const handleBulkDelete = () => {\n if (selectedWorkspaces.length === 0) return;\n\n openConfirmDialog({\n title: tr('workspaces.suspend.bulkTitle', 'Suspend selected workspaces'),\n description: `${tr('workspaces.suspend.prefix', 'Suspend')} ${selectedWorkspaces.length} ${tr(\n selectedWorkspaces.length === 1\n ? 'workspaces.suspend.bulkSuffixSingle'\n : 'workspaces.suspend.bulkSuffixMany',\n selectedWorkspaces.length === 1 ? 'selected workspace?' : 'selected workspaces?'\n )}`,\n confirmText: `${tr('workspaces.suspend.confirm', 'Suspend')} ${selectedWorkspaces.length}`,\n variant: 'warning',\n onConfirm: () => {\n void executeSuspend(selectedWorkspaces.map((workspace) => workspace.id));\n },\n });\n };\n\n const toggleWorkspaceSelection = (workspaceId: string, checked: boolean) => {\n setSelectedWorkspaceIds((previousSelection) => {\n const nextSelection = new Set(previousSelection);\n if (checked) {\n nextSelection.add(workspaceId);\n } else {\n nextSelection.delete(workspaceId);\n }\n return nextSelection;\n });\n };\n\n const toggleAllWorkspaces = (checked: boolean) => {\n setSelectedWorkspaceIds((previousSelection) => {\n const nextSelection = new Set(previousSelection);\n workspaces.forEach((workspace) => {\n if (checked) {\n nextSelection.add(workspace.id);\n } else {\n nextSelection.delete(workspace.id);\n }\n });\n return nextSelection;\n });\n };\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.WORKSPACE_LIST)) {\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('workspaces.list.noPermission', \"You don't have permission to view workspaces.\")}\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('workspaces.list.loading', 'Loading workspaces...')} />\n </div>\n );\n }\n\n if (error) {\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}\n action={{\n label: tr('common.retry', 'Retry'),\n onClick: () => {\n void refetch();\n },\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 flex w-full max-w-7xl flex-col gap-6\">\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"space-y-2\">\n <h1 className=\"text-3xl font-bold text-[var(--color-text-primary)]\">\n {tr('workspaces.list.title', 'Workspaces')}\n </h1>\n <p className=\"max-w-2xl text-[var(--color-text-secondary)]\">\n {tr(\n 'workspaces.list.subtitle',\n 'Manage organization workspaces, review their status, and open the workspace detail flow.'\n )}\n </p>\n </div>\n\n {hasPermission(PERMISSIONS.WORKSPACE_CREATE) && (\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces/new`)}\n 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\"\n >\n <Plus size={18} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr('workspaces.create.button', 'Create Workspace')}\n </span>\n </button>\n )}\n </div>\n\n {fetchedWorkspaces.length > 0 ? (\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">\n {tr('workspaces.list.title', 'Workspaces')}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {fetchedWorkspaces.length}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">\n {tr('workspaces.status.active', 'Active')}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {fetchedWorkspaces.filter((w) => w.status === WorkspaceStatus.ACTIVE).length}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"col-span-2 p-4 sm:col-span-1\">\n <p className=\"text-sm text-text-secondary\">\n {tr('workspaces.list.members', 'Members')}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {fetchedWorkspaces.reduce((sum, w) => sum + (w.memberCount ?? 0), 0)}\n </p>\n </GlassCard>\n </div>\n ) : null}\n\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-4\">\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-center\">\n <SearchInput\n value={searchQuery}\n onChange={setSearchQuery}\n placeholder={tr('workspaces.list.searchPlaceholder', 'Search workspaces...')}\n label={tr('workspaces.list.searchLabel', 'Search workspaces')}\n inputId=\"workspaces-search\"\n className=\"flex-1\"\n />\n\n <label className=\"flex min-h-11 min-w-[180px] flex-col justify-center rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-sm text-[var(--color-text-secondary)]\">\n <span className=\"sr-only\">\n {tr('workspaces.list.filterByStatus', 'Filter by workspace status')}\n </span>\n <select\n value={filter.status || ''}\n onChange={(event) =>\n setFilter({\n ...filter,\n status: event.target.value\n ? (event.target.value as WorkspaceStatus)\n : undefined,\n })\n }\n className=\"bg-transparent text-[var(--color-text-primary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n aria-label={tr('workspaces.list.filterByStatus', 'Filter by workspace status')}\n >\n <option value=\"\">{tr('workspaces.list.allStatuses', 'All statuses')}</option>\n <option value={WorkspaceStatus.ACTIVE}>\n {tr('workspaces.status.active', 'Active')}\n </option>\n <option value={WorkspaceStatus.INACTIVE}>\n {tr('workspaces.status.inactive', 'Inactive')}\n </option>\n <option value={WorkspaceStatus.ARCHIVED}>\n {tr('workspaces.status.archived', 'Archived')}\n </option>\n </select>\n </label>\n\n <button\n type=\"button\"\n onClick={() => {\n void refetch();\n }}\n 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)]\"\n aria-label={tr('workspaces.list.refresh', 'Refresh workspaces')}\n title={tr('workspaces.list.refresh', 'Refresh workspaces')}\n >\n <RefreshCw size={18} aria-hidden=\"true\" />\n </button>\n </div>\n\n {workspaces.length > 0 ? (\n <div className=\"mt-4 flex flex-col gap-3 rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <label className=\"flex items-center gap-2 text-sm text-[var(--color-text-primary)]\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={toggleAllWorkspaces}\n ariaLabel={tr('workspaces.list.selectAll', 'Select all workspaces')}\n />\n <span>{tr('common.selectAllVisible', 'Select all visible')}</span>\n </label>\n\n {selectedWorkspaceIds.size > 0 ? (\n <button\n type=\"button\"\n onClick={() => setSelectedWorkspaceIds(new Set())}\n className=\"text-sm text-[var(--color-text-secondary)] transition-colors hover:text-[var(--color-text-primary)]\"\n >\n {tr('common.clearSelection', 'Clear selection')}\n </button>\n ) : null}\n </div>\n\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center\">\n <span className=\"text-sm text-[var(--color-text-secondary)]\">\n {selectedWorkspaceIds.size} {tr('common.selected', 'selected')}\n </span>\n {hasPermission(PERMISSIONS.WORKSPACE_DELETE) && (\n <button\n type=\"button\"\n onClick={handleBulkDelete}\n disabled={selectedWorkspaces.length === 0 || deleteLoading}\n className=\"inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border border-[var(--color-status-warning-border)] px-3 py-2 text-[var(--color-status-warning-text)] transition-all duration-200 hover:bg-[var(--color-status-warning-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <Trash2 size={16} aria-hidden=\"true\" />\n <span>{tr('workspaces.list.suspendSelected', 'Suspend Selected')}</span>\n {selectedWorkspaces.length > 0 ? (\n <span>({selectedWorkspaces.length})</span>\n ) : null}\n </button>\n )}\n </div>\n </div>\n ) : null}\n </GlassCard>\n\n {workspaces.length === 0 ? (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-6\">\n <EmptyState\n icon={<Briefcase size={40} aria-hidden=\"true\" />}\n title={tr('workspaces.list.emptyNoneTitle', 'No workspaces found')}\n description={\n hasPermission(PERMISSIONS.WORKSPACE_CREATE)\n ? tr(\n 'workspaces.list.emptyNoneDescription',\n 'Create a workspace to start mapping members, organization ownership, and collaboration settings.'\n )\n : tr(\n 'workspaces.list.emptyNoneDescriptionViewer',\n 'No workspaces have been created yet.'\n )\n }\n action={\n hasPermission(PERMISSIONS.WORKSPACE_CREATE)\n ? {\n label: tr('workspaces.create.button', 'Create Workspace'),\n onClick: () => navigate(`${basePath}/workspaces/new`),\n }\n : undefined\n }\n />\n </GlassCard>\n ) : (\n <>\n <div className=\"grid gap-4 md:hidden\">\n {workspaces.map((workspace) => (\n <GlassCard\n key={workspace.id}\n treatment=\"insight\"\n className=\"border-border-seam p-4\"\n >\n <div className=\"flex items-start gap-3\">\n <SelectionCheckbox\n checked={selectedWorkspaceIds.has(workspace.id)}\n onChange={(checked) => toggleWorkspaceSelection(workspace.id, checked)}\n ariaLabel={`${tr('workspaces.list.selectOne', 'Select workspace')} ${workspace.name}`}\n />\n\n <div className=\"min-w-0 flex-1 space-y-3\">\n <div>\n <div className=\"flex flex-wrap items-start gap-2\">\n <h2 className=\"text-base font-semibold text-[var(--color-text-primary)]\">\n {workspace.name}\n </h2>\n <WorkspaceStatusBadge status={workspace.status} />\n </div>\n <p className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-muted)]\">\n /{workspace.slug}\n </p>\n </div>\n\n <dl className=\"grid grid-cols-2 gap-3 text-sm\">\n <div>\n <dt className=\"text-[var(--color-text-secondary)]\">\n {tr('workspaces.list.members', 'Members')}\n </dt>\n <dd className=\"font-medium text-[var(--color-text-primary)]\">\n {workspace.memberCount ?? 0}\n </dd>\n </div>\n <div>\n <dt className=\"text-[var(--color-text-secondary)]\">\n {tr('common.created', 'Created')}\n </dt>\n <dd className=\"font-medium text-[var(--color-text-primary)]\">\n {formatDate(workspace.createdAt)}\n </dd>\n </div>\n </dl>\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-wrap gap-2 border-t border-[var(--color-border-default)] pt-4\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces/${workspace.id}`)}\n className=\"inline-flex min-h-10 items-center gap-2 rounded-lg border border-[var(--color-border-default)] px-3 py-2 text-sm text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]\"\n >\n <Eye size={16} aria-hidden=\"true\" />\n {tr('common.view', 'View')}\n </button>\n {hasPermission(PERMISSIONS.WORKSPACE_UPDATE) && (\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces/${workspace.id}/edit`)}\n className=\"inline-flex min-h-10 items-center gap-2 rounded-lg border border-[var(--color-border-default)] px-3 py-2 text-sm text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]\"\n >\n <SquarePen size={16} aria-hidden=\"true\" />\n {tr('common.edit', 'Edit')}\n </button>\n )}\n {hasPermission(PERMISSIONS.WORKSPACE_DELETE) && (\n <button\n type=\"button\"\n onClick={() => handleDelete(workspace.id, workspace.name)}\n disabled={deleteLoading}\n className=\"inline-flex min-h-10 items-center gap-2 rounded-lg border border-[var(--color-status-warning-border)] px-3 py-2 text-sm text-[var(--color-status-warning-text)] transition-all duration-200 hover:bg-[var(--color-status-warning-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <Trash2 size={16} aria-hidden=\"true\" />\n {tr('workspaces.suspend.confirm', 'Suspend')}\n </button>\n )}\n </div>\n </GlassCard>\n ))}\n </div>\n\n <GlassCard\n treatment=\"plain\"\n className=\"hidden overflow-hidden border-border-seam p-0 md:block\"\n >\n <div className=\"overflow-x-auto\">\n <table className=\"min-w-full\">\n <thead className=\"bg-[var(--color-bg-subtle)]\">\n <tr>\n <th className=\"w-12 px-6 py-3 text-left text-xs font-semibold uppercase tracking-wide text-[var(--color-text-secondary)]\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={toggleAllWorkspaces}\n ariaLabel={tr('workspaces.list.selectAll', 'Select all workspaces')}\n />\n </th>\n <th className=\"px-6 py-3 text-left text-xs font-semibold uppercase tracking-wide text-[var(--color-text-secondary)]\">\n {tr('workspaces.list.column.workspace', 'Workspace')}\n </th>\n <th className=\"px-6 py-3 text-left text-xs font-semibold uppercase tracking-wide text-[var(--color-text-secondary)]\">\n {tr('common.status', 'Status')}\n </th>\n <th className=\"px-6 py-3 text-left text-xs font-semibold uppercase tracking-wide text-[var(--color-text-secondary)]\">\n {tr('common.created', 'Created')}\n </th>\n <th className=\"px-6 py-3 text-right text-xs font-semibold uppercase tracking-wide text-[var(--color-text-secondary)]\">\n {tr('common.actions', 'Actions')}\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-[var(--color-border-seam)]\">\n {workspaces.map((workspace) => (\n <tr\n key={workspace.id}\n className=\"transition-colors hover:bg-[var(--color-bg-subtle)]\"\n >\n <td className=\"px-6 py-4 align-top\">\n <SelectionCheckbox\n checked={selectedWorkspaceIds.has(workspace.id)}\n onChange={(checked) => toggleWorkspaceSelection(workspace.id, checked)}\n ariaLabel={`${tr('workspaces.list.selectOne', 'Select workspace')} ${workspace.name}`}\n />\n </td>\n <td className=\"px-6 py-4\">\n <div>\n <p className=\"font-medium text-[var(--color-text-primary)]\">\n {workspace.name}\n </p>\n <p className=\"break-all font-mono text-sm text-[var(--color-text-muted)]\">\n /{workspace.slug}\n </p>\n </div>\n </td>\n <td className=\"px-6 py-4 align-top\">\n <WorkspaceStatusBadge status={workspace.status} />\n </td>\n <td className=\"px-6 py-4 align-top text-sm text-[var(--color-text-secondary)]\">\n {formatDate(workspace.createdAt)}\n </td>\n <td className=\"px-6 py-4 align-top\">\n <div className=\"flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces/${workspace.id}`)}\n className=\"rounded-lg p-2 text-[var(--color-text-secondary)] transition-all duration-200 hover:bg-[var(--color-bg-muted)] hover:text-[var(--color-text-primary)]\"\n title={`${tr('common.view', 'View')} ${workspace.name}`}\n aria-label={`${tr('common.view', 'View')} ${workspace.name}`}\n >\n <Eye size={18} aria-hidden=\"true\" />\n </button>\n {hasPermission(PERMISSIONS.WORKSPACE_UPDATE) && (\n <button\n type=\"button\"\n onClick={() =>\n navigate(`${basePath}/workspaces/${workspace.id}/edit`)\n }\n className=\"rounded-lg p-2 text-[var(--color-text-secondary)] transition-all duration-200 hover:bg-[var(--color-bg-muted)] hover:text-[var(--color-text-primary)]\"\n title={`${tr('common.edit', 'Edit')} ${workspace.name}`}\n aria-label={`${tr('common.edit', 'Edit')} ${workspace.name}`}\n >\n <SquarePen size={18} aria-hidden=\"true\" />\n </button>\n )}\n {hasPermission(PERMISSIONS.WORKSPACE_DELETE) && (\n <button\n type=\"button\"\n onClick={() => handleDelete(workspace.id, workspace.name)}\n disabled={deleteLoading}\n className=\"rounded-lg p-2 text-[var(--color-status-warning-text)] transition-all duration-200 hover:bg-[var(--color-status-warning-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50\"\n title={`${tr('workspaces.suspend.confirm', 'Suspend')} ${workspace.name}`}\n aria-label={`${tr('workspaces.suspend.confirm', 'Suspend')} ${workspace.name}`}\n >\n <Trash2 size={18} aria-hidden=\"true\" />\n </button>\n )}\n </div>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </GlassCard>\n </>\n )}\n </div>\n\n {ConfirmDialog}\n </div>\n );\n}\n"],"mappings":"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"}